cmail_rpgp/composed/message/
decrypt.rs1use log::debug;
2use zeroize::{Zeroize, ZeroizeOnDrop};
3
4use crate::crypto::sym::SymmetricKeyAlgorithm;
5use crate::errors::Result;
6use crate::packet::SymKeyEncryptedSessionKey;
7use crate::types::{EskType, PkeskBytes, SecretKeyRepr, SecretKeyTrait, SkeskVersion};
8
9pub fn decrypt_session_key<F, L>(
11 locked_key: &L,
12 key_pw: F,
13 values: &PkeskBytes,
14 typ: EskType,
15) -> Result<PlainSessionKey>
16where
17 F: FnOnce() -> String,
18 L: SecretKeyTrait<Unlocked = SecretKeyRepr>,
19{
20 debug!("decrypt session key");
21
22 locked_key.unlock(key_pw, |priv_key| priv_key.decrypt(values, typ, locked_key))
23}
24
25#[derive(derive_more::Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
36pub enum PlainSessionKey {
37 V3_4 {
41 sym_alg: SymmetricKeyAlgorithm,
42 #[debug("..")]
43 key: Vec<u8>,
44 },
45
46 V5 {
47 #[debug("..")]
48 key: Vec<u8>,
49 },
50
51 V6 {
53 #[debug("..")]
54 key: Vec<u8>,
55 },
56}
57
58pub fn decrypt_session_key_with_password<F>(
63 packet: &SymKeyEncryptedSessionKey,
64 msg_pw: F,
65) -> Result<PlainSessionKey>
66where
67 F: FnOnce() -> String,
68{
69 debug!("decrypt session key with password");
70
71 let packet_algorithm = packet.sym_algorithm();
72 ensure!(
73 packet_algorithm != SymmetricKeyAlgorithm::Plaintext,
74 "SKESK packet encryption algorithm cannot be plaintext"
75 );
76
77 if packet.version() == SkeskVersion::V6 {
82 ensure!(
83 !packet.s2k().known_weak_hash_algo(),
84 "Weak hash algorithm in S2K not allowed for v6 {:?}",
85 packet.s2k()
86 )
87 }
88
89 let key = packet
90 .s2k()
91 .derive_key(&msg_pw(), packet_algorithm.key_size())?;
92
93 debug!("derived key: {}", hex::encode(&key));
94 if packet.encrypted_key().is_none() {
95 return Ok(PlainSessionKey::V3_4 {
99 key,
100 sym_alg: packet_algorithm,
101 });
102 }
103
104 let decrypted_key = packet.decrypt(&key)?;
105
106 Ok(decrypted_key)
107}