prople_did_core/doc/
mod.rs1use multibase;
23
24use rst_common::standard::serde::{self, Deserialize, Serialize};
25use rst_common::standard::serde_json;
26
27use prople_crypto::ecdh::pubkey::PublicKey as ECDHPubKey;
28use prople_crypto::eddsa::pubkey::PubKey as EdDSAPubKey;
29use prople_crypto::types::ByteHex;
30
31use crate::types::*;
32
33pub trait ToDoc {
34 fn to_doc(&self) -> Doc;
35}
36
37#[derive(Debug)]
38pub enum PublicKeyDecoded {
39 EdDSA(EdDSAPubKey),
40 ECDH(ECDHPubKey),
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize)]
46#[serde(crate = "self::serde")]
47pub struct Primary {
48 pub id: DIDSyntax,
49 pub controller: DIDController,
50
51 #[serde(rename = "type")]
52 pub verification_type: DIDVerificationKeyType,
53
54 #[serde(rename = "publicKeyMultibase")]
55 pub multibase: DIDMultibase,
56}
57
58impl Primary {
59 pub fn decode_pub_key(&self) -> Result<PublicKeyDecoded, DIDError> {
60 match self.verification_type.to_owned().as_str() {
61 VERIFICATION_TYPE_ED25519 => {
62 let public_key = self.decode_pub_key_verificaiton()?;
63 Ok(PublicKeyDecoded::EdDSA(public_key))
64 }
65 VERIFICATION_TYPE_X25519 => {
66 let public_key = self.decode_pub_key_agreement()?;
67 Ok(PublicKeyDecoded::ECDH(public_key))
68 }
69 _ => Err(DIDError::DecodePubKeyError(
70 "unknown verification type".to_string(),
71 )),
72 }
73 }
74
75 fn decode_pub_key_verificaiton(&self) -> Result<EdDSAPubKey, DIDError> {
76 let (_, pubkey_bytes) = multibase::decode(&self.multibase).map_err(|_| {
77 DIDError::DecodePubKeyError(
78 "unable to decode encoded multibase to EDDSA public key".to_string(),
79 )
80 })?;
81
82 let pubkey_string = String::from_utf8(pubkey_bytes).map_err(|_| {
83 DIDError::DecodePubKeyError("unable convert public key to string".to_string())
84 })?;
85
86 let pubkey = EdDSAPubKey::from_hex(ByteHex::from(pubkey_string))
87 .map_err(|_| DIDError::DecodePubKeyError("unable to restore public key".to_string()))?;
88 Ok(pubkey)
89 }
90
91 fn decode_pub_key_agreement(&self) -> Result<ECDHPubKey, DIDError> {
92 let (_, pubkey_bytes) = multibase::decode(&self.multibase).map_err(|_| {
93 DIDError::DecodePubKeyError(
94 "unable to decode encoded multibase to ECDH public key".to_string(),
95 )
96 })?;
97
98 let pubkey_string = String::from_utf8(pubkey_bytes).map_err(|_| {
99 DIDError::DecodePubKeyError("unable convert public key to string".to_string())
100 })?;
101
102 let pubkey = ECDHPubKey::from_hex(ByteHex::from(pubkey_string))
103 .map_err(|_| DIDError::DecodePubKeyError("unable to restore public key".to_string()))?;
104
105 Ok(pubkey)
106 }
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
114#[serde(crate = "self::serde")]
115pub struct Doc {
116 #[serde(rename = "@context")]
117 pub context: Vec<DIDContext>,
118
119 pub id: DIDSyntax,
120
121 #[serde(skip_serializing_if = "Option::is_none")]
122 pub authentication: Option<Vec<Primary>>,
123
124 #[serde(skip_serializing_if = "Option::is_none")]
125 #[serde(rename = "capabilityInvocation")]
126 pub cap_invoke: Option<Vec<Primary>>,
127
128 #[serde(skip_serializing_if = "Option::is_none")]
129 #[serde(rename = "capabilityDelegation")]
130 pub cap_delegate: Option<Vec<Primary>>,
131
132 #[serde(skip_serializing_if = "Option::is_none")]
133 #[serde(rename = "assertionMethod")]
134 pub assertion: Option<Vec<Primary>>,
135}
136
137impl Doc {
138 pub fn generate(did: String) -> Self {
139 let context = vec![CONTEXT_DEFAULT.to_string()];
140 Self {
141 context,
142 id: did,
143 authentication: None,
144 cap_delegate: None,
145 cap_invoke: None,
146 assertion: None,
147 }
148 }
149
150 pub fn add_context(&mut self, context: DIDContext) -> &mut Self {
151 self.context.push(context);
152 self
153 }
154
155 pub fn add_assertion(&mut self, assertion: Primary) -> &mut Self {
156 if let Some(ref mut assertions) = self.assertion {
157 assertions.push(assertion.clone())
158 }
159
160 if self.assertion.is_none() {
161 self.assertion = Some(vec![assertion.clone()]);
162 }
163
164 self
165 }
166
167 pub fn add_authentication(&mut self, auth: Primary) -> &mut Self {
168 if let Some(ref mut authentication) = self.authentication {
169 authentication.push(auth.clone())
170 }
171
172 if self.authentication.is_none() {
173 self.authentication = Some(vec![auth.clone()]);
174 }
175
176 self
177 }
178
179 pub fn add_cap_delegate(&mut self, delegate: Primary) -> &mut Self {
180 if let Some(ref mut cap_delegate) = self.cap_delegate {
181 cap_delegate.push(delegate.clone())
182 }
183
184 if self.cap_delegate.is_none() {
185 self.cap_delegate = Some(vec![delegate.clone()]);
186 }
187
188 self
189 }
190
191 pub fn add_cap_invoke(&mut self, invoke: Primary) -> &mut Self {
192 if let Some(ref mut cap_invoke) = self.cap_invoke {
193 cap_invoke.push(invoke.clone())
194 }
195
196 if self.cap_invoke.is_none() {
197 self.cap_invoke = Some(vec![invoke.clone()]);
198 }
199
200 self
201 }
202}
203
204impl ToJSON for Doc {
205 fn to_json(&self) -> Result<JSONValue, DIDError> {
206 let jsonstr = serde_json::to_string(self)
207 .map_err(|err| DIDError::GenerateDocError(err.to_string()))?;
208 Ok(JSONValue::from(jsonstr))
209 }
210}
211
212impl Validator for Doc {
213 fn validate(&self) -> Result<(), DIDError> {
214 if self.id.is_empty() {
215 return Err(DIDError::ValidateError("[doc]: missing id".to_string()));
216 }
217
218 if self.context.is_empty() {
219 return Err(DIDError::ValidateError(
220 "[doc]: at least one context must be filled".to_string(),
221 ));
222 }
223
224 Ok(())
225 }
226}
227
228#[cfg(test)]
229mod tests {
230 use super::*;
231
232 use prople_crypto::eddsa::keypair::KeyPair;
233
234 use crate::keys::{AgreementKey, VerificationKey};
235
236 #[test]
237 fn test_add_assertion() {
238 let primary = Primary {
239 id: "id".to_string(),
240 controller: "controller".to_string(),
241 verification_type: "verification".to_string(),
242 multibase: "multibase".to_string(),
243 };
244
245 let mut doc = Doc::generate("test".to_string());
246 let json = doc
247 .add_assertion(primary.clone())
248 .add_assertion(primary.clone())
249 .to_json();
250
251 assert!(!json.is_err());
252
253 let fromjson: Result<Doc, _> =
254 serde_json::from_str(json.as_ref().unwrap().to_string().as_str());
255 assert!(!fromjson.as_ref().is_err());
256
257 let doc = fromjson.unwrap();
258 assert!(doc.authentication.is_none());
259 assert!(doc.cap_delegate.is_none());
260 assert!(doc.cap_invoke.is_none());
261 assert_eq!(doc.assertion.unwrap().len(), 2);
262 }
263
264 #[test]
265 fn test_validation_error() {
266 let mut doc = Doc::generate("test".to_string());
267 doc.context = vec![];
268
269 let validation = doc.validate();
270 assert!(validation.is_err());
271 }
272
273 #[test]
274 fn test_validation_success() {
275 let doc = Doc::generate("test".to_string());
276 let validation = doc.validate();
277 assert!(validation.is_ok());
278 }
279
280 #[test]
281 fn test_decode_public_key_eddsa() {
282 let key = VerificationKey::new();
283 let pairs = key.generate();
284
285 let primary = Primary {
286 id: "id".to_string(),
287 controller: "controller".to_string(),
288 verification_type: VERIFICATION_TYPE_ED25519.to_string(),
289 multibase: pairs.clone().pub_key,
290 };
291
292 let decoded = primary.decode_pub_key();
293 assert!(!decoded.is_err());
294
295 let decoded_pub_key = decoded.unwrap();
296 assert!(matches!(decoded_pub_key, PublicKeyDecoded::EdDSA(_)));
297
298 match decoded_pub_key {
299 PublicKeyDecoded::EdDSA(pubkey) => {
300 let privkey_pem = pairs.priv_key.to_pem().unwrap();
301 let keypair_regenerated = KeyPair::from_pem(privkey_pem).unwrap();
302 let pubkey_regenerated = keypair_regenerated.pub_key();
303 assert_eq!(pubkey.to_hex(), pubkey_regenerated.to_hex())
304 }
305 _ => panic!("unknown"),
306 }
307 }
308
309 #[test]
310 fn test_decode_public_key_ecdh() {
311 let key = AgreementKey::new();
312 let pairs = key.generate();
313
314 let primary = Primary {
315 id: "id".to_string(),
316 controller: "controller".to_string(),
317 verification_type: VERIFICATION_TYPE_X25519.to_string(),
318 multibase: pairs.clone().pub_key,
319 };
320
321 let decoded = primary.decode_pub_key();
322 assert!(!decoded.is_err());
323
324 let decoded_pub_key = decoded.unwrap();
325 assert!(matches!(decoded_pub_key, PublicKeyDecoded::ECDH(_)));
326
327 match decoded_pub_key {
328 PublicKeyDecoded::ECDH(pubkey) => {
329 let keypair = pairs.priv_key;
330 assert_eq!(keypair.pub_key().to_hex(), pubkey.to_hex());
331 }
332 _ => panic!("unknown"),
333 }
334 }
335
336 #[test]
337 fn test_decode_public_key_invalid_type() {
338 let primary = Primary {
339 id: "id".to_string(),
340 controller: "controller".to_string(),
341 verification_type: "unknown".to_string(),
342 multibase: "".to_string(),
343 };
344
345 let decoded = primary.decode_pub_key();
346 assert!(decoded.is_err());
347 assert!(matches!(
348 decoded.unwrap_err(),
349 DIDError::DecodePubKeyError(_)
350 ))
351 }
352}