dark_crystal_key_backup_rust/
lib.rs1pub use crypto_box::aead::Error;
10use crypto_box::aead::{generic_array::GenericArray, Aead};
11pub use crypto_box::{Box, PublicKey, SecretKey};
12pub use dark_crystal_secret_sharing_rust::{
13 combine_authenticated, default_threshold, share_authenticated, thresold_sanity, RecoveryError,
14 ShareError,
15};
16use rand::Rng;
17use std::convert::TryInto;
18use std::fmt;
19use zeroize::Zeroize;
20
21const PUBLIC_KEY_LENGTH: usize = 32;
22const NONCE_LENGTH: usize = 24;
23
24#[derive(Debug)]
27pub struct EncryptedShareSet {
28 pub ciphertext: Vec<u8>,
29 pub encrypted_shares: Vec<Vec<u8>>,
30 pub eph_public_key: PublicKey,
31}
32
33pub fn share_and_encrypt(
35 public_keys: Vec<[u8; PUBLIC_KEY_LENGTH]>,
36 secret: Vec<u8>,
37 threshold: u8,
38) -> Result<EncryptedShareSet, ShareAndEncryptError> {
39 let num_shares = public_keys.len().try_into().unwrap();
41 let (shares, ciphertext) = share_authenticated(&secret, num_shares, threshold)?;
42 let mut encrypted_shares: Vec<Vec<u8>> = Vec::new();
43
44 let mut rng = crypto_box::rand_core::OsRng;
45 let eph_secret_key = SecretKey::generate(&mut rng);
46 let eph_public_key = eph_secret_key.public_key();
47 let mut eph_secret_key_bytes = eph_secret_key.as_bytes().clone();
48
49 for share_index in 0..public_keys.len() {
50 let share = &shares[share_index];
51 let pk = PublicKey::from(public_keys[share_index]);
52 let esk = SecretKey::from(eph_secret_key_bytes);
53 encrypted_shares.push(encrypt(esk, pk, share.to_vec())?);
54 }
55 eph_secret_key_bytes.zeroize();
56
57 Ok(EncryptedShareSet {
58 encrypted_shares,
59 ciphertext,
60 eph_public_key,
61 })
62}
63
64pub fn share_and_encrypt_detached_nonce(
68 public_keys: Vec<[u8; PUBLIC_KEY_LENGTH]>,
69 secret: Vec<u8>,
70 threshold: u8,
71) -> Result<EncryptedShareSet, ShareAndEncryptError> {
72 let num_shares = public_keys.len().try_into().unwrap();
74 let (shares, ciphertext) = share_authenticated(&secret, num_shares, threshold)?;
75 let mut encrypted_shares: Vec<Vec<u8>> = Vec::new();
76
77 let mut rng = crypto_box::rand_core::OsRng;
78 let eph_secret_key = SecretKey::generate(&mut rng);
79 let eph_public_key = eph_secret_key.public_key();
80 let mut eph_secret_key_bytes = eph_secret_key.as_bytes().clone();
81
82 let nonce: [u8; NONCE_LENGTH] = ciphertext.clone()[..NONCE_LENGTH].try_into().unwrap();
83
84 for share_index in 0..public_keys.len() {
85 let share = &shares[share_index];
86 let pk = PublicKey::from(public_keys[share_index]);
87 let esk = SecretKey::from(eph_secret_key_bytes);
88 encrypted_shares.push(encrypt_with_given_nonce(esk, pk, share.to_vec(), nonce)?);
89 }
90 eph_secret_key_bytes.zeroize();
91
92 Ok(EncryptedShareSet {
93 encrypted_shares,
94 ciphertext,
95 eph_public_key,
96 })
97}
98
99pub fn encrypt(
101 secret_key: SecretKey,
102 public_key: PublicKey,
103 plaintext: Vec<u8>,
104) -> Result<Vec<u8>, Error> {
105 let alice_box = Box::new(&public_key, &secret_key);
106 let mut rng = crypto_box::rand_core::OsRng;
107 let nonce_bytes = rng.gen::<[u8; NONCE_LENGTH]>();
108 let nonce = GenericArray::from_slice(&nonce_bytes);
109
110 let mut ciphertext_with_nonce = nonce_bytes.to_vec();
111
112 let ciphertext = alice_box.encrypt(&nonce, &plaintext[..])?;
113 ciphertext_with_nonce.extend(ciphertext);
114 Ok(ciphertext_with_nonce)
115}
116
117pub fn decrypt(
119 secret_key: SecretKey,
120 public_key: &PublicKey,
121 ciphertext_with_nonce: &Vec<u8>,
122) -> Result<Vec<u8>, Error> {
123 let ciphertext = &ciphertext_with_nonce[NONCE_LENGTH..];
124 let nonce = GenericArray::from_slice(&ciphertext_with_nonce[..NONCE_LENGTH]);
125
126 let bob_box = Box::new(public_key, &secret_key);
127 bob_box.decrypt(&nonce, &ciphertext[..])
128}
129
130pub fn encrypt_with_given_nonce(
133 secret_key: SecretKey,
134 public_key: PublicKey,
135 plaintext: Vec<u8>,
136 nonce: [u8; NONCE_LENGTH],
137) -> Result<Vec<u8>, Error> {
138 let alice_box = Box::new(&public_key, &secret_key);
139 let nonce = GenericArray::from_slice(&nonce);
140 alice_box.encrypt(&nonce, &plaintext[..])
141}
142
143pub fn decrypt_with_given_nonce(
146 secret_key: SecretKey,
147 public_key: &PublicKey,
148 ciphertext: &Vec<u8>,
149 nonce: [u8; NONCE_LENGTH],
150) -> Result<Vec<u8>, Error> {
151 let nonce = GenericArray::from_slice(&nonce);
152 let bob_box = Box::new(public_key, &secret_key);
153 bob_box.decrypt(&nonce, &ciphertext[..])
154}
155
156#[derive(Debug)]
158pub struct ShareAndEncryptError {
159 pub message: String,
160}
161
162impl fmt::Display for ShareAndEncryptError {
163 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164 write!(f, "Error during recovery {}", self.message)
165 }
166}
167
168impl From<crypto_box::aead::Error> for ShareAndEncryptError {
169 fn from(error: crypto_box::aead::Error) -> Self {
170 ShareAndEncryptError {
171 message: error.to_string(),
172 }
173 }
174}
175
176impl From<ShareError> for ShareAndEncryptError {
177 fn from(error: ShareError) -> Self {
178 ShareAndEncryptError {
179 message: error.to_string(),
180 }
181 }
182}
183
184#[cfg(test)]
185mod tests {
186 use super::*;
187 use dark_crystal_secret_sharing_rust::combine_authenticated;
188
189 #[test]
190 fn encryption() {
191 let mut rng = crypto_box::rand_core::OsRng;
192 let alice_secret_key = SecretKey::generate(&mut rng);
193 let alice_public_key = alice_secret_key.public_key();
194
195 let bob_secret_key = SecretKey::generate(&mut rng);
196 let bob_public_key = bob_secret_key.public_key();
197
198 let plaintext = b"hello";
199
200 let ciphertext = encrypt(alice_secret_key, bob_public_key, plaintext.to_vec()).unwrap();
201 let decrypted_plaintext = decrypt(bob_secret_key, &alice_public_key, &ciphertext).unwrap();
202
203 assert_eq!(&plaintext[..], &decrypted_plaintext[..]);
204 }
205
206 #[test]
207 fn encryption_with_given_nonce() {
208 let mut rng = crypto_box::rand_core::OsRng;
209 let alice_secret_key = SecretKey::generate(&mut rng);
210 let alice_public_key = alice_secret_key.public_key();
211
212 let bob_secret_key = SecretKey::generate(&mut rng);
213 let bob_public_key = bob_secret_key.public_key();
214
215 let nonce = rng.gen::<[u8; NONCE_LENGTH]>();
216 let plaintext = b"hello";
217
218 let ciphertext =
219 encrypt_with_given_nonce(alice_secret_key, bob_public_key, plaintext.to_vec(), nonce)
220 .unwrap();
221 let decrypted_plaintext =
222 decrypt_with_given_nonce(bob_secret_key, &alice_public_key, &ciphertext, nonce)
223 .unwrap();
224
225 assert_eq!(&plaintext[..], &decrypted_plaintext[..]);
226 }
227
228 #[test]
229 fn test_share_and_encrypt() {
230 let mut rng = crypto_box::rand_core::OsRng;
231 let alice_secret_key = SecretKey::generate(&mut rng);
232 let alice_public_key = alice_secret_key.public_key();
233
234 let bob_secret_key = SecretKey::generate(&mut rng);
235 let bob_public_key = bob_secret_key.public_key();
236
237 let mut public_keys: Vec<[u8; PUBLIC_KEY_LENGTH]> = Vec::new();
238 public_keys.push(*bob_public_key.as_bytes());
239 public_keys.push(*alice_public_key.as_bytes());
240
241 let original_secret = b"hello";
242 let encrypted_share_set =
243 share_and_encrypt(public_keys, original_secret[..].to_vec(), 2).unwrap();
244
245 assert_eq!(encrypted_share_set.encrypted_shares.len(), 2);
246 assert_eq!(encrypted_share_set.encrypted_shares[0].len(), 73);
247
248 let mut decrypted_shares: Vec<Vec<u8>> = Vec::new();
250 decrypted_shares.push(
251 decrypt(
252 alice_secret_key,
253 &encrypted_share_set.eph_public_key,
254 &encrypted_share_set.encrypted_shares[1],
255 )
256 .unwrap(),
257 );
258 decrypted_shares.push(
259 decrypt(
260 bob_secret_key,
261 &encrypted_share_set.eph_public_key,
262 &encrypted_share_set.encrypted_shares[0],
263 )
264 .unwrap(),
265 );
266
267 let recovered_secret =
269 combine_authenticated(decrypted_shares, encrypted_share_set.ciphertext).unwrap();
270 assert_eq!(recovered_secret, b"hello");
271 }
272
273 #[test]
274 fn test_share_and_encrypt_detached_nonce() {
275 let mut rng = crypto_box::rand_core::OsRng;
276 let alice_secret_key = SecretKey::generate(&mut rng);
277 let alice_public_key = alice_secret_key.public_key();
278
279 let bob_secret_key = SecretKey::generate(&mut rng);
280 let bob_public_key = bob_secret_key.public_key();
281
282 let mut public_keys: Vec<[u8; PUBLIC_KEY_LENGTH]> = Vec::new();
283 public_keys.push(*bob_public_key.as_bytes());
284 public_keys.push(*alice_public_key.as_bytes());
285
286 let original_secret = b"hello";
287 let encrypted_share_set =
288 share_and_encrypt_detached_nonce(public_keys, original_secret[..].to_vec(), 2).unwrap();
289
290 assert_eq!(encrypted_share_set.encrypted_shares.len(), 2);
291 assert_eq!(encrypted_share_set.encrypted_shares[0].len(), 49);
292
293 let nonce = encrypted_share_set.ciphertext.clone()[..NONCE_LENGTH]
295 .try_into()
296 .unwrap();
297
298 let mut decrypted_shares: Vec<Vec<u8>> = Vec::new();
299 decrypted_shares.push(
300 decrypt_with_given_nonce(
301 alice_secret_key,
302 &encrypted_share_set.eph_public_key,
303 &encrypted_share_set.encrypted_shares[1],
304 nonce,
305 )
306 .unwrap(),
307 );
308 decrypted_shares.push(
309 decrypt_with_given_nonce(
310 bob_secret_key,
311 &encrypted_share_set.eph_public_key,
312 &encrypted_share_set.encrypted_shares[0],
313 nonce,
314 )
315 .unwrap(),
316 );
317
318 let recovered_secret =
320 combine_authenticated(decrypted_shares, encrypted_share_set.ciphertext).unwrap();
321 assert_eq!(recovered_secret, b"hello");
322 }
323}