1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// grrr clippy... you cannot specify extra bounds with the async fn syntax...
#![allow(clippy::manual_async_fn)]
// default implementations don't always make sense...
#![allow(clippy::new_without_default)]
#![deny(missing_docs)]
#![deny(unsafe_code)]

//! SeedBundle parsing and generation library.
//!
//! [![Project](https://img.shields.io/badge/project-holochain-blue.svg?style=flat-square)](http://holochain.org/)
//! [![Forum](https://img.shields.io/badge/chat-forum%2eholochain%2enet-blue.svg?style=flat-square)](https://forum.holochain.org)
//! [![Chat](https://img.shields.io/badge/chat-chat%2eholochain%2enet-blue.svg?style=flat-square)](https://chat.holochain.org)
//!
//! [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
//! [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
//!
//! ### Links
//!
//! - [Git Repo - https://github.com/holochain/lair](https://github.com/holochain/lair)
//! - [API Documentation - https://docs.rs/hc_seed_bundle](https://docs.rs/hc_seed_bundle)
//! - [Javascript Implementation - https://holochain.github.io/hcSeedBundle/](https://holochain.github.io/hcSeedBundle/)
//!
//! ### Rationale
//!
//! - Applications like Holochain have different requirements than classic
//! blockchain systems in terms of key management. Namely there is no need
//! for read-only or hardened wallets (Holochain handles these concepts
//! through capabilities and membranes).
//! - Applications like Holochain still have need of hierarchy and determinism
//! in key (or in this case seed) derivation.
//! - Since we're using libsodium for hashing, signature, and encryption
//! algorithms, let's use it for derivation as well.
//! - To be psychologically compatible with the
//! [Bitcoin "HD Wallet" spec](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki),
//! we will do away with the "context" part of sodium KDF by always setting
//! it to `b"SeedBndl"` and focusing on the `subkey_id` and can declare a
//! chain of subsequent derivations of a 32 byte seed in the form
//! `m/68/1/65/8` where we apply `subkey_id`s 68, 1, 65, then 8 in turn.
//!
//! ### hcSeedBundle Encoding Spec
//!
//! Encoded in [MSGPACK](https://msgpack.org/index.html) binary format.
//!
//! To better facilitate rust/javascript interoperability, the rust library
//! will treat msgpack "ext" types as binary data.
//!
//! #### SeedBundle
//!
//! ```text
//! // seed_bundle is a top-level array
//! 'seed_bundle':array [
//!   // literal 'hcsb0' version / heuristic marker
//!   'id_ver':str,
//!
//!   // list of SeedCiphers define how to decrypt
//!   'cipher_list':array [
//!     'cipher_1':SeedCipher,
//!     'cipher_2':SeedCipher,
//!     // ..
//!     'cipher_N':SeedCipher,
//!   ],
//!
//!   // associated application data
//!   'app_data':bin,
//! ]
//! ```
//!
//! #### SeedCipher::PwHash
//!
//! ```text
//! // the PwHash type SeedCipher defines a straight-forward
//! // pwhash secret that is use to secretstream encrypt a seed
//! 'seed_cipher':array [
//!   // literal 'pw' indicates the pw hash cipher type
//!   'type':str,
//!
//!   // argon2id 16 byte salt
//!   'salt':bin,
//!
//!   // argon2id mem limit capped to u32 for js compatibility
//!   'mem_limit':int,
//!
//!   // argon2id ops limit capped to u32 for js compatibility
//!   'ops_limit':int,
//!
//!   // secretstream 24 byte header
//!   'header':bin,
//!
//!   // secretstream 49 byte cipher
//!   'cipher':bin,
//! ]
//! ```
//!
//! #### SeedCipher::SecurityQuestions
//!
//! ```text
//! // Security Questions SeedCipher defines a pwhash cipher
//! // based on concatonating 3 answers that are lcased/trimmed
//! 'seed_cipher':array [
//!   // literal 'qa' indicates the security question cipher type
//!   'type':str,
//!
//!   // argon2id 16 byte salt
//!   'salt':bin,
//!
//!   // argon2id mem limit capped to u32 for js compatibility
//!   'mem_limit':int,
//!
//!   // argon2id ops limit capped to u32 for js compatibility
//!   'ops_limit':int,
//!
//!   // the first security question to be answered
//!   'question_1':str,
//!
//!   // the second security question to be answered
//!   'question_2':str,
//!
//!   // the third security question to be answered
//!   'question_3':str,
//!
//!   // secretstream 24 byte header
//!   'header':bin,
//!
//!   // secretstream 49 byte cipher
//!   'cipher':bin,
//! ]
//! ```
//!
//!### Algorithms
//!
//! - `sodium_kdf32` - seed derivation
//!   - set to output 32 bytes (`[32 byte sub-seed]`)
//!   - context bytes - fixed `b"SeedBndl"`
//!   - subkey_id clamped to u32 to better support javascript
//! - `argon2id32` - generates secret for seed secretstream encryption
//!   - set to output 32 bytes (`[32 secret bytes]`)
//!   - salt: `[16 salt bytes from bundle]`
//!   - mem_limit: default `MODERATE`
//!   - ops_limit: default `MODERATE`
//!   - passphrase: user-supplied
//! - `secretstream_xchacha20poly1305`
//!   - single `push_final/pull_final` with entire contents

/// re-exported dependencies
pub mod dependencies {
    pub use futures;
    pub use one_err;
    pub use rmp_serde;
    pub use rmpv;
    pub use serde;
    pub use serde_bytes;
    pub use sodoken;
}

mod seed_cipher;
pub use seed_cipher::*;

mod unlocked_seed_bundle;
pub use unlocked_seed_bundle::*;