dark_crystal_web3_core/secret/
mod.rs1use crate::secret::bip39::{bytes_to_mnemonic, mnemonic_to_bytes};
4use std::str::Utf8Error;
5pub mod bip39;
6
7#[derive(Debug, PartialEq)]
10pub enum Secret {
11 Raw(Vec<u8>), Utf8(String), Bip39(String), }
15impl Secret {
18 pub fn from_bytes(input: Vec<u8>) -> Result<Secret, EncodingError> {
20 match input[0] {
21 0 => Ok(Secret::Raw(input[1..].to_vec())),
22 1 => Ok(Secret::Utf8(std::str::from_utf8(&input[1..])?.to_string())),
23 2 => Ok(Secret::Bip39(bytes_to_mnemonic(&input[1..].to_vec())?)),
24 _ => Err(EncodingError {}),
25 }
26 }
27
28 pub fn to_bytes(&self) -> Result<Vec<u8>, EncodingError> {
30 fn add_type(type_code: u8, input: Vec<u8>) -> Vec<u8> {
31 let mut output: Vec<u8> = vec![type_code];
32 output.extend(input);
33 output
34 }
35
36 match self {
37 Secret::Raw(bytes) => Ok(add_type(0, bytes.to_vec())),
38 Secret::Utf8(string) => Ok(add_type(1, string.as_bytes().to_vec())),
39 Secret::Bip39(string) => Ok(add_type(2, mnemonic_to_bytes(string)?)),
40 }
41 }
42
43 pub fn detect_from_string(input: String) -> Secret {
44 match mnemonic_to_bytes(&input) {
45 Ok(_) => Secret::Bip39(input),
46 Err(_) => match hex::decode(&input) {
47 Ok(bytes) => Secret::Raw(bytes),
48 Err(_) => Secret::Utf8(input),
49 },
50 }
51 }
52}
53
54#[derive(Debug)]
56pub struct EncodingError {}
57
58impl From<Utf8Error> for EncodingError {
59 fn from(_error: std::str::Utf8Error) -> Self {
60 EncodingError {}
61 }
62}
63
64impl From<::bip39::Error> for EncodingError {
65 fn from(_error: ::bip39::Error) -> Self {
66 EncodingError {}
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn encode_secrets() {
76 assert_eq!(
77 vec![0, 98, 108, 97, 104],
78 Secret::Raw(b"blah".to_vec()).to_bytes().unwrap()
79 );
80
81 assert_eq!(
82 vec![1, 98, 108, 97, 104],
83 Secret::Utf8("blah".to_string()).to_bytes().unwrap()
84 );
85
86 assert_eq!(
87 vec![2, 208, 109, 216, 221, 151, 58, 13, 74, 112, 181, 62, 174, 181, 203, 225, 153],
88 Secret::Bip39(
89 "spare human danger common patch pioneer security pond push purity wear crane"
90 .to_string()
91 )
92 .to_bytes()
93 .unwrap()
94 );
95 }
96
97 #[test]
98 fn decode_secrets() {
99 assert_eq!(
100 Secret::from_bytes(vec![0, 98, 108, 97, 104]).unwrap(),
101 Secret::Raw(b"blah".to_vec())
102 );
103
104 assert_eq!(
105 Secret::from_bytes(vec![1, 98, 108, 97, 104]).unwrap(),
106 Secret::Utf8("blah".to_string())
107 );
108
109 assert_eq!(
110 Secret::from_bytes(vec![
111 2, 208, 109, 216, 221, 151, 58, 13, 74, 112, 181, 62, 174, 181, 203, 225, 153
112 ])
113 .unwrap(),
114 Secret::Bip39(
115 "spare human danger common patch pioneer security pond push purity wear crane"
116 .to_string()
117 )
118 );
119 }
120
121 #[test]
122 fn detect_string() {
123 assert_eq!(
124 Secret::detect_from_string("blah".to_string()),
125 Secret::Utf8("blah".to_string())
126 );
127
128 assert_eq!(
129 Secret::detect_from_string("deadbeef".to_string()),
130 Secret::Raw(hex::decode("deadbeef").unwrap())
131 );
132
133 assert_eq!(
134 Secret::detect_from_string("dead beef".to_string()),
135 Secret::Utf8("dead beef".to_string())
136 );
137
138 assert_eq!(
139 Secret::detect_from_string(
140 "spare human danger common patch pioneer security pond push purity wear crane"
141 .to_string()
142 ),
143 Secret::Bip39(
144 "spare human danger common patch pioneer security pond push purity wear crane"
145 .to_string()
146 )
147 );
148 }
149}