bc_components/encrypted_key/
key_derivation_params.rs1use dcbor::prelude::*;
2
3#[cfg(feature = "ssh-agent")]
4use super::SSHAgentParams;
5use super::{
6 Argon2idParams, HKDFParams, KeyDerivation, KeyDerivationMethod,
7 PBKDF2Params, ScryptParams,
8};
9use crate::{EncryptedMessage, Result, SymmetricKey};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
13pub enum KeyDerivationParams {
14 HKDF(HKDFParams),
15 PBKDF2(PBKDF2Params),
16 Scrypt(ScryptParams),
17 Argon2id(Argon2idParams),
18 #[cfg(feature = "ssh-agent")]
19 SSHAgent(SSHAgentParams),
20}
21
22impl KeyDerivationParams {
23 pub fn method(&self) -> KeyDerivationMethod {
25 match self {
26 KeyDerivationParams::HKDF(_) => KeyDerivationMethod::HKDF,
27 KeyDerivationParams::PBKDF2(_) => KeyDerivationMethod::PBKDF2,
28 KeyDerivationParams::Scrypt(_) => KeyDerivationMethod::Scrypt,
29 KeyDerivationParams::Argon2id(_) => KeyDerivationMethod::Argon2id,
30 #[cfg(feature = "ssh-agent")]
31 KeyDerivationParams::SSHAgent(_) => KeyDerivationMethod::SSHAgent,
32 }
33 }
34
35 pub fn is_password_based(&self) -> bool {
36 matches!(
37 self,
38 KeyDerivationParams::PBKDF2(_)
39 | KeyDerivationParams::Scrypt(_)
40 | KeyDerivationParams::Argon2id(_)
41 )
42 }
43
44 pub fn is_ssh_agent(&self) -> bool {
45 #[cfg(feature = "ssh-agent")]
46 {
47 matches!(self, KeyDerivationParams::SSHAgent(_))
48 }
49 #[cfg(not(feature = "ssh-agent"))]
50 {
51 false
52 }
53 }
54
55 pub fn lock(
56 &mut self,
57 content_key: &SymmetricKey,
58 secret: impl AsRef<[u8]>,
59 ) -> Result<EncryptedMessage> {
60 match self {
61 KeyDerivationParams::HKDF(params) => {
62 params.lock(content_key, secret)
63 }
64 KeyDerivationParams::PBKDF2(params) => {
65 params.lock(content_key, secret)
66 }
67 KeyDerivationParams::Scrypt(params) => {
68 params.lock(content_key, secret)
69 }
70 KeyDerivationParams::Argon2id(params) => {
71 params.lock(content_key, secret)
72 }
73 #[cfg(feature = "ssh-agent")]
74 KeyDerivationParams::SSHAgent(params) => {
75 params.lock(content_key, secret)
76 }
77 }
78 }
79}
80
81impl std::fmt::Display for KeyDerivationParams {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 match self {
84 KeyDerivationParams::HKDF(params) => write!(f, "{}", params),
85 KeyDerivationParams::PBKDF2(params) => write!(f, "{}", params),
86 KeyDerivationParams::Scrypt(params) => write!(f, "{}", params),
87 KeyDerivationParams::Argon2id(params) => write!(f, "{}", params),
88 #[cfg(feature = "ssh-agent")]
89 KeyDerivationParams::SSHAgent(params) => write!(f, "{}", params),
90 }
91 }
92}
93
94impl From<KeyDerivationParams> for CBOR {
95 fn from(value: KeyDerivationParams) -> Self {
96 match value {
97 KeyDerivationParams::HKDF(params) => params.into(),
98 KeyDerivationParams::PBKDF2(params) => params.into(),
99 KeyDerivationParams::Scrypt(params) => params.into(),
100 KeyDerivationParams::Argon2id(params) => params.into(),
101 #[cfg(feature = "ssh-agent")]
102 KeyDerivationParams::SSHAgent(params) => params.into(),
103 }
104 }
105}
106
107impl TryFrom<CBOR> for KeyDerivationParams {
108 type Error = dcbor::Error;
109
110 fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
111 let a = cbor.clone().try_into_array()?;
112 let mut iter = a.into_iter();
113 let index: usize = iter
114 .next()
115 .ok_or_else(|| dcbor::Error::msg("Missing index"))?
116 .try_into()?;
117 match KeyDerivationMethod::from_index(index) {
118 Some(KeyDerivationMethod::HKDF) => {
119 Ok(KeyDerivationParams::HKDF(HKDFParams::try_from(cbor)?))
120 }
121 Some(KeyDerivationMethod::PBKDF2) => {
122 Ok(KeyDerivationParams::PBKDF2(PBKDF2Params::try_from(cbor)?))
123 }
124 Some(KeyDerivationMethod::Scrypt) => {
125 Ok(KeyDerivationParams::Scrypt(ScryptParams::try_from(cbor)?))
126 }
127 Some(KeyDerivationMethod::Argon2id) => Ok(
128 KeyDerivationParams::Argon2id(Argon2idParams::try_from(cbor)?),
129 ),
130 #[cfg(feature = "ssh-agent")]
131 Some(KeyDerivationMethod::SSHAgent) => Ok(
132 KeyDerivationParams::SSHAgent(SSHAgentParams::try_from(cbor)?),
133 ),
134 None => Err(dcbor::Error::msg("Invalid KeyDerivationMethod")),
135 }
136 }
137}