did_utils/
didkit.rs

1use serde_json::Value;
2
3use crate::{
4    didcore::{Document, Service, VerificationMethod, VerificationMethodType},
5    ldmodel::Context,
6};
7
8impl VerificationMethod {
9    /// Creates a new `VerificationMethod` instance.
10    ///
11    /// # Arguments
12    ///
13    /// * `id` - A unique identifier for the verification method.
14    /// * `key_type` - The type of key used in the verification method.
15    /// * `controller` - The identifier of the controller of the verification method.
16    ///
17    /// # Returns
18    ///
19    /// * A new instance of `VerificationMethod`.
20    pub fn new(id: String, key_type: String, controller: String) -> Self {
21        Self {
22            id,
23            key_type,
24            controller,
25            revoked: None,
26            public_key: None,
27            private_key: None,
28            additional_properties: None,
29        }
30    }
31}
32
33impl Service {
34    /// Creates a new `Service` instance.
35    ///
36    /// # Arguments
37    ///
38    /// * `id` - A unique identifier for the service.
39    /// * `service_type` - The type of service.
40    /// * `service_endpoint` - The endpoint where the service can be accessed.
41    ///
42    /// # Returns
43    ///
44    /// * A new instance of `Service`.
45    pub fn new(id: String, service_type: String, service_endpoint: Value) -> Self {
46        Self {
47            id,
48            service_type,
49            service_endpoint,
50            additional_properties: None,
51        }
52    }
53}
54
55impl Document {
56    /// Creates a new `Document` instance with only the required members.
57    ///
58    /// # Arguments
59    ///
60    /// * `context` - The context defining the vocabulary for the document.
61    /// * `id` - A unique identifier for the DID document.
62    ///
63    /// # Returns
64    ///
65    /// * A new instance of `Document`.
66    pub fn new(context: Context, id: String) -> Self {
67        Self {
68            id,
69            context,
70            also_known_as: None,
71            controller: None,
72            authentication: Some(vec![]),
73            assertion_method: Some(vec![]),
74            capability_delegation: None,
75            capability_invocation: None,
76            key_agreement: Some(vec![]),
77            verification_method: Some(vec![]),
78            service: Some(vec![]),
79            proof: None,
80            additional_properties: None,
81        }
82    }
83
84    /// Creates a new `Document` instance with frequent members.
85    ///
86    /// # Arguments
87    ///
88    /// * `context` - The context defining the vocabulary for the document.
89    /// * `id` - A unique identifier for the DID document.
90    /// * `authentication` - An optional vector of `Authentication` methods.
91    /// * `assertion_method` - An optional vector of `AssertionMethod` methods.
92    /// * `key_agreement` - An optional vector of `KeyAgreement` methods.
93    /// * `verification_method` - An optional vector of `VerificationMethod` methods.
94    /// * `service` - An optional vector of `Service` instances.
95    ///
96    /// # Returns
97    ///
98    /// * A new instance of `Document`.
99    pub fn new_full(
100        context: Context,
101        id: String,
102        authentication: Option<Vec<VerificationMethodType>>,
103        assertion_method: Option<Vec<VerificationMethodType>>,
104        key_agreement: Option<Vec<VerificationMethodType>>,
105        verification_method: Option<Vec<VerificationMethod>>,
106        service: Option<Vec<Service>>,
107    ) -> Self {
108        Self {
109            id,
110            context,
111            also_known_as: None,
112            controller: None,
113            authentication,
114            assertion_method,
115            capability_delegation: None,
116            capability_invocation: None,
117            key_agreement,
118            verification_method,
119            service,
120            proof: None,
121            additional_properties: None,
122        }
123    }
124}
125
126#[cfg(test)]
127pub mod tests {
128    use super::*;
129    use crate::crypto::{
130        Ed25519KeyPair, {Generate, KeyMaterial},
131    };
132    use crate::didcore::KeyFormat::Multibase;
133    use multibase::Base::Base58Btc;
134
135    #[test]
136    fn test_document_new() {
137        let context = Context::SingleString("https://www.w3.org/ns/did/v1".to_owned());
138        let id = "did:example:123456789abcdefghi".to_string();
139        let document = Document::new(context, id);
140        let canonicalized = json_canon::to_string(&document).unwrap();
141        assert_eq!(
142            canonicalized,
143            r#"{"@context":"https://www.w3.org/ns/did/v1","assertionMethod":[],"authentication":[],"id":"did:example:123456789abcdefghi","keyAgreement":[],"service":[],"verificationMethod":[]}"#
144        );
145    }
146
147    #[test]
148    fn test_document_new_full() {
149        let context = Context::SingleString("https://www.w3.org/ns/did/v1".to_owned());
150        let id = "did:example:123456789abcdefghi".to_string();
151
152        // Generate key for verification method
153        let my_string = String::from("Sample seed bytes of thirtytwo!b");
154        let seed: &[u8] = my_string.as_bytes();
155        let eddsa_key_pair = Ed25519KeyPair::new_with_seed(seed).unwrap();
156        let ecdh_key_pair = eddsa_key_pair.get_x25519().unwrap();
157
158        let mut private_eddsa_vm = VerificationMethod::new(
159            "did:example:123456789abcdefghi#keys-1".to_string(),
160            "Ed25519VerificationKey2018".to_string(),
161            "did:example:123456789abcdefghi".to_string(),
162        );
163        let mut public_eddsa_vm = private_eddsa_vm.clone();
164
165        let eddsa_private_key_multibase = multibase::encode(Base58Btc, eddsa_key_pair.private_key_bytes().unwrap());
166        private_eddsa_vm.private_key = Some(Multibase(eddsa_private_key_multibase));
167
168        let eddsa_public_key_multibase = multibase::encode(Base58Btc, eddsa_key_pair.public_key_bytes().unwrap());
169        public_eddsa_vm.public_key = Some(Multibase(eddsa_public_key_multibase));
170
171        let mut private_ecdh_vm = VerificationMethod::new(
172            "did:example:123456789abcdefghi#keys-2".to_string(),
173            "X25519KeyAgreementKey2019".to_string(),
174            "did:example:123456789abcdefghi".to_string(),
175        );
176        let mut public_ecdh_vm = private_ecdh_vm.clone();
177
178        let ecdh_private_key_multibase = multibase::encode(Base58Btc, ecdh_key_pair.private_key_bytes().unwrap());
179        private_ecdh_vm.private_key = Some(Multibase(ecdh_private_key_multibase));
180
181        let ecdh_public_key_multibase = multibase::encode(Base58Btc, ecdh_key_pair.public_key_bytes().unwrap());
182        public_ecdh_vm.public_key = Some(Multibase(ecdh_public_key_multibase));
183
184        let private_verification_method = Some(vec![private_eddsa_vm, private_ecdh_vm]);
185        let public_verification_method = Some(vec![public_eddsa_vm, public_ecdh_vm]);
186
187        let authentication = Some(vec![VerificationMethodType::Reference(
188            "did:example:123456789abcdefghi#keys-1".to_string(),
189        )]);
190        let assertion_method = Some(vec![VerificationMethodType::Reference(
191            "did:example:123456789abcdefghi#keys-1".to_string(),
192        )]);
193        let key_agreement = Some(vec![VerificationMethodType::Reference(
194            "did:example:123456789abcdefghi#keys-2".to_string(),
195        )]);
196
197        let srv = Service::new(
198            "did:example:123456789abcdefghi#keys-1".to_string(),
199            "did-communication".to_string(),
200            Value::String("https://example.com".to_string()),
201        );
202        let service = Some(vec![srv]);
203
204        let private_document = Document::new_full(
205            context.clone(),
206            id.clone(),
207            authentication.clone(),
208            assertion_method.clone(),
209            key_agreement.clone(),
210            private_verification_method,
211            service.clone(),
212        );
213        let public_document = Document::new_full(
214            context,
215            id,
216            authentication,
217            assertion_method,
218            key_agreement,
219            public_verification_method,
220            service,
221        );
222
223        let canonicalized_private_document = json_canon::to_string(&private_document).unwrap();
224        let canonicalized_public_document = json_canon::to_string(&public_document).unwrap();
225
226        let expected_private_document = std::fs::read_to_string("test_resources/didkit_test_document_new_full_private.json").unwrap();
227        let expected_public_document = std::fs::read_to_string("test_resources/didkit_test_document_new_full_public.json").unwrap();
228
229        assert_eq!(expected_private_document, canonicalized_private_document);
230        assert_eq!(expected_public_document, canonicalized_public_document);
231    }
232}