1use serde::{Deserialize, Serialize};
2use uuid::Uuid;
3
4#[derive(Debug, Deserialize, Serialize)]
5pub struct KeyStore {
8 pub version: u8,
10 pub id: Uuid,
12 pub address: Option<String>,
14 pub label: Option<String>,
16 pub(crate) crypto: CryptoData,
18}
19
20#[derive(Debug, Deserialize, Serialize)]
21pub struct CryptoData {
23 pub cipher: String,
24 pub cipherparams: CipherParams,
25 #[serde(
26 serialize_with = "hex::serde::serialize",
27 deserialize_with = "hex::serde::deserialize"
28 )]
29 pub ciphertext: Vec<u8>,
30 pub kdf: KdfType,
31 pub kdfparams: KdfParamsType,
32 #[serde(
33 serialize_with = "hex::serde::serialize",
34 deserialize_with = "hex::serde::deserialize"
35 )]
36 pub mac: Vec<u8>,
37}
38
39#[derive(Debug, Deserialize, Serialize)]
40pub struct CipherParams {
42 #[serde(
43 serialize_with = "hex::serde::serialize",
44 deserialize_with = "hex::serde::deserialize"
45 )]
46 pub iv: Vec<u8>,
47}
48
49#[derive(Debug, Deserialize, PartialEq, Serialize)]
50#[serde(rename_all = "lowercase")]
51pub enum KdfType {
53 Pbkdf2,
54 Scrypt,
55}
56
57#[derive(Debug, Deserialize, PartialEq, Serialize)]
58#[serde(untagged)]
59pub enum KdfParamsType {
61 Pbkdf2 {
62 c: u32,
63 dklen: u8,
64 prf: String,
65 #[serde(
66 serialize_with = "hex::serde::serialize",
67 deserialize_with = "hex::serde::deserialize"
68 )]
69 salt: Vec<u8>,
70 },
71 Scrypt {
72 dklen: u8,
73 n: u32,
74 p: u32,
75 r: u32,
76 #[serde(
77 serialize_with = "hex::serde::serialize",
78 deserialize_with = "hex::serde::deserialize"
79 )]
80 salt: Vec<u8>,
81 },
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87 use anyhow::Result;
88
89 #[test]
90 fn test_deserialize_pbkdf2() -> Result<()> {
91 let data = r#"
92 {
93 "crypto" : {
94 "cipher" : "aes-128-ctr",
95 "cipherparams" : {
96 "iv" : "6087dab2f9fdbbfaddc31a909735c1e6"
97 },
98 "ciphertext" : "5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46",
99 "kdf" : "pbkdf2",
100 "kdfparams" : {
101 "c" : 262144,
102 "dklen" : 32,
103 "prf" : "hmac-sha256",
104 "salt" : "ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd"
105 },
106 "mac" : "517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2"
107 },
108 "id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6",
109 "version" : 3
110 }"#;
111 let keystore: KeyStore = serde_json::from_str(data)?;
112 assert_eq!(keystore.version, 3);
113 assert_eq!(
114 keystore.id,
115 Uuid::parse_str("3198bc9c-6672-5ab3-d995-4942343ae5b6")?
116 );
117 assert_eq!(keystore.crypto.cipher, "aes-128-ctr");
118 assert_eq!(
119 keystore.crypto.cipherparams.iv,
120 hex::decode("6087dab2f9fdbbfaddc31a909735c1e6")?
121 );
122 assert_eq!(
123 keystore.crypto.ciphertext,
124 hex::decode("5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46")?
125 );
126 assert_eq!(keystore.crypto.kdf, KdfType::Pbkdf2);
127 assert_eq!(
128 keystore.crypto.kdfparams,
129 KdfParamsType::Pbkdf2 {
130 c: 262144,
131 dklen: 32,
132 prf: String::from("hmac-sha256"),
133 salt: hex::decode(
134 "ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd"
135 )?,
136 }
137 );
138 assert_eq!(
139 keystore.crypto.mac,
140 hex::decode("517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2")?
141 );
142 Ok(())
143 }
144
145 #[test]
146 fn test_deserialize_scrypt() -> Result<()> {
147 let data = r#"
148 {
149 "crypto" : {
150 "cipher" : "aes-128-ctr",
151 "cipherparams" : {
152 "iv" : "83dbcc02d8ccb40e466191a123791e0e"
153 },
154 "ciphertext" : "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c",
155 "kdf" : "scrypt",
156 "kdfparams" : {
157 "dklen" : 32,
158 "n" : 262144,
159 "p" : 8,
160 "r" : 1,
161 "salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19"
162 },
163 "mac" : "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097"
164 },
165 "id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6",
166 "version" : 3
167 }"#;
168 let keystore: KeyStore = serde_json::from_str(data)?;
169 assert_eq!(keystore.version, 3);
170 assert_eq!(
171 keystore.id,
172 Uuid::parse_str("3198bc9c-6672-5ab3-d995-4942343ae5b6")?
173 );
174 assert_eq!(keystore.crypto.cipher, "aes-128-ctr");
175 assert_eq!(
176 keystore.crypto.cipherparams.iv,
177 hex::decode("83dbcc02d8ccb40e466191a123791e0e")?
178 );
179 assert_eq!(
180 keystore.crypto.ciphertext,
181 hex::decode("d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c")?
182 );
183 assert_eq!(keystore.crypto.kdf, KdfType::Scrypt);
184 assert_eq!(
185 keystore.crypto.kdfparams,
186 KdfParamsType::Scrypt {
187 dklen: 32,
188 n: 262144,
189 p: 8,
190 r: 1,
191 salt: hex::decode(
192 "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19"
193 )?,
194 }
195 );
196 assert_eq!(
197 keystore.crypto.mac,
198 hex::decode("2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097")?
199 );
200 Ok(())
201 }
202}