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