1#[cfg(feature = "miniscript_12_0")]
2pub use mscript_12_0 as miniscript;
3#[cfg(feature = "miniscript_12_3_5")]
4pub use mscript_12_3_5 as miniscript;
5
6use std::collections::BTreeSet;
7
8use aes_gcm::{
9 aead::{Aead, KeyInit},
10 Aes256Gcm, Key, Nonce,
11};
12use miniscript::bitcoin::{
13 self,
14 bip32::{ChildNumber, DerivationPath},
15 hashes::{sha256, Hash, HashEngine},
16 secp256k1, VarInt,
17};
18use rand::{rngs::OsRng, TryRngCore};
19
20use crate::{descriptor::bip341_nums, Encryption, Version};
21
22const DECRYPTION_SECRET: &str = "BEB_BACKUP_DECRYPTION_SECRET";
23const INDIVIDUAL_SECRET: &str = "BEB_BACKUP_INDIVIDUAL_SECRET";
24const MAGIC: &str = "BEB";
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum Error {
28 KeyCount,
29 DerivPathCount,
30 DerivPathLength,
31 DerivPathEmpty,
32 DataLength,
33 Encrypt,
34 Decrypt,
35 Corrupted,
36 Version,
37 Magic,
38 VarInt,
39 WrongKey,
40 IndividualSecretsEmpty,
41 IndividualSecretsLength,
42 CypherTextEmpty,
43 CypherTextLength,
44 ContentMetadata,
45 Encryption,
46 OffsetOverflow,
47 EmptyBytes,
48 Increment,
49 ContentMetadataEmpty,
50}
51
52#[derive(Debug, Clone, PartialEq, Eq)]
53pub enum Content {
54 None,
55 Bip380,
56 Bip388,
57 Bip329,
58 BIP(u16),
59 Proprietary(Vec<u8>),
60 Unknown,
61}
62
63impl From<Content> for Vec<u8> {
68 fn from(value: Content) -> Self {
69 match value {
70 Content::None => [0].into(),
71 Content::Proprietary(mut data) => {
72 assert!(data.len() > 2);
73 assert!(data.len() < u8::MAX as usize);
74 let mut content = vec![data.len() as u8];
75 content.append(&mut data);
76 content
77 }
78 Content::Unknown => unimplemented!(),
79 c => {
80 let mut content = vec![2];
81 let bip_number = match c {
82 Content::Bip380 => 380u16.to_be_bytes(),
83 Content::Bip388 => 388u16.to_be_bytes(),
84 Content::Bip329 => 329u16.to_be_bytes(),
85 Content::BIP(bip) => bip.to_be_bytes(),
86 _ => unreachable!(),
87 };
88 content.append(&mut bip_number.to_vec());
89 content
90 }
91 }
92 }
93}
94
95pub fn parse_content_metadata(bytes: &[u8]) -> Result<(usize, Content), Error> {
96 let len = bytes.len();
97 if len == 0 {
98 Err(Error::ContentMetadataEmpty)?
99 }
100 let data_len = bytes[0];
101 match data_len {
102 0 => Ok((1, Content::None)),
103 1 => Err(Error::ContentMetadata),
104 2 => {
105 let bip_number = u16::from_be_bytes(bytes[1..3].try_into().expect("len ok"));
106 match bip_number {
107 380 => Ok((3, Content::Bip380)),
108 388 => Ok((3, Content::Bip388)),
109 329 => Ok((3, Content::Bip329)),
110 bip_number => Ok((3, Content::BIP(bip_number))),
111 }
112 }
113 len => {
114 let end = (len + 1) as usize;
115 let data = &bytes[1..end].to_vec();
116 Ok((end, Content::Proprietary(data.to_vec())))
117 }
118 }
119}
120
121impl Content {
122 pub fn is_known(&self) -> bool {
123 match self {
124 Content::None | Content::Unknown | Content::Proprietary(_) => false,
125 Content::Bip380 | Content::Bip388 | Content::Bip329 | Content::BIP(_) => true,
126 }
127 }
128}
129
130pub fn xor(a: &[u8; 32], b: &[u8; 32]) -> [u8; 32] {
131 let mut out = [0; 32];
132 for i in 0..32 {
133 out[i] = a[i] ^ b[i];
134 }
135 out
136}
137
138pub fn nonce() -> [u8; 12] {
139 let mut rng = OsRng;
140 let mut nonce = [0u8; 12];
141 rng.try_fill_bytes(&mut nonce)
142 .expect("os rng must not fail");
143 nonce
144}
145
146pub fn decryption_secret(keys: &[[u8; 33]]) -> sha256::Hash {
147 let mut engine = sha256::HashEngine::default();
148 engine.input(DECRYPTION_SECRET.as_bytes());
149 keys.iter().for_each(|k| engine.input(k));
150 sha256::Hash::from_engine(engine)
151}
152
153pub fn individual_secret(secret: &sha256::Hash, key: &[u8; 33]) -> [u8; 32] {
154 let mut engine = sha256::HashEngine::default();
155 engine.input(INDIVIDUAL_SECRET.as_bytes());
156 engine.input(key);
157 let si = sha256::Hash::from_engine(engine);
158 xor(secret.as_byte_array(), si.as_byte_array())
159}
160
161pub fn individual_secrets(secret: &sha256::Hash, keys: &[[u8; 33]]) -> Vec<[u8; 32]> {
162 keys.iter()
163 .map(|k| individual_secret(secret, k))
164 .collect::<Vec<_>>()
165}
166
167pub fn inner_encrypt(
168 secret: sha256::Hash,
169 mut data: Vec<u8>,
170) -> Result<([u8; 12], Vec<u8>), Error> {
171 let nonce = nonce();
172
173 let key = Key::<Aes256Gcm>::from_slice(secret.as_byte_array());
174 let cipher = Aes256Gcm::new(key);
175
176 let mut plaintext = vec![];
177 plaintext.append(&mut data);
178
179 cipher
180 .encrypt(&Nonce::from(nonce), plaintext.as_slice())
181 .map(|c| (nonce, c))
182 .map_err(|_| Error::Encrypt)
183}
184
185pub fn encode_derivation_paths(derivation_paths: Vec<DerivationPath>) -> Result<Vec<u8>, Error> {
188 if derivation_paths.len() > u8::MAX as usize {
189 return Err(Error::DerivPathLength);
190 }
191 let mut encoded_paths = vec![derivation_paths.len() as u8];
192 for path in derivation_paths {
193 let childs = path.to_u32_vec();
194 let len = childs.len();
195 if len > u8::MAX as usize {
196 return Err(Error::DerivPathLength);
197 }
198 encoded_paths.push(len as u8);
199 for c in childs {
200 encoded_paths.append(&mut c.to_be_bytes().to_vec());
201 }
202 }
203 Ok(encoded_paths)
204}
205
206pub fn encode_individual_secrets(individual_secrets: &[[u8; 32]]) -> Result<Vec<u8>, Error> {
209 let individual_secrets: BTreeSet<_> = individual_secrets.iter().collect();
210 if individual_secrets.len() > u8::MAX as usize {
211 return Err(Error::IndividualSecretsLength);
212 } else if individual_secrets.is_empty() {
213 return Err(Error::IndividualSecretsEmpty);
214 }
215 let len = individual_secrets.len() as u8;
216 let mut out = Vec::with_capacity(1 + (individual_secrets.len() * 32));
217 out.push(len);
218 for is in individual_secrets {
219 out.append(&mut is.to_vec());
220 }
221 Ok(out)
222}
223
224pub fn encode_encrypted_payload(nonce: [u8; 12], cyphertext: &[u8]) -> Result<Vec<u8>, Error> {
227 if cyphertext.is_empty() {
228 return Err(Error::CypherTextEmpty);
229 }
230 let mut out = Vec::new();
231 out.append(&mut nonce.as_slice().to_vec());
232 let mut var_int = bitcoin::consensus::serialize(&bitcoin::VarInt(cyphertext.len() as u64));
233 out.append(&mut var_int);
234 out.append(&mut cyphertext.to_vec());
235
236 Ok(out)
237}
238
239pub fn encode_v1(
244 version: u8,
245 mut derivation_paths: Vec<u8>,
246 mut individual_secrets: Vec<u8>,
247 encryption: u8,
248 mut encrypted_payload: Vec<u8>,
249) -> Vec<u8> {
250 let mut out = MAGIC.as_bytes().to_vec();
252 out.push(version);
254 out.append(&mut derivation_paths);
256 out.append(&mut individual_secrets);
258 out.push(encryption);
260 out.append(&mut encrypted_payload);
262 out
263}
264
265pub fn check_offset(offset: usize, bytes: &[u8]) -> Result<(), Error> {
266 if bytes.len() <= offset {
267 Err(Error::Corrupted)
268 } else {
269 Ok(())
270 }
271}
272
273pub fn check_offset_lookahead(offset: usize, bytes: &[u8], lookahead: usize) -> Result<(), Error> {
274 let target = offset
275 .checked_add(lookahead)
276 .ok_or(Error::Increment)?
277 .checked_sub(1)
278 .ok_or(Error::Increment)?;
279 if bytes.len() <= target {
280 Err(Error::Corrupted)
281 } else {
282 Ok(())
283 }
284}
285
286pub fn init_offset(bytes: &[u8], value: usize) -> Result<usize, Error> {
287 check_offset(value, bytes)?;
288 Ok(value)
289}
290
291pub fn increment_offset(bytes: &[u8], offset: usize, incr: usize) -> Result<usize, Error> {
292 check_offset(offset + incr, bytes)?;
293 offset.checked_add(incr).ok_or(Error::OffsetOverflow)
294}
295
296pub fn decode_version(bytes: &[u8]) -> Result<u8, Error> {
299 let offset = init_offset(bytes, parse_magic_byte(bytes)?)?;
301 let (_, version) = parse_version(&bytes[offset..])?;
303 Ok(version)
304}
305
306pub fn decode_derivation_paths(bytes: &[u8]) -> Result<Vec<DerivationPath>, Error> {
309 let mut offset = init_offset(bytes, parse_magic_byte(bytes)?)?;
311 let (incr, _) = parse_version(&bytes[offset..])?;
313 offset = increment_offset(bytes, offset, incr)?;
314 let (_, derivation_paths) = parse_derivation_paths(&bytes[offset..])?;
316 Ok(derivation_paths)
317}
318
319#[allow(clippy::type_complexity)]
322pub fn decode_v1(
323 bytes: &[u8],
324) -> Result<
325 (
326 Vec<DerivationPath>, Vec<[u8; 32]>, u8, [u8; 12], Vec<u8>, ),
332 Error,
333> {
334 let mut offset = init_offset(bytes, parse_magic_byte(bytes)?)?;
336 let (incr, _) = parse_version(&bytes[offset..])?;
338 offset = increment_offset(bytes, offset, incr)?;
339 let (incr, derivation_paths) = parse_derivation_paths(&bytes[offset..])?;
341 offset = increment_offset(bytes, offset, incr)?;
342 let (incr, individual_secrets) = parse_individual_secrets(&bytes[offset..])?;
344 offset = increment_offset(bytes, offset, incr)?;
345 let (incr, encryption_type) = parse_encryption(&bytes[offset..])?;
347 offset = increment_offset(bytes, offset, incr)?;
348 let (nonce, cyphertext) = parse_encrypted_payload(&bytes[offset..])?;
350
351 Ok((
352 derivation_paths,
353 individual_secrets,
354 encryption_type,
355 nonce,
356 cyphertext,
357 ))
358}
359
360pub fn encrypt_aes_gcm_256_v1(
361 derivation_paths: Vec<DerivationPath>,
362 content_metadata: Content,
363 keys: Vec<secp256k1::PublicKey>,
364 data: &[u8],
365) -> Result<Vec<u8>, Error> {
366 let keys = keys
368 .into_iter()
369 .filter(|k| *k != bip341_nums())
370 .collect::<BTreeSet<_>>();
371
372 let derivation_paths = derivation_paths
374 .into_iter()
375 .collect::<BTreeSet<_>>()
376 .into_iter()
377 .collect::<Vec<_>>();
378
379 if keys.len() > u8::MAX as usize || keys.is_empty() {
380 return Err(Error::KeyCount);
381 }
382 if derivation_paths.len() > u8::MAX as usize {
383 return Err(Error::DerivPathCount);
384 }
385 if data.len() > u32::MAX as usize {
390 return Err(Error::DataLength);
391 }
392 if data.is_empty() {
393 return Err(Error::DataLength);
394 }
395
396 let content_metadata: Vec<u8> = content_metadata.into();
397 if content_metadata.is_empty() {
398 return Err(Error::ContentMetadata);
399 }
400
401 let mut raw_keys = keys.into_iter().map(|k| k.serialize()).collect::<Vec<_>>();
402 raw_keys.sort();
403
404 let secret = decryption_secret(&raw_keys);
405 let individual_secrets =
406 encode_individual_secrets(&individual_secrets(&secret, raw_keys.as_slice()))?;
407 let derivation_paths = encode_derivation_paths(derivation_paths)?;
408
409 let mut payload = content_metadata;
411 payload.append(&mut data.to_vec());
412
413 let (nonce, cyphertext) = inner_encrypt(secret, payload.to_vec())?;
414 let encrypted_payload = encode_encrypted_payload(nonce, cyphertext.as_slice())?;
415
416 Ok(encode_v1(
417 Version::V1.into(),
418 derivation_paths,
419 individual_secrets,
420 Encryption::AesGcm256.into(),
421 encrypted_payload,
422 ))
423}
424
425pub fn try_decrypt_aes_gcm_256(
426 cyphertext: &[u8],
427 secret: &[u8; 32],
428 nonce: [u8; 12],
429) -> Option<Vec<u8>> {
430 let nonce = Nonce::from(nonce);
431
432 let key = Key::<Aes256Gcm>::from_slice(secret);
433 let cipher = Aes256Gcm::new(key);
434
435 cipher.decrypt(&nonce, cyphertext).ok()
436}
437
438pub fn decrypt_aes_gcm_256_v1(
439 key: secp256k1::PublicKey,
440 individual_secrets: &Vec<[u8; 32]>,
441 cyphertext: Vec<u8>,
442 nonce: [u8; 12],
443) -> Result<(Content, Vec<u8>), Error> {
444 let raw_key = key.serialize();
445
446 let mut engine = sha256::HashEngine::default();
447 engine.input(INDIVIDUAL_SECRET.as_bytes());
448 engine.input(&raw_key);
449 let si = sha256::Hash::from_engine(engine);
450
451 for ci in individual_secrets {
452 let secret = xor(si.as_byte_array(), ci);
453 if let Some(out) = try_decrypt_aes_gcm_256(&cyphertext, &secret, nonce) {
454 let mut offset = init_offset(&out, 0)?;
455 let (incr, content) = parse_content_metadata(&out)?;
457 offset = increment_offset(&out, offset, incr)?;
459 let out = out[offset..].to_vec();
460 return Ok((content, out));
461 }
462 }
463
464 Err(Error::WrongKey)
465}
466
467pub fn parse_magic_byte(bytes: &[u8]) -> Result<usize , Error> {
468 let magic = MAGIC.as_bytes();
469
470 if bytes.len() < magic.len() || &bytes[..magic.len()] != magic {
471 return Err(Error::Magic);
472 }
473 Ok(magic.len())
474}
475
476pub fn parse_version(bytes: &[u8]) -> Result<(usize, u8), Error> {
477 if bytes.is_empty() {
478 return Err(Error::Version);
479 }
480 let version = bytes[0];
481 if version > Version::max().into() {
482 return Err(Error::Version);
483 }
484 Ok((1, version))
485}
486
487pub fn parse_encryption(bytes: &[u8]) -> Result<(usize, u8), Error> {
488 if bytes.is_empty() {
489 return Err(Error::Encryption);
490 }
491 let encryption = bytes[0];
492 Ok((1, encryption))
493}
494
495pub fn parse_derivation_paths(
502 bytes: &[u8],
503) -> Result<(usize , Vec<DerivationPath>), Error> {
504 let mut offset = init_offset(bytes, 0).map_err(|_| Error::DerivPathEmpty)?;
505 let mut derivation_paths = BTreeSet::new();
506
507 let count = bytes[0];
509
510 if count != 0 {
511 offset = increment_offset(bytes, offset, 1)?;
512 for _ in 0..count {
513 check_offset(offset, bytes)?;
514 let child_count = bytes[offset];
516 if child_count == 0 {
517 return Err(Error::DerivPathEmpty);
518 } else {
519 let mut childs = vec![];
520 offset += 1;
521 for _ in 0..child_count {
522 check_offset_lookahead(offset, bytes, 4)?;
523 let raw_child: [u8; 4] =
525 bytes[offset..(offset + 4)].try_into().expect("verified");
526 let child = u32::from_be_bytes(raw_child);
527 let child = ChildNumber::from(child);
528 childs.push(child);
529 offset += 4;
530 }
531 derivation_paths.insert(DerivationPath::from(childs));
532 }
533 }
534 } else {
535 offset += 1;
536 }
537
538 let derivation_paths = derivation_paths.into_iter().collect();
539
540 Ok((offset, derivation_paths))
541}
542
543pub fn parse_individual_secrets(
550 bytes: &[u8],
551) -> Result<(usize , Vec<[u8; 32]>), Error> {
552 if bytes.is_empty() {
553 return Err(Error::EmptyBytes);
554 }
555 let count = bytes[0];
557 if count < 1 {
558 return Err(Error::IndividualSecretsEmpty);
559 }
560 let mut offset = init_offset(bytes, 1)?;
561
562 let mut individual_secrets = BTreeSet::new();
563 for _ in 0..count {
564 check_offset_lookahead(offset, bytes, 32)?;
565 let secret: [u8; 32] = bytes[offset..offset + 32]
567 .try_into()
568 .map_err(|_| Error::Corrupted)?;
569 individual_secrets.insert(secret);
570 offset += 32;
571 }
572
573 let individual_secrets = individual_secrets.into_iter().collect();
574 Ok((offset, individual_secrets))
575}
576
577pub fn parse_encrypted_payload(
581 bytes: &[u8],
582) -> Result<([u8; 12] , Vec<u8> ), Error> {
583 let mut offset = init_offset(bytes, 0)?;
584 check_offset_lookahead(offset, bytes, 12)?;
586 let nonce: [u8; 12] = bytes[offset..offset + 12].try_into().expect("checked");
587 offset = increment_offset(bytes, offset, 12)?;
588 let (VarInt(data_len), incr) =
590 bitcoin::consensus::deserialize_partial(&bytes[offset..]).map_err(|_| Error::VarInt)?;
591 let data_len = data_len as usize;
593 offset = increment_offset(bytes, offset, incr)?;
594 check_offset_lookahead(offset, bytes, data_len)?;
596 let cyphertext = bytes[offset..offset + data_len].to_vec();
597 Ok((nonce, cyphertext))
598}
599
600#[cfg(test)]
601mod tests {
602 use aes_gcm::aead::{rand_core::RngCore, OsRng};
603 use miniscript::bitcoin::XOnlyPublicKey;
604 use rand::random;
605
606 use super::*;
607 use std::str::FromStr;
608
609 fn pk1() -> secp256k1::PublicKey {
610 secp256k1::PublicKey::from_str(
611 "02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443",
612 )
613 .unwrap()
614 }
615
616 fn pk2() -> secp256k1::PublicKey {
617 secp256k1::PublicKey::from_str(
618 "0384526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f07",
619 )
620 .unwrap()
621 }
622
623 fn pk3() -> secp256k1::PublicKey {
624 secp256k1::PublicKey::from_str(
625 "0384526253c27c7aef56c7b71a5cd25bebb000000a437826defc5b2568bde81f07",
626 )
627 .unwrap()
628 }
629
630 #[test]
631 fn test_fuzz_catch_1() {
632 let bytes = [
634 66, 73, 80, 88, 88, 88, 88, 0, 0, 1, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
635 48, 48, 48, 48, 48, 207, 207, 207, 207, 207, 207, 48, 48, 48, 48, 48, 48, 48, 48, 48,
636 32, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 185, 185, 0, 88, 0, 0, 185, 185,
637 ];
638 let _ = decode_v1(&bytes);
639 }
640
641 #[test]
642 fn test_nonce() {
643 let nonce_1 = nonce();
644 let nonce_2 = nonce();
645 assert_ne!(nonce_1, nonce_2);
646 }
647
648 #[test]
649 fn test_check_offset() {
650 let res = check_offset(1, &[0x00]);
651 assert!(res.is_err());
652 check_offset(1, &[0x00, 0x00]).unwrap();
653 }
654
655 #[test]
656 fn test_check_offset_look_ahead() {
657 let res = check_offset_lookahead(0, &[0x00; 2], 3);
658 assert!(res.is_err());
659 check_offset_lookahead(0, &[0x00; 2], 2).unwrap();
660 }
661
662 #[test]
663 fn test_init_offset() {
664 let res = init_offset(&[0x00], 1);
665 assert!(res.is_err());
666 init_offset(&[0x00], 0).unwrap();
667 }
668
669 #[test]
670 fn test_increment_offset() {
671 let res = increment_offset(&[0x00], 0, 1);
672 assert!(res.is_err());
673 increment_offset(&[0x00; 2], 0, 1).unwrap();
674 }
675
676 #[test]
677 fn test_parse_magic() {
678 let magic = "BEB".as_bytes();
679 assert_eq!(MAGIC, "BEB");
680 let offset = parse_magic_byte(magic).unwrap();
681 assert_eq!(offset, magic.len());
682 let res = parse_magic_byte("BOBt s".as_bytes());
683 assert_eq!(res, Err(Error::Magic));
684 let _ = parse_magic_byte(MAGIC.as_bytes()).unwrap();
685 }
686
687 #[test]
688 fn test_parse_version() {
689 let (_, v) = parse_version(&[0x00]).unwrap();
690 assert_eq!(v, 0x00);
691 let (_, v) = parse_version(&[0x01]).unwrap();
692 assert_eq!(v, 0x01);
693 let res = parse_version(&[]);
694 assert_eq!(res, Err(Error::Version));
695 let res = parse_version(&[0x02]);
696 assert_eq!(res, Err(Error::Version));
697 }
698
699 #[test]
700 pub fn test_parse_encryption() {
701 let (l, e) = parse_encryption(&[0]).unwrap();
702 assert_eq!(l, 1);
703 assert_eq!(e, 0);
704 let (l, e) = parse_encryption(&[0, 2]).unwrap();
705 assert_eq!(l, 1);
706 assert_eq!(e, 0);
707 let (l, e) = parse_encryption(&[2, 0]).unwrap();
708 assert_eq!(l, 1);
709 assert_eq!(e, 2);
710 let failed = parse_encryption(&[]).unwrap_err();
711 assert_eq!(failed, Error::Encryption)
712 }
713
714 #[test]
715 pub fn test_parse_derivation_path() {
716 let (_, p) = parse_derivation_paths(&[0x01, 0x01, 0x00, 0x00, 0x00, 0x01]).unwrap();
718 assert_eq!(p.len(), 1);
719
720 let p = parse_derivation_paths(&[0x01, 0x01, 0x00]).unwrap_err();
722 assert_eq!(p, Error::Corrupted);
723 let p = parse_derivation_paths(&[0x01, 0x01, 0x00, 0x00]).unwrap_err();
724 assert_eq!(p, Error::Corrupted);
725 let p = parse_derivation_paths(&[0x01, 0x01, 0x00, 0x00, 0x00]).unwrap_err();
726 assert_eq!(p, Error::Corrupted);
727
728 let p = parse_derivation_paths(&[0x01, 0x00]).unwrap_err();
730 assert_eq!(p, Error::DerivPathEmpty);
731 }
732
733 #[test]
734 pub fn test_parse_individual_secrets() {
735 let fail = parse_individual_secrets(&[]).unwrap_err();
737 assert_eq!(fail, Error::EmptyBytes);
738
739 let fail = parse_individual_secrets(&[0x00]).unwrap_err();
741 assert_eq!(fail, Error::IndividualSecretsEmpty);
742
743 let is1 = [1u8; 32].to_vec();
744 let is2 = [2u8; 32].to_vec();
745
746 let mut bytes = vec![0x01];
748 bytes.append(&mut is1.clone());
749 let (_, is) = parse_individual_secrets(&bytes).unwrap();
750 assert_eq!(is[0].to_vec(), is1);
751
752 let mut bytes = vec![0x02];
754 bytes.append(&mut is1.clone());
755 bytes.append(&mut is2.clone());
756 let (_, is) = parse_individual_secrets(&bytes).unwrap();
757 assert_eq!(is[0].to_vec(), is1);
758 assert_eq!(is[1].to_vec(), is2);
759 }
760
761 #[test]
762 fn test_parse_content() {
763 assert!(parse_content_metadata(&[]).is_err());
765 let (_, c) = parse_content_metadata(&[0]).unwrap();
767 assert_eq!(c, Content::None);
768 assert!(parse_content_metadata(&[1, 0]).is_err());
770 let (_, c) = parse_content_metadata(&[2, 0x01, 0x7c]).unwrap();
772 assert_eq!(c, Content::Bip380);
773 let (_, c) = parse_content_metadata(&[2, 0x01, 0x84]).unwrap();
775 assert_eq!(c, Content::Bip388);
776 let (_, c) = parse_content_metadata(&[2, 0x01, 0x49]).unwrap();
778 assert_eq!(c, Content::Bip329);
779 let (_, c) = parse_content_metadata(&[2, 0xFF, 0xFF]).unwrap();
781 assert_eq!(c, Content::BIP(u16::MAX));
782 let (_, c) = parse_content_metadata(&[2, 0, 0]).unwrap();
783 assert_eq!(c, Content::BIP(0));
784 let (_, c) = parse_content_metadata(&[3, 0, 0, 0]).unwrap();
786 assert_eq!(c, Content::Proprietary(vec![0, 0, 0]));
787 }
788
789 #[test]
790 fn test_serialize_content() {
791 let mut c = Content::Proprietary(vec![0, 0, 0]);
793 let mut serialized: Vec<u8> = c.into();
794 assert_eq!(serialized, vec![3, 0, 0, 0]);
795 c = Content::Bip380;
797 serialized = c.into();
798 assert_eq!(serialized, vec![0x02, 0x01, 0x7C]);
799 c = Content::BIP(380);
800 serialized = c.into();
801 assert_eq!(serialized, vec![0x02, 0x01, 0x7C]);
802 c = Content::Bip388;
804 serialized = c.into();
805 assert_eq!(serialized, vec![0x02, 0x01, 0x84]);
806 c = Content::BIP(388);
807 serialized = c.into();
808 assert_eq!(serialized, vec![0x02, 0x01, 0x84]);
809 c = Content::Bip329;
811 serialized = c.into();
812 assert_eq!(serialized, vec![0x02, 0x01, 0x49]);
813 c = Content::BIP(329);
814 serialized = c.into();
815 assert_eq!(serialized, vec![0x02, 0x01, 0x49]);
816 }
817
818 #[test]
819 fn test_content_is_known() {
820 let mut c = Content::None;
821 assert!(!c.is_known());
822 c = Content::Unknown;
823 assert!(!c.is_known());
824 c = Content::Proprietary(vec![0, 0, 0]);
825 assert!(!c.is_known());
826 c = Content::Bip380;
827 assert!(c.is_known());
828 c = Content::Bip388;
829 assert!(c.is_known());
830 c = Content::Bip329;
831 assert!(c.is_known());
832 c = Content::BIP(0);
833 assert!(c.is_known());
834 }
835
836 #[test]
837 fn test_simple_encode_decode_encrypted_payload() {
838 let bytes = encode_encrypted_payload([3; 12], &[1, 2, 3, 4]).unwrap();
839 let mut expected = [3; 12].to_vec();
840 expected.append(&mut [4, 1, 2, 3, 4].to_vec());
841 assert_eq!(bytes, expected);
842 let (nonce, cyphertext) = parse_encrypted_payload(&bytes).unwrap();
843 assert_eq!([3u8; 12], nonce);
844 assert_eq!([1, 2, 3, 4].to_vec(), cyphertext);
845 }
846
847 #[test]
848 fn test_encode_empty_encrypted_payload() {
849 let res = encode_encrypted_payload([3; 12], &[]);
850 assert_eq!(res, Err(Error::CypherTextEmpty));
851 }
852
853 #[test]
854 fn test_encode_decode_derivation_paths() {
855 let bytes = encode_derivation_paths(vec![
856 DerivationPath::from_str("0/1h/2/3h").unwrap(),
857 DerivationPath::from_str("84'/0'/0'/2'").unwrap(),
858 ])
859 .unwrap();
860 let expected = vec![
861 2, 4, 0, 0, 0, 0, 128, 0, 0, 1, 0, 0, 0, 2, 128, 0, 0, 3, 4, 128, 0, 0, 84, 128, 0, 0,
862 0, 128, 0, 0, 0, 128, 0, 0, 2,
863 ];
864 assert_eq!(expected, bytes);
865 let (offset, paths) = parse_derivation_paths(&bytes).unwrap();
866 assert_eq!(offset, 35);
867 assert_eq!(
868 paths,
869 vec![
870 DerivationPath::from_str("0/1h/2/3h").unwrap(),
871 DerivationPath::from_str("84'/0'/0'/2'").unwrap(),
872 ]
873 );
874 }
875
876 #[test]
877 fn test_decode_deriv_path_sorted() {
878 let bytes = encode_derivation_paths(vec![
879 DerivationPath::from_str("84'/0'/0'/2'").unwrap(),
880 DerivationPath::from_str("0/1h/2/3h").unwrap(),
881 ])
882 .unwrap();
883 let (_, paths) = parse_derivation_paths(&bytes).unwrap();
884 assert_eq!(
885 paths,
886 vec![
889 DerivationPath::from_str("0/1h/2/3h").unwrap(),
890 DerivationPath::from_str("84'/0'/0'/2'").unwrap(),
891 ]
892 );
893 }
894
895 #[test]
896 fn test_decode_deriv_path_no_duplicates() {
897 let bytes = encode_derivation_paths(vec![
898 DerivationPath::from_str("0/1h/2/3h").unwrap(),
899 DerivationPath::from_str("84'/0'/0'/2'").unwrap(),
900 DerivationPath::from_str("84'/0'/0'/2'").unwrap(),
901 ])
902 .unwrap();
903 let (_, paths) = parse_derivation_paths(&bytes).unwrap();
904 assert_eq!(
905 paths,
906 vec![
907 DerivationPath::from_str("0/1h/2/3h").unwrap(),
908 DerivationPath::from_str("84'/0'/0'/2'").unwrap(),
909 ]
910 );
911 }
912
913 #[test]
914 fn test_decode_deriv_path_empty() {
915 let bytes = encode_derivation_paths(vec![]).unwrap();
916 assert_eq!(bytes, vec![0x00]);
917 let (_, paths) = parse_derivation_paths(&bytes).unwrap();
918 assert_eq!(paths, vec![]);
919 }
920
921 #[test]
922 fn test_encode_too_much_deriv_paths() {
923 let mut deriv_paths = vec![];
924 for _ in 0..256 {
925 deriv_paths.push(DerivationPath::from_str("0/1h/2/3h").unwrap());
926 }
927 assert_eq!(deriv_paths.len(), 256);
928 let res = encode_derivation_paths(deriv_paths);
929 assert_eq!(res, Err(Error::DerivPathLength));
930 }
931
932 #[test]
933 fn test_encode_too_long_deriv_paths() {
934 let mut deriv_path = vec![];
935 for _ in 0..256 {
936 deriv_path.push(ChildNumber::from_normal_idx(0).unwrap());
937 }
938 assert_eq!(deriv_path.len(), 256);
939 let res = encode_derivation_paths(vec![DerivationPath::from(deriv_path)]);
940 assert_eq!(res, Err(Error::DerivPathLength));
941 }
942
943 #[test]
944 fn test_encode_decode_encrypted_payload() {
945 let payloads = [
946 "test".as_bytes().to_vec(),
947 [1; 0x1FFF].to_vec(),
948 [2; 0x2FFFFFFF].to_vec(),
949 ];
950 for payload in payloads {
951 let bytes = encode_encrypted_payload([3; 12], &payload).unwrap();
952 let (nonce, cyphertext) = parse_encrypted_payload(&bytes).unwrap();
953 assert_eq!([3u8; 12], nonce);
954 assert_eq!(payload, cyphertext);
955 }
956 }
957
958 #[test]
959 fn test_encode_empty_individual_secrets() {
960 let res = encode_individual_secrets(&[]);
961 assert_eq!(res, Err(Error::IndividualSecretsEmpty));
962 }
963
964 #[test]
965 fn test_too_much_individual_secrets() {
966 let mut secrets = vec![];
967 let mut rng = OsRng;
968 for _ in 0..256 {
969 let mut secret = [0u8; 32];
970 rng.fill_bytes(&mut secret);
971 secrets.push(secret);
972 }
973 let res = encode_individual_secrets(&secrets);
974 assert_eq!(res, Err(Error::IndividualSecretsLength));
975 }
976
977 #[test]
978 fn test_encode_decode_individual_secrets() {
979 let secrets = vec![[0; 32], [1; 32]];
980 let bytes = encode_individual_secrets(&secrets).unwrap();
981 let expected = vec![
982 2u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
983 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
984 1, 1, 1, 1, 1, 1, 1, 1,
985 ];
986 assert_eq!(expected, bytes);
987 let (_, decoded) = parse_individual_secrets(&bytes).unwrap();
988 assert_eq!(secrets, decoded);
989 }
990
991 #[test]
992 fn test_encode_individual_secrets_no_duplicates() {
993 let secrets = vec![[0; 32], [0; 32]];
994 let bytes = encode_individual_secrets(&secrets).unwrap();
995 let expected = vec![
996 1u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
997 0, 0, 0, 0, 0,
998 ];
999 assert_eq!(expected, bytes);
1000 }
1001
1002 #[test]
1003 fn test_decode_individual_secrets_no_duplicates() {
1004 let bytes = vec![
1005 2u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1006 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1007 0, 0, 0, 0, 0, 0, 0, 0,
1008 ];
1009 let (_, secrets) = parse_individual_secrets(&bytes).unwrap();
1010 assert_eq!(secrets.len(), 1);
1011 }
1012
1013 #[test]
1014 fn test_encode_decode_v1() {
1015 let bytes = encode_v1(
1016 0x01,
1017 encode_derivation_paths(vec![DerivationPath::from_str("8/9").unwrap()]).unwrap(),
1018 [0x01; 33].to_vec(),
1019 0x01,
1020 encode_encrypted_payload([0x04u8; 12], &[0x00]).unwrap(),
1021 );
1022 let mut expected = MAGIC.as_bytes().to_vec();
1024 expected.append(&mut vec![0x01]);
1026 expected.append(&mut vec![
1028 0x01, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09,
1029 ]);
1030 expected.append(&mut [0x01; 33].to_vec());
1032 expected.append(&mut vec![0x01]);
1034 expected.append(&mut encode_encrypted_payload([0x04u8; 12], &[0x00]).unwrap());
1036 assert_eq!(bytes, expected);
1037 let version = decode_version(&bytes).unwrap();
1038 assert_eq!(version, 0x01);
1039 let derivs = decode_derivation_paths(&bytes).unwrap();
1040 assert_eq!(derivs, vec![DerivationPath::from_str("8/9").unwrap()]);
1041 let (derivs, secrets, encryption, nonce, cyphertext) = decode_v1(&bytes).unwrap();
1042 assert_eq!(derivs, vec![DerivationPath::from_str("8/9").unwrap()]);
1043 assert_eq!(secrets, vec![[0x01; 32]]);
1044 assert_eq!(encryption, 0x01);
1045 assert_eq!(nonce, [0x04u8; 12]);
1046 assert_eq!(cyphertext, vec![0x00]);
1047 }
1048
1049 #[test]
1050 fn test_encrypt_sanitizing() {
1051 let keys = vec![];
1053 let data = "test".as_bytes().to_vec();
1054 let res = encrypt_aes_gcm_256_v1(vec![], Content::Bip380, keys, &data);
1055 assert_eq!(res, Err(Error::KeyCount));
1056
1057 let mut keys = BTreeSet::new();
1059 while keys.len() < 256 {
1060 let key: [u8; 32] = random();
1061 if let Ok(k) = XOnlyPublicKey::from_slice(&key) {
1062 let k = bitcoin::secp256k1::PublicKey::from_x_only_public_key(
1063 k,
1064 secp256k1::Parity::Odd,
1065 );
1066 keys.insert(k);
1067 }
1068 }
1069 let keys = keys.into_iter().collect::<Vec<_>>();
1070 let res = encrypt_aes_gcm_256_v1(vec![], Content::Bip380, keys, &data);
1071 assert_eq!(res, Err(Error::KeyCount));
1072
1073 let keys = [pk1()].to_vec();
1075 let res = encrypt_aes_gcm_256_v1(vec![], Content::Bip380, keys, &[]);
1076 assert_eq!(res, Err(Error::DataLength));
1077
1078 let keys = [pk1()].to_vec();
1080 let mut deriv_paths = BTreeSet::new();
1081 while deriv_paths.len() < 256 {
1082 let raw_deriv: [u32; 4] = random();
1083 let childs: Vec<ChildNumber> =
1084 raw_deriv.iter().copied().map(ChildNumber::from).collect();
1085 let deriv: DerivationPath = childs.into();
1086 deriv_paths.insert(deriv);
1087 }
1088 let deriv_paths = deriv_paths.into_iter().collect();
1089 let res = encrypt_aes_gcm_256_v1(deriv_paths, Content::Bip380, keys, &data);
1090 assert_eq!(res, Err(Error::DerivPathCount));
1091 }
1092
1093 #[test]
1094 fn test_basic_encrypt_decrypt() {
1095 let keys = vec![pk2(), pk1()];
1096 let data = "test".as_bytes().to_vec();
1097 let bytes = encrypt_aes_gcm_256_v1(vec![], Content::None, keys, &data).unwrap();
1098
1099 let version = decode_version(&bytes).unwrap();
1100 assert_eq!(version, 1);
1101
1102 let deriv_paths = decode_derivation_paths(&bytes).unwrap();
1103 assert!(deriv_paths.is_empty());
1104
1105 let (_, individual_secrets, encryption_type, nonce, cyphertext) =
1106 decode_v1(&bytes).unwrap();
1107 assert_eq!(encryption_type, 0x01);
1108
1109 let (content, decrypted_1) =
1110 decrypt_aes_gcm_256_v1(pk1(), &individual_secrets, cyphertext.clone(), nonce).unwrap();
1111 assert_eq!(content, Content::None);
1112 assert_eq!(String::from_utf8(decrypted_1).unwrap(), "test".to_string());
1113 let (content, decrypted_2) =
1114 decrypt_aes_gcm_256_v1(pk2(), &individual_secrets, cyphertext.clone(), nonce).unwrap();
1115 assert_eq!(content, Content::None);
1116 assert_eq!(String::from_utf8(decrypted_2).unwrap(), "test".to_string());
1117 let decrypted_3 =
1118 decrypt_aes_gcm_256_v1(pk3(), &individual_secrets, cyphertext.clone(), nonce);
1119 assert!(decrypted_3.is_err());
1120 }
1121
1122 #[test]
1123 fn test_decrypt_wrong_secret() {
1124 let mut engine = sha256::HashEngine::default();
1125 engine.input("secret".as_bytes());
1126 let secret = sha256::Hash::from_engine(engine);
1127
1128 let mut engine = sha256::HashEngine::default();
1129 engine.input("wrong_secret".as_bytes());
1130 let wrong_secret = sha256::Hash::from_engine(engine);
1131
1132 let payload = "payload".as_bytes().to_vec();
1133 let (nonce, ciphertext) = inner_encrypt(secret, payload).unwrap();
1134 let _ = try_decrypt_aes_gcm_256(&ciphertext, secret.as_byte_array(), nonce).unwrap();
1136 let fails = try_decrypt_aes_gcm_256(&ciphertext, wrong_secret.as_byte_array(), nonce);
1138 assert!(fails.is_none());
1139 }
1140
1141 #[test]
1142 fn test_decrypt_wrong_nonce() {
1143 let mut engine = sha256::HashEngine::default();
1144 engine.input("secret".as_bytes());
1145 let secret = sha256::Hash::from_engine(engine);
1146
1147 let payload = "payload".as_bytes().to_vec();
1148 let (nonce, ciphertext) = inner_encrypt(secret, payload).unwrap();
1149 let _ = try_decrypt_aes_gcm_256(&ciphertext, secret.as_byte_array(), nonce).unwrap();
1151 let nonce = [0xF1; 12];
1153 let fails = try_decrypt_aes_gcm_256(&ciphertext, secret.as_byte_array(), nonce);
1154 assert!(fails.is_none());
1155 }
1156
1157 #[test]
1158 fn test_decrypt_corrupted_ciphertext_fails() {
1159 let mut engine = sha256::HashEngine::default();
1160 engine.input("secret".as_bytes());
1161 let secret = sha256::Hash::from_engine(engine);
1162
1163 let payload = "payload".as_bytes().to_vec();
1164 let (nonce, mut ciphertext) = inner_encrypt(secret, payload).unwrap();
1165 let _ = try_decrypt_aes_gcm_256(&ciphertext, secret.as_byte_array(), nonce).unwrap();
1167
1168 let offset = ciphertext.len() - 10;
1170 for i in offset..offset + 5 {
1171 *ciphertext.get_mut(i).unwrap() = 0;
1172 }
1173
1174 let fails = try_decrypt_aes_gcm_256(&ciphertext, secret.as_byte_array(), nonce);
1176 assert!(fails.is_none());
1177 }
1178}