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