use std::fmt;
use crate::crypto::pbkdf2;
use crate::mnemonic::Mnemonic;
#[derive(Clone)]
pub struct Seed {
bytes: Vec<u8>,
}
impl Seed {
pub fn new(mnemonic: &Mnemonic, password: &str) -> Self {
let salt = format!("mnemonic{}", password);
let bytes = pbkdf2(mnemonic.phrase().as_bytes(), &salt);
Self { bytes }
}
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
}
}
impl AsRef<[u8]> for Seed {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl fmt::Debug for Seed {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:#X}", self)
}
}
impl fmt::LowerHex for Seed {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if f.alternate() {
f.write_str("0x")?;
}
for byte in &self.bytes {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}
impl fmt::UpperHex for Seed {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if f.alternate() {
f.write_str("0x")?;
}
for byte in &self.bytes {
write!(f, "{:02X}", byte)?;
}
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::language::Language;
#[test]
fn seed_hex_format() {
let entropy = &[
0x33, 0xE4, 0x6B, 0xB1, 0x3A, 0x74, 0x6E, 0xA4, 0x1C, 0xDD, 0xE4, 0x5C, 0x90, 0x84,
0x6A, 0x79,
];
let mnemonic = Mnemonic::from_entropy(entropy, Language::English).unwrap();
let seed = Seed::new(&mnemonic, "password");
assert_eq!(format!("{:x}", seed), "0bde96f14c35a66235478e0c16c152fcaf6301e4d9a81d3febc50879fe7e5438e6a8dd3e39bdf3ab7b12d6b44218710e17d7a2844ee9633fab0e03d9a6c8569b");
assert_eq!(format!("{:X}", seed), "0BDE96F14C35A66235478E0C16C152FCAF6301E4D9A81D3FEBC50879FE7E5438E6A8DD3E39BDF3AB7B12D6B44218710E17D7A2844EE9633FAB0E03D9A6C8569B");
assert_eq!(format!("{:#x}", seed), "0x0bde96f14c35a66235478e0c16c152fcaf6301e4d9a81d3febc50879fe7e5438e6a8dd3e39bdf3ab7b12d6b44218710e17d7a2844ee9633fab0e03d9a6c8569b");
assert_eq!(format!("{:#X}", seed), "0x0BDE96F14C35A66235478E0C16C152FCAF6301E4D9A81D3FEBC50879FE7E5438E6A8DD3E39BDF3AB7B12D6B44218710E17D7A2844EE9633FAB0E03D9A6C8569B");
}
}