use base64::{Engine as _, engine::general_purpose::STANDARD as BASE64_STD_ENGINE};
use tracing::warn;
use zeroize::Zeroizing;
use crate::{
cosign::SignatureLayer,
crypto::{SigStoreSigner, SigningScheme, signing_key::SigStoreKeyPair},
errors::{Result, SigstoreError},
};
use super::Constraint;
#[derive(Debug)]
pub struct PrivateKeySigner {
key: SigStoreSigner,
}
impl PrivateKeySigner {
pub fn new_with_raw(
key_raw: Zeroizing<Vec<u8>>,
password: Zeroizing<Vec<u8>>,
signing_scheme: &SigningScheme,
) -> Result<Self> {
let signer = match password.is_empty() {
true => SigStoreKeyPair::from_pem(&key_raw),
false => SigStoreKeyPair::from_encrypted_pem(&key_raw, &password),
}
.map_err(|e| SigstoreError::ApplyConstraintError(e.to_string()))?
.to_sigstore_signer(signing_scheme)
.map_err(|e| SigstoreError::ApplyConstraintError(e.to_string()))?;
Ok(Self { key: signer })
}
pub fn new_with_signer(signer: SigStoreSigner) -> Self {
Self { key: signer }
}
}
impl Constraint for PrivateKeySigner {
fn add_constraint(&self, signature_layer: &mut SignatureLayer) -> Result<bool> {
if signature_layer.signature.is_some() {
warn!(signature = ?signature_layer.signature, "already has signature");
return Ok(false);
}
signature_layer.raw_data = serde_json::to_vec(&signature_layer.simple_signing)?;
let sig = self.key.sign(&signature_layer.raw_data)?;
let sig_base64 = BASE64_STD_ENGINE.encode(sig);
signature_layer.signature = Some(sig_base64);
Ok(true)
}
}