1use super::{
18 Bytes, Cipher, CipherSer, CipherSerParams, Kdf, KdfSer, KdfSerParams, H256,
19};
20use serde::{
21 de::{Error, MapAccess, Visitor},
22 ser::SerializeStruct,
23 Deserialize, Deserializer, Serialize, Serializer,
24};
25use serde_json;
26use std::{fmt, str};
27
28pub type CipherText = Bytes;
29
30#[derive(Debug, PartialEq)]
31pub struct Crypto {
32 pub cipher: Cipher,
33 pub ciphertext: CipherText,
34 pub kdf: Kdf,
35 pub mac: H256,
36}
37
38impl str::FromStr for Crypto {
39 type Err = serde_json::error::Error;
40
41 fn from_str(s: &str) -> Result<Self, Self::Err> { serde_json::from_str(s) }
42}
43
44impl From<Crypto> for String {
45 fn from(c: Crypto) -> Self {
46 serde_json::to_string(&c).expect(
47 "Serialization cannot fail, because all crypto keys are strings",
48 )
49 }
50}
51
52enum CryptoField {
53 Cipher,
54 CipherParams,
55 CipherText,
56 Kdf,
57 KdfParams,
58 Mac,
59 Version,
60}
61
62impl<'a> Deserialize<'a> for CryptoField {
63 fn deserialize<D>(deserializer: D) -> Result<CryptoField, D::Error>
64 where D: Deserializer<'a> {
65 deserializer.deserialize_any(CryptoFieldVisitor)
66 }
67}
68
69struct CryptoFieldVisitor;
70
71impl<'a> Visitor<'a> for CryptoFieldVisitor {
72 type Value = CryptoField;
73
74 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
75 write!(formatter, "a valid crypto struct description")
76 }
77
78 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
79 where E: Error {
80 match value {
81 "cipher" => Ok(CryptoField::Cipher),
82 "cipherparams" => Ok(CryptoField::CipherParams),
83 "ciphertext" => Ok(CryptoField::CipherText),
84 "kdf" => Ok(CryptoField::Kdf),
85 "kdfparams" => Ok(CryptoField::KdfParams),
86 "mac" => Ok(CryptoField::Mac),
87 "version" => Ok(CryptoField::Version),
88 _ => Err(Error::custom(format!("Unknown field: '{}'", value))),
89 }
90 }
91}
92
93impl<'a> Deserialize<'a> for Crypto {
94 fn deserialize<D>(deserializer: D) -> Result<Crypto, D::Error>
95 where D: Deserializer<'a> {
96 static FIELDS: &[&str] =
97 &["id", "version", "crypto", "Crypto", "address"];
98 deserializer.deserialize_struct("Crypto", FIELDS, CryptoVisitor)
99 }
100}
101
102struct CryptoVisitor;
103
104impl<'a> Visitor<'a> for CryptoVisitor {
105 type Value = Crypto;
106
107 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
108 write!(formatter, "a valid vault crypto object")
109 }
110
111 fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
112 where V: MapAccess<'a> {
113 let mut cipher = None;
114 let mut cipherparams = None;
115 let mut ciphertext = None;
116 let mut kdf = None;
117 let mut kdfparams = None;
118 let mut mac = None;
119
120 loop {
121 match visitor.next_key()? {
122 Some(CryptoField::Cipher) => {
123 cipher = Some(visitor.next_value()?);
124 }
125 Some(CryptoField::CipherParams) => {
126 cipherparams = Some(visitor.next_value()?);
127 }
128 Some(CryptoField::CipherText) => {
129 ciphertext = Some(visitor.next_value()?);
130 }
131 Some(CryptoField::Kdf) => {
132 kdf = Some(visitor.next_value()?);
133 }
134 Some(CryptoField::KdfParams) => {
135 kdfparams = Some(visitor.next_value()?);
136 }
137 Some(CryptoField::Mac) => {
138 mac = Some(visitor.next_value()?);
139 }
140 Some(CryptoField::Version) => {
143 visitor.next_value().unwrap_or(())
144 }
145 None => {
146 break;
147 }
148 }
149 }
150
151 let cipher = match (cipher, cipherparams) {
152 (
153 Some(CipherSer::Aes128Ctr),
154 Some(CipherSerParams::Aes128Ctr(params)),
155 ) => Cipher::Aes128Ctr(params),
156 (None, _) => return Err(V::Error::missing_field("cipher")),
157 (Some(_), None) => {
158 return Err(V::Error::missing_field("cipherparams"))
159 }
160 };
161
162 let ciphertext = match ciphertext {
163 Some(ciphertext) => ciphertext,
164 None => return Err(V::Error::missing_field("ciphertext")),
165 };
166
167 let kdf = match (kdf, kdfparams) {
168 (Some(KdfSer::Pbkdf2), Some(KdfSerParams::Pbkdf2(params))) => {
169 Kdf::Pbkdf2(params)
170 }
171 (Some(KdfSer::Scrypt), Some(KdfSerParams::Scrypt(params))) => {
172 Kdf::Scrypt(params)
173 }
174 (Some(_), Some(_)) => {
175 return Err(V::Error::custom("Invalid cipherparams"))
176 }
177 (None, _) => return Err(V::Error::missing_field("kdf")),
178 (Some(_), None) => {
179 return Err(V::Error::missing_field("kdfparams"))
180 }
181 };
182
183 let mac = match mac {
184 Some(mac) => mac,
185 None => return Err(V::Error::missing_field("mac")),
186 };
187
188 let result = Crypto {
189 cipher,
190 ciphertext,
191 kdf,
192 mac,
193 };
194
195 Ok(result)
196 }
197}
198
199impl Serialize for Crypto {
200 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
201 where S: Serializer {
202 let mut crypto = serializer.serialize_struct("Crypto", 6)?;
203 match self.cipher {
204 Cipher::Aes128Ctr(ref params) => {
205 crypto.serialize_field("cipher", &CipherSer::Aes128Ctr)?;
206 crypto.serialize_field("cipherparams", params)?;
207 }
208 }
209 crypto.serialize_field("ciphertext", &self.ciphertext)?;
210 match self.kdf {
211 Kdf::Pbkdf2(ref params) => {
212 crypto.serialize_field("kdf", &KdfSer::Pbkdf2)?;
213 crypto.serialize_field("kdfparams", params)?;
214 }
215 Kdf::Scrypt(ref params) => {
216 crypto.serialize_field("kdf", &KdfSer::Scrypt)?;
217 crypto.serialize_field("kdfparams", params)?;
218 }
219 }
220
221 crypto.serialize_field("mac", &self.mac)?;
222 crypto.end()
223 }
224}