ssi_verification_methods/methods/w3c/
json_web_key_2020.rs1use 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#[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 #[ld(id)]
46 pub id: IriBuf,
47
48 #[ld("sec:controller")]
50 pub controller: UriBuf,
51
52 #[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 fn id(&self) -> &Iri {
108 self.id.as_iri()
109 }
110
111 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 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}