devolutions_crypto/key_derivation/
key_derivation_v1.rs1use std::convert::TryFrom;
3use std::io::{Cursor, Read, Write};
4
5use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
6use zeroize::Zeroizing;
7
8use rand::TryRng;
9
10use crate::key::{secret_key_from_raw, SecretKey};
11use crate::utils::derive_key_pbkdf2;
12use crate::{Error, Header, KeyDerivationVersion, Result, DEFAULT_PBKDF2_ITERATIONS};
13
14use super::{DerivationParameters, DerivationParametersPayload};
15
16pub const KEY_LENGTH: usize = 32;
17
18#[derive(Clone, Debug)]
19pub struct KeyDerivationV1 {
20 pub iterations: u32,
21 pub salt: Vec<u8>,
22}
23
24impl KeyDerivationV1 {
25 pub fn derive(&self, key: &[u8]) -> Zeroizing<Vec<u8>> {
26 Zeroizing::new(derive_key_pbkdf2(
27 key,
28 &self.salt,
29 self.iterations,
30 KEY_LENGTH,
31 ))
32 }
33}
34
35impl From<&KeyDerivationV1> for Vec<u8> {
36 fn from(params: &KeyDerivationV1) -> Self {
37 let mut data = Vec::with_capacity(8 + params.salt.len());
38 data.write_u32::<LittleEndian>(params.iterations).unwrap();
39 data.write_u32::<LittleEndian>(params.salt.len() as u32)
40 .unwrap();
41 data.write_all(¶ms.salt).unwrap();
42 data
43 }
44}
45
46impl TryFrom<&[u8]> for KeyDerivationV1 {
47 type Error = Error;
48
49 fn try_from(data: &[u8]) -> Result<Self> {
50 let mut cursor = Cursor::new(data);
51 let iterations = cursor.read_u32::<LittleEndian>()?;
52 let salt_len = cursor.read_u32::<LittleEndian>()? as usize;
53 let remaining = data.len() - (cursor.position() as usize);
54
55 if remaining < salt_len {
56 return Err(Error::InvalidLength);
57 }
58
59 let mut salt = vec![0u8; salt_len];
60 cursor.read_exact(&mut salt)?;
61 Ok(KeyDerivationV1 { iterations, salt })
62 }
63}
64
65pub struct Pbkdf2 {
69 iterations: u32,
70}
71
72impl Pbkdf2 {
73 pub fn new() -> Self {
75 Self {
76 iterations: DEFAULT_PBKDF2_ITERATIONS,
77 }
78 }
79
80 pub fn with_params(iterations: u32) -> Self {
83 Self { iterations }
84 }
85
86 pub fn derive(&self, key: &[u8]) -> Result<(SecretKey, DerivationParameters)> {
88 let mut salt = vec![0u8; 16];
89 rand::rngs::SysRng
90 .try_fill_bytes(&mut salt)
91 .map_err(|_| Error::RandomError)?;
92 self.derive_with_salt(key, &salt)
93 }
94
95 pub fn derive_with_salt(
97 &self,
98 key: &[u8],
99 salt: &[u8],
100 ) -> Result<(SecretKey, DerivationParameters)> {
101 let params = KeyDerivationV1 {
102 iterations: self.iterations,
103 salt: salt.to_vec(),
104 };
105 let raw = params.derive(key);
106 let secret_key = secret_key_from_raw(raw)?;
107
108 let mut header: Header<DerivationParameters> = Header::default();
109 header.version = KeyDerivationVersion::V1;
110
111 let derivation_params = DerivationParameters {
112 header,
113 payload: DerivationParametersPayload::V1(params),
114 };
115
116 Ok((secret_key, derivation_params))
117 }
118
119 pub fn parameters(self) -> Result<DerivationParameters> {
123 let mut salt = vec![0u8; 16];
124 rand::rngs::SysRng
125 .try_fill_bytes(&mut salt)
126 .map_err(|_| Error::RandomError)?;
127 let v1 = KeyDerivationV1 {
128 iterations: self.iterations,
129 salt,
130 };
131 let mut header: Header<DerivationParameters> = Header::default();
132 header.version = KeyDerivationVersion::V1;
133 Ok(DerivationParameters {
134 header,
135 payload: DerivationParametersPayload::V1(v1),
136 })
137 }
138}
139
140impl Default for Pbkdf2 {
141 fn default() -> Self {
142 Self::new()
143 }
144}