use log::debug;
use zeroize::{Zeroize, ZeroizeOnDrop};
use crate::crypto::sym::SymmetricKeyAlgorithm;
use crate::errors::Result;
use crate::packet::SymKeyEncryptedSessionKey;
use crate::types::{EskType, PkeskBytes, SecretKeyRepr, SecretKeyTrait, SkeskVersion};
pub fn decrypt_session_key<F, L>(
locked_key: &L,
key_pw: F,
values: &PkeskBytes,
typ: EskType,
) -> Result<PlainSessionKey>
where
F: FnOnce() -> String,
L: SecretKeyTrait<Unlocked = SecretKeyRepr>,
{
debug!("decrypt session key");
locked_key.unlock(key_pw, |priv_key| priv_key.decrypt(values, typ, locked_key))
}
#[derive(derive_more::Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
pub enum PlainSessionKey {
V3_4 {
sym_alg: SymmetricKeyAlgorithm,
#[debug("..")]
key: Vec<u8>,
},
V5 {
#[debug("..")]
key: Vec<u8>,
},
V6 {
#[debug("..")]
key: Vec<u8>,
},
}
pub fn decrypt_session_key_with_password<F>(
packet: &SymKeyEncryptedSessionKey,
msg_pw: F,
) -> Result<PlainSessionKey>
where
F: FnOnce() -> String,
{
debug!("decrypt session key with password");
let packet_algorithm = packet.sym_algorithm();
ensure!(
packet_algorithm != SymmetricKeyAlgorithm::Plaintext,
"SKESK packet encryption algorithm cannot be plaintext"
);
if packet.version() == SkeskVersion::V6 {
ensure!(
!packet.s2k().known_weak_hash_algo(),
"Weak hash algorithm in S2K not allowed for v6 {:?}",
packet.s2k()
)
}
let key = packet
.s2k()
.derive_key(&msg_pw(), packet_algorithm.key_size())?;
debug!("derived key: {}", hex::encode(&key));
if packet.encrypted_key().is_none() {
return Ok(PlainSessionKey::V3_4 {
key,
sym_alg: packet_algorithm,
});
}
let decrypted_key = packet.decrypt(&key)?;
Ok(decrypted_key)
}