bip39/
seed.rs

1use crypto::pbkdf2;
2use mnemonic::Mnemonic;
3use std::fmt;
4
5/// The secret value used to derive HD wallet addresses from a [`Mnemonic`][Mnemonic] phrase.
6///
7/// Because it is not possible to create a [`Mnemonic`][Mnemonic] instance that is invalid, it is
8/// therefore impossible to have a [`Seed`][Seed] instance that is invalid. This guarantees that only
9/// a valid, intact mnemonic phrase can be used to derive HD wallet addresses.
10///
11/// To get the raw byte value use [`Seed::as_bytes()`][Seed::as_bytes()]. These can be used to derive
12/// HD wallet addresses using another crate (deriving HD wallet addresses is outside the scope of this
13/// crate and the BIP39 standard).
14///
15/// [Mnemonic]: ./mnemonic/struct.Mnemonic.html
16/// [Seed]: ./seed/struct.Seed.html
17/// [Seed::as_bytes()]: ./seed/struct.Seed.html#method.as_bytes
18
19#[derive(Clone)]
20pub struct Seed {
21    bytes: Vec<u8>,
22}
23
24impl Seed {
25    /// Generates the seed from the [`Mnemonic`][Mnemonic] and the password.
26    ///
27    /// [Mnemonic]: ./mnemonic/struct.Mnemonic.html
28    pub fn new(mnemonic: &Mnemonic, password: &str) -> Self {
29        let salt = format!("mnemonic{}", password);
30        let bytes = pbkdf2(mnemonic.entropy(), &salt);
31
32        Self {
33            bytes,
34        }
35    }
36
37    /// 通过对比 EtherJs 中的代码,生成种子是直接使用的 mnemonic 而不是 entropy
38    pub fn new_cpc(mnemonic: &Mnemonic, password: &str) -> Self {
39        let salt = format!("mnemonic{}", password);
40        let bytes = pbkdf2(mnemonic.phrase().as_bytes(), &salt);
41
42        Self {
43            bytes,
44        }
45    }
46
47    /// Get the seed value as a byte slice
48    pub fn as_bytes(&self) -> &[u8] {
49        &self.bytes
50    }
51}
52
53impl AsRef<[u8]> for Seed {
54    fn as_ref(&self) -> &[u8] {
55        self.as_bytes()
56    }
57}
58
59impl fmt::Debug for Seed {
60    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61        write!(f, "{:#X}", self)
62    }
63}
64
65impl fmt::LowerHex for Seed {
66    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67        if f.alternate() {
68            f.write_str("0x")?;
69        }
70
71        for byte in &self.bytes {
72            write!(f, "{:x}", byte)?;
73        }
74
75        Ok(())
76    }
77}
78
79impl fmt::UpperHex for Seed {
80    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81        if f.alternate() {
82            f.write_str("0x")?;
83        }
84
85        for byte in &self.bytes {
86            write!(f, "{:X}", byte)?;
87        }
88
89        Ok(())
90    }
91}