use pgp::composed::{Deserializable, DetachedSignature, SignedSecretKey};
use pgp::types::Password;
use super::errors::CryptoError;
use super::messages;
#[derive(Clone)]
pub struct PrivateKey {
key: SignedSecretKey,
passphrase: Vec<u8>,
}
impl PrivateKey {
pub fn from_armored(armored: &str, passphrase: &[u8]) -> Result<Self, CryptoError> {
let (key, _headers) = SignedSecretKey::from_string(armored)
.map_err(|e| CryptoError::Parse(format!("secret key: {e}")))?;
let password = password_from_bytes(passphrase);
key.unlock(&password, |_, _| Ok(()))
.map_err(|e| CryptoError::Unlock(e.to_string()))?
.map_err(|e| CryptoError::Unlock(e.to_string()))?;
Ok(Self {
key,
passphrase: passphrase.to_vec(),
})
}
pub fn decrypt_armored_message(&self, armored: &str) -> Result<Vec<u8>, CryptoError> {
messages::decrypt_armored(armored, &self.key, &self.password())
}
pub fn decrypt_binary_message(&self, ciphertext: &[u8]) -> Result<Vec<u8>, CryptoError> {
messages::decrypt_binary(ciphertext, &self.key, &self.password())
}
pub fn decrypt_armored_verify(
&self,
armored: &str,
ring: &super::VerificationKeyRing,
) -> Result<(Vec<u8>, super::VerificationStatus), CryptoError> {
super::verify::decrypt_and_verify(armored, &self.key, &self.password(), ring)
}
pub(crate) fn signed_public_key(&self) -> pgp::composed::SignedPublicKey {
self.key.to_public_key()
}
pub fn verify_detached_signature(
&self,
armored_sig: &str,
data: &[u8],
) -> Result<(), CryptoError> {
let (sig, _headers) = DetachedSignature::from_string(armored_sig)
.map_err(|e| CryptoError::Parse(format!("detached signature: {e}")))?;
sig.verify(&self.key.to_public_key(), data)
.map_err(|e| CryptoError::Verification(e.to_string()))
}
pub fn encrypt_and_sign(
&self,
signer: &PrivateKey,
data: &[u8],
text: bool,
compress: bool,
) -> Result<String, CryptoError> {
super::encrypt::encrypt_and_sign(&self.key, Some(signer), data, text, compress)
}
pub fn encrypt(&self, data: &[u8]) -> Result<String, CryptoError> {
super::encrypt::encrypt_and_sign(&self.key, None, data, false, false)
}
pub fn sign_detached(&self, data: &[u8]) -> Result<String, CryptoError> {
super::encrypt::sign_detached(self, data)
}
pub(crate) fn key(&self) -> &SignedSecretKey {
&self.key
}
pub(crate) fn password(&self) -> Password {
password_from_bytes(&self.passphrase)
}
}
pub fn decrypt_armored_with_keys(
armored: &str,
keys: &[PrivateKey],
) -> Result<Vec<u8>, CryptoError> {
let owned: Vec<(&SignedSecretKey, Password)> =
keys.iter().map(|k| (k.key(), k.password())).collect();
let refs: Vec<(&SignedSecretKey, &Password)> = owned.iter().map(|(k, p)| (*k, p)).collect();
messages::decrypt_armored_any(armored, &refs)
}
pub(crate) fn password_from_bytes(bytes: &[u8]) -> Password {
Password::from(bytes)
}