Skip to main content

ssi_verification_methods/methods/w3c/
json_web_key_2020.rs

1use std::{borrow::Cow, hash::Hash};
2
3use iref::{Iri, IriBuf, UriBuf};
4use serde::{Deserialize, Serialize};
5use ssi_claims_core::{InvalidProof, MessageSignatureError, ProofValidationError, ProofValidity};
6use ssi_jwk::{Algorithm, JWK};
7use ssi_verification_methods_core::{JwkVerificationMethod, VerificationMethodSet, VerifyBytes};
8use static_iref::iri;
9
10use crate::{
11    ExpectedType, GenericVerificationMethod, InvalidVerificationMethod, TypedVerificationMethod,
12    VerificationMethod,
13};
14
15pub const JSON_WEB_KEY_2020_TYPE: &str = "JsonWebKey2020";
16
17/// JSON Web Key 2020 verification method.
18///
19/// To be used with the [JSON Web Signature 2020][1] cryptographic suite.
20///
21/// See: <https://w3c-ccg.github.io/lds-jws2020/#json-web-key-2020>
22///
23/// [1]: <https://w3c-ccg.github.io/lds-jws2020>
24#[derive(
25    Debug,
26    Clone,
27    PartialEq,
28    Eq,
29    Hash,
30    Serialize,
31    Deserialize,
32    linked_data::Serialize,
33    linked_data::Deserialize,
34)]
35#[serde(tag = "type", rename = "JsonWebKey2020")]
36#[ld(prefix("sec" = "https://w3id.org/security#"))]
37#[ld(type = "sec:JsonWebKey2020")]
38pub struct JsonWebKey2020 {
39    /// Key identifier.
40    ///
41    /// Should be the JWK thumbprint calculated from the public key value
42    /// according to [RFC7638][rfc7638].
43    ///
44    /// [rfc7638]: <https://w3c-ccg.github.io/lds-jws2020/#bib-rfc7638>
45    #[ld(id)]
46    pub id: IriBuf,
47
48    /// Key controller.
49    #[ld("sec:controller")]
50    pub controller: UriBuf,
51
52    /// Public JSON Web Key.
53    #[serde(rename = "publicKeyJwk")]
54    #[ld("sec:publicKeyJwk")]
55    pub public_key: Box<JWK>,
56}
57
58impl JsonWebKey2020 {
59    pub const NAME: &'static str = JSON_WEB_KEY_2020_TYPE;
60    pub const IRI: &'static Iri = iri!("https://w3id.org/security#JsonWebKey2020");
61
62    pub fn public_key_jwk(&self) -> &JWK {
63        &self.public_key
64    }
65
66    pub fn sign_bytes(
67        &self,
68        secret_key: &JWK,
69        algorithm: Option<ssi_jwk::Algorithm>,
70        data: &[u8],
71    ) -> Result<Vec<u8>, MessageSignatureError> {
72        let algorithm = algorithm
73            .or(secret_key.algorithm)
74            .ok_or(MessageSignatureError::InvalidSecretKey)?;
75        ssi_jws::sign_bytes(algorithm, data, secret_key)
76            .map_err(|_| MessageSignatureError::InvalidSecretKey)
77    }
78
79    pub fn verify_bytes(
80        &self,
81        data: &[u8],
82        signature: &[u8],
83        algorithm: Option<Algorithm>,
84    ) -> Result<ProofValidity, ProofValidationError> {
85        let algorithm = match (self.public_key.algorithm, algorithm) {
86            (Some(a), Some(b)) => {
87                if a == b {
88                    a
89                } else {
90                    return Ok(Err(InvalidProof::AlgorithmMismatch));
91                }
92            }
93            (Some(a), None) => a,
94            (None, Some(b)) => b,
95            (None, None) => return Err(ProofValidationError::InvalidKey),
96        };
97
98        Ok(
99            ssi_jws::verify_bytes(algorithm, data, &self.public_key, signature)
100                .map_err(|_| InvalidProof::Signature),
101        )
102    }
103}
104
105impl VerificationMethod for JsonWebKey2020 {
106    /// Returns the identifier of the key.
107    fn id(&self) -> &Iri {
108        self.id.as_iri()
109    }
110
111    /// Returns an URI to the key controller.
112    fn controller(&self) -> Option<&Iri> {
113        Some(self.controller.as_iri())
114    }
115}
116
117impl VerificationMethodSet for JsonWebKey2020 {
118    type TypeSet = &'static str;
119
120    fn type_set() -> Self::TypeSet {
121        Self::NAME
122    }
123}
124
125impl TypedVerificationMethod for JsonWebKey2020 {
126    fn expected_type() -> Option<ExpectedType> {
127        Some(JSON_WEB_KEY_2020_TYPE.to_string().into())
128    }
129
130    fn type_match(ty: &str) -> bool {
131        ty == JSON_WEB_KEY_2020_TYPE
132    }
133
134    /// Returns the type of the key.
135    fn type_(&self) -> &str {
136        JSON_WEB_KEY_2020_TYPE
137    }
138}
139
140impl JwkVerificationMethod for JsonWebKey2020 {
141    fn to_jwk(&'_ self) -> Cow<'_, JWK> {
142        Cow::Borrowed(self.public_key_jwk())
143    }
144}
145
146impl VerifyBytes<Algorithm> for JsonWebKey2020 {
147    fn verify_bytes(
148        &self,
149        algorithm: Algorithm,
150        signing_bytes: &[u8],
151        signature: &[u8],
152    ) -> Result<ProofValidity, ProofValidationError> {
153        self.verify_bytes(signing_bytes, signature, Some(algorithm))
154    }
155}
156
157impl TryFrom<GenericVerificationMethod> for JsonWebKey2020 {
158    type Error = InvalidVerificationMethod;
159
160    fn try_from(mut m: GenericVerificationMethod) -> Result<Self, Self::Error> {
161        Ok(Self {
162            id: m.id,
163            controller: m.controller,
164            public_key: Box::new(
165                serde_json::from_value(
166                    m.properties.remove("publicKeyJwk").ok_or_else(|| {
167                        InvalidVerificationMethod::missing_property("publicKeyJwk")
168                    })?,
169                )
170                .map_err(|_| InvalidVerificationMethod::invalid_property("publicKeyJwk"))?,
171            ),
172        })
173    }
174}