hashtree_core/
encryption.rs1use crate::crypto::{self, CryptoError, EncryptionKey};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
7pub enum EncryptionMode {
8 LegacyChk,
9 #[default]
10 ChkV1,
11 RndV1,
12}
13
14#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16pub struct ObjectKey {
17 bytes: [u8; 33],
18 length: u8,
19}
20
21impl std::fmt::Debug for ObjectKey {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 f.debug_struct("ObjectKey")
24 .field("mode", &self.mode())
25 .finish_non_exhaustive()
26 }
27}
28
29impl ObjectKey {
30 pub fn from_bytes(bytes: &[u8]) -> Result<Self, CryptoError> {
31 match bytes.len() {
32 32 => {}
33 33 if matches!(bytes[0], 1 | 2) => {}
34 33 => return Err(CryptoError::UnsupportedSuite(bytes[0])),
35 _ => return Err(CryptoError::InvalidKeyLength),
36 }
37 let mut stored = [0; 33];
38 stored[..bytes.len()].copy_from_slice(bytes);
39 Ok(Self {
40 bytes: stored,
41 length: bytes.len() as u8,
42 })
43 }
44
45 pub fn from_hex(value: &str) -> Result<Self, CryptoError> {
46 let bytes = hex::decode(value).map_err(|_| CryptoError::InvalidKeyLength)?;
47 Self::from_bytes(&bytes)
48 }
49
50 pub fn as_bytes(&self) -> &[u8] {
51 &self.bytes[..self.length as usize]
52 }
53
54 pub fn mode(&self) -> EncryptionMode {
55 if self.length == 32 {
56 EncryptionMode::LegacyChk
57 } else if self.bytes[0] == 1 {
58 EncryptionMode::ChkV1
59 } else {
60 EncryptionMode::RndV1
61 }
62 }
63
64 pub fn raw_key(&self) -> EncryptionKey {
65 self.as_bytes()[self.length as usize - 32..]
66 .try_into()
67 .expect("validated key")
68 }
69
70 pub fn to_hex(&self) -> String {
71 hex::encode(self.as_bytes())
72 }
73
74 fn versioned(suite: u8, key: EncryptionKey) -> Self {
75 let mut bytes = [0; 33];
76 bytes[0] = suite;
77 bytes[1..].copy_from_slice(&key);
78 Self { bytes, length: 33 }
79 }
80}
81
82impl From<EncryptionKey> for ObjectKey {
83 fn from(key: EncryptionKey) -> Self {
84 let mut bytes = [0; 33];
85 bytes[..32].copy_from_slice(&key);
86 Self { bytes, length: 32 }
87 }
88}
89
90impl AsRef<[u8]> for ObjectKey {
91 fn as_ref(&self) -> &[u8] {
92 self.as_bytes()
93 }
94}
95
96pub fn encrypt_object(
97 plaintext: &[u8],
98 mode: EncryptionMode,
99) -> Result<(Vec<u8>, ObjectKey), CryptoError> {
100 match mode {
101 EncryptionMode::LegacyChk | EncryptionMode::ChkV1 => {
102 let (bytes, key) = crypto::encrypt_chk(plaintext)?;
103 let key = if mode == EncryptionMode::LegacyChk {
104 key.into()
105 } else {
106 ObjectKey::versioned(1, key)
107 };
108 Ok((bytes, key))
109 }
110 EncryptionMode::RndV1 => {
111 let key = crypto::generate_key();
112 Ok((
113 crypto::encrypt(plaintext, &key)?,
114 ObjectKey::versioned(2, key),
115 ))
116 }
117 }
118}
119
120pub fn decrypt_object(bytes: &[u8], key: &ObjectKey) -> Result<Vec<u8>, CryptoError> {
121 match key.mode() {
122 EncryptionMode::LegacyChk | EncryptionMode::ChkV1 => {
123 crypto::decrypt_chk(bytes, &key.raw_key())
124 }
125 EncryptionMode::RndV1 => crypto::decrypt(bytes, &key.raw_key()),
126 }
127}
128
129impl std::ops::Deref for ObjectKey {
130 type Target = [u8];
131 fn deref(&self) -> &[u8] {
132 self.as_bytes()
133 }
134}
135
136impl serde::Serialize for ObjectKey {
137 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
138 self.as_bytes().serialize(serializer)
139 }
140}
141
142impl<'de> serde::Deserialize<'de> for ObjectKey {
143 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
144 let bytes = Vec::<u8>::deserialize(deserializer)?;
145 Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
146 }
147}