bitcoin_encrypted_backup/
ll.rs

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
63/// Encode content metadata, 3 variants:
64/// - <LENGTH == 0> => None
65/// - <LENGTH == 2><BIP_NUMBER> => encoding format defined in BIP<BIP_NUMBER>
66/// - <LENGTH > 2> => proprietary
67impl 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
185/// Encode following this format:
186/// <LENGTH><DERIVATION_PATH_1><DERIVATION_PATH_2><..><DERIVATION_PATH_N>
187pub 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
206/// Encode following this format:
207/// <LENGTH><INDIVIDUAL_SECRET_1><INDIVIDUAL_SECRET_2><..><INDIVIDUAL_SECRET_N>
208pub 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
224/// Encode following this format:
225/// <NONCE><LENGTH><CYPHERTEXT>
226pub 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
239/// Encode following this format
240/// <MAGIC><VERSION><DERIVATION_PATHS><INDIVIDUAL_SECRETS><ENCRYPTION><ENCRYPTED_PAYLOAD>
241/// NOTE: payload that will fail to decode can be encoded with this function, for instance with an
242/// invalid version, the inputs args must be sanitized by the caller.
243pub 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    // <MAGIC>
251    let mut out = MAGIC.as_bytes().to_vec();
252    // <VERSION>
253    out.push(version);
254    // <DERIVATION_PATHS>
255    out.append(&mut derivation_paths);
256    // <INDIVIDUAL_SECRETS>
257    out.append(&mut individual_secrets);
258    // <ENCRYPTION>
259    out.push(encryption);
260    // <ENCRYPTED_PAYLOAD>
261    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
296/// Expects a payload following this format:
297/// <MAGIC><VERSION><..>
298pub fn decode_version(bytes: &[u8]) -> Result<u8, Error> {
299    // <MAGIC>
300    let offset = init_offset(bytes, parse_magic_byte(bytes)?)?;
301    // <VERSION>
302    let (_, version) = parse_version(&bytes[offset..])?;
303    Ok(version)
304}
305
306/// Expects a payload following this format:
307/// <MAGIC><VERSION><DERIVATION_PATHS><..>
308pub fn decode_derivation_paths(bytes: &[u8]) -> Result<Vec<DerivationPath>, Error> {
309    // <MAGIC>
310    let mut offset = init_offset(bytes, parse_magic_byte(bytes)?)?;
311    // <VERSION>
312    let (incr, _) = parse_version(&bytes[offset..])?;
313    offset = increment_offset(bytes, offset, incr)?;
314    // <DERIVATION_PATHS>
315    let (_, derivation_paths) = parse_derivation_paths(&bytes[offset..])?;
316    Ok(derivation_paths)
317}
318
319/// Expects a payload following this format:
320/// <MAGIC><VERSION><DERIVATION_PATHS><INDIVIDUAL_SECRETS><ENCRYPTION><ENCRYPTED_PAYLOAD><..>
321#[allow(clippy::type_complexity)]
322pub fn decode_v1(
323    bytes: &[u8],
324) -> Result<
325    (
326        Vec<DerivationPath>, /* derivation_paths */
327        Vec<[u8; 32]>,       /* individual_secrets */
328        u8,                  /* encryption_type */
329        [u8; 12],            /* nonce */
330        Vec<u8>,             /* cyphertext */
331    ),
332    Error,
333> {
334    // <MAGIC>
335    let mut offset = init_offset(bytes, parse_magic_byte(bytes)?)?;
336    // <VERSION>
337    let (incr, _) = parse_version(&bytes[offset..])?;
338    offset = increment_offset(bytes, offset, incr)?;
339    // <DERIVATION_PATHS>
340    let (incr, derivation_paths) = parse_derivation_paths(&bytes[offset..])?;
341    offset = increment_offset(bytes, offset, incr)?;
342    // <INDIVIDUAL_SECRETS>
343    let (incr, individual_secrets) = parse_individual_secrets(&bytes[offset..])?;
344    offset = increment_offset(bytes, offset, incr)?;
345    // <ENCRYPTION>
346    let (incr, encryption_type) = parse_encryption(&bytes[offset..])?;
347    offset = increment_offset(bytes, offset, incr)?;
348    // <ENCRYPTED_PAYLOAD>
349    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    // drop duplicates keys and sort out bip341 nums
367    let keys = keys
368        .into_iter()
369        .filter(|k| *k != bip341_nums())
370        .collect::<BTreeSet<_>>();
371
372    // drop duplicates derivation paths
373    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    // NOTE:  RFC5116 define the max length of the plaintext to 2^36 - 31
386    // but for convenience we limit it to u32::MAX in order to not exceed
387    // usize::MAX on 32 bits architectures
388    // https://datatracker.ietf.org/doc/html/rfc5116#section-5.1
389    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    // <PAYLOAD> = <CONTENT_METADATA><DATA>
410    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            // <CONTENT_METADATA>
456            let (incr, content) = parse_content_metadata(&out)?;
457            // <DECRYPTED_PAYLOAD>
458            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 /* offset */, 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
495/// Expects to parse a payload of the form:
496/// <COUNT>
497/// <CHILD_COUNT><CHILD><..><CHILD>
498/// <..>
499/// <CHILD_COUNT><CHILD><..><CHILD>
500/// <..>
501pub fn parse_derivation_paths(
502    bytes: &[u8],
503) -> Result<(usize /* offset */, Vec<DerivationPath>), Error> {
504    let mut offset = init_offset(bytes, 0).map_err(|_| Error::DerivPathEmpty)?;
505    let mut derivation_paths = BTreeSet::new();
506
507    // <COUNT>
508    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            // <CHILD_COUNT>
515            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                    // <CHILD>
524                    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
543/// Expects to parse a payload of the form:
544/// <COUNT>
545/// <INDIVIDUAL_SECRET>
546/// <..>
547/// <INDIVIDUAL_SECRET>
548/// <..>
549pub fn parse_individual_secrets(
550    bytes: &[u8],
551) -> Result<(usize /* offset */, Vec<[u8; 32]>), Error> {
552    if bytes.is_empty() {
553        return Err(Error::EmptyBytes);
554    }
555    // <COUNT>
556    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        // <INDIVIDUAL_SECRET>
566        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
577/// Expects to parse a payload of the form:
578/// <NONCE><LENGTH><CYPHERTEXT>
579/// <..>
580pub fn parse_encrypted_payload(
581    bytes: &[u8],
582) -> Result<([u8; 12] /* nonce */, Vec<u8> /* cyphertext */), Error> {
583    let mut offset = init_offset(bytes, 0)?;
584    // <NONCE>
585    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    // <LENGTH>
589    let (VarInt(data_len), incr) =
590        bitcoin::consensus::deserialize_partial(&bytes[offset..]).map_err(|_| Error::VarInt)?;
591    // FIXME: in 32bit systems usize is 32 bits
592    let data_len = data_len as usize;
593    offset = increment_offset(bytes, offset, incr)?;
594    // <CYPHERTEXT>
595    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        // NOTE: the bug was in check_offset_lookahead() where substract 1 to 0 panics
633        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        // single deriv path
717        let (_, p) = parse_derivation_paths(&[0x01, 0x01, 0x00, 0x00, 0x00, 0x01]).unwrap();
718        assert_eq!(p.len(), 1);
719
720        // child number must be encoded on 4 bytes
721        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        // empty childs
729        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        // empty bytes
736        let fail = parse_individual_secrets(&[]).unwrap_err();
737        assert_eq!(fail, Error::EmptyBytes);
738
739        // empty vector
740        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        // single secret
747        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        // multiple secrets
753        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        // empty bytes must fail
764        assert!(parse_content_metadata(&[]).is_err());
765        // None
766        let (_, c) = parse_content_metadata(&[0]).unwrap();
767        assert_eq!(c, Content::None);
768        // len == 1 fails
769        assert!(parse_content_metadata(&[1, 0]).is_err());
770        // BIP380
771        let (_, c) = parse_content_metadata(&[2, 0x01, 0x7c]).unwrap();
772        assert_eq!(c, Content::Bip380);
773        // BIP388
774        let (_, c) = parse_content_metadata(&[2, 0x01, 0x84]).unwrap();
775        assert_eq!(c, Content::Bip388);
776        // BIP329
777        let (_, c) = parse_content_metadata(&[2, 0x01, 0x49]).unwrap();
778        assert_eq!(c, Content::Bip329);
779        // Arbitrary BIPs
780        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        // Proprietary
785        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        // Proprietary
792        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        // BIP 380
796        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        // BIP 388
803        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        // BIP 329
810        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            // NOTE: order of derivation paths is reverted here as during parsing they are stored
887            // in an BTreeSet in order to avoid duplicates
888            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        // <MAGIC>
1023        let mut expected = MAGIC.as_bytes().to_vec();
1024        // <VERSION>
1025        expected.append(&mut vec![0x01]);
1026        // <DERIVATION_PATHS>
1027        expected.append(&mut vec![
1028            0x01, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09,
1029        ]);
1030        // <INDIVIDUAL_SECRETS>
1031        expected.append(&mut [0x01; 33].to_vec());
1032        // <ENCRYPTION>
1033        expected.append(&mut vec![0x01]);
1034        // <ENCRYPTED_PAYLOAD>
1035        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        // Empty keyvector must fail
1052        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        // > 255 keys must fail
1058        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        // Empty payload must fail
1074        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        // > 255 deriv path must fail
1079        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        // decrypting with secret success
1135        let _ = try_decrypt_aes_gcm_256(&ciphertext, secret.as_byte_array(), nonce).unwrap();
1136        // decrypting with wrong secret fails
1137        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        // decrypting with correct nonce success
1150        let _ = try_decrypt_aes_gcm_256(&ciphertext, secret.as_byte_array(), nonce).unwrap();
1151        // decrypting with wrong nonce fails
1152        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        // decrypting with secret success
1166        let _ = try_decrypt_aes_gcm_256(&ciphertext, secret.as_byte_array(), nonce).unwrap();
1167
1168        // corrupting the ciphertext
1169        let offset = ciphertext.len() - 10;
1170        for i in offset..offset + 5 {
1171            *ciphertext.get_mut(i).unwrap() = 0;
1172        }
1173
1174        // decryption must then fails
1175        let fails = try_decrypt_aes_gcm_256(&ciphertext, secret.as_byte_array(), nonce);
1176        assert!(fails.is_none());
1177    }
1178}