identity_credential/credential/
proof.rs

1// Copyright 2020-2023 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use identity_core::common::Object;
5use serde::Deserialize;
6use serde::Serialize;
7
8/// Represents a cryptographic proof that can be used to validate verifiable credentials and
9/// presentations.
10///
11/// This representation does not inherently implement any standard; instead, it
12/// can be utilized to implement standards or user-defined proofs. The presence of the
13/// `type` field is necessary to accommodate different types of cryptographic proofs.
14///
15/// Note that this proof is not related to JWT and can be used in combination or as an alternative
16/// to it.
17#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
18pub struct Proof {
19  /// Type of proof.
20  #[serde(rename = "type")]
21  pub type_: String,
22
23  /// Properties of the proof, entries depend on the proof type.
24  #[serde(flatten)]
25  pub properties: Object,
26}
27
28impl Proof {
29  /// Creates a new `Proof`.
30  pub fn new(type_: String, properties: Object) -> Proof {
31    Self { type_, properties }
32  }
33}
34
35#[cfg(test)]
36mod tests {
37  use super::Proof;
38  use crate::credential::Credential;
39  use identity_core::common::Object;
40  use identity_core::convert::FromJson;
41
42  #[test]
43  fn test_proof_from_json() {
44    let proof = r#"
45    {
46      "type": "test-proof",
47      "signature": "abc123"
48    }
49    "#;
50    let proof: Proof = Proof::from_json(proof).expect("proof deserialization failed");
51
52    assert_eq!(proof.type_, "test-proof");
53    let value = proof
54      .properties
55      .get("signature")
56      .expect("property in proof doesn't exist");
57    assert_eq!(value, "abc123");
58  }
59
60  #[test]
61  fn test_credential_with_proof_from_json() {
62    let credential_json = r#"
63    {
64      "@context": [
65        "https://www.w3.org/2018/credentials/v1",
66        "https://www.w3.org/2018/credentials/examples/v1"
67      ],
68      "id": "http://example.edu/credentials/58473",
69      "type": ["VerifiableCredential", "AlumniCredential"],
70      "issuer": "https://example.edu/issuers/14",
71      "issuanceDate": "2010-01-01T19:23:24Z",
72      "credentialSubject": {
73        "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
74        "alumniOf": "Example University"
75      },
76      "proof": {
77        "type": "RsaSignature2018",
78        "created": "2017-06-18T21:19:10Z",
79        "proofPurpose": "assertionMethod",
80        "verificationMethod": "https://example.com/jdoe/keys/1",
81        "jws": "eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..TCYt5XsITJX1CxPCT8yAV-TVkIEq_PbChOMqsLfRoPsnsgw5WEuts01mq-pQy7UJiN5mgRxD-WUcX16dUEMGlv50aqzpqh4Qktb3rk-BuQy72IFLOqV0G_zS245-kronKb78cPN25DGlcTwLtjPAYuNzVBAh4vGHSrQyHUdBBPM"
82      }
83    }
84    "#;
85
86    let proof: Proof = Credential::<Object>::from_json(credential_json).unwrap().proof.unwrap();
87
88    assert_eq!(proof.type_, "RsaSignature2018");
89    let value = proof
90      .properties
91      .get("proofPurpose")
92      .expect("property in proof doesn't exist");
93    assert_eq!(value, "assertionMethod");
94    assert_eq!(proof.properties.len(), 4);
95  }
96}