ssi_verification_methods/methods/w3c/
ecdsa_secp_256r1_verification_key_2019.rs1use iref::{Iri, IriBuf, UriBuf};
2use rdf_types::{Interpretation, Vocabulary};
3use serde::{Deserialize, Serialize};
4use ssi_claims_core::{InvalidProof, MessageSignatureError, ProofValidationError, ProofValidity};
5use ssi_jwk::JWK;
6use ssi_multicodec::MultiEncodedBuf;
7use ssi_security::{Multibase, MultibaseBuf};
8use ssi_verification_methods_core::{JwkVerificationMethod, VerificationMethodSet, VerifyBytes};
9use static_iref::iri;
10use std::{borrow::Cow, hash::Hash, str::FromStr};
11
12use crate::{
13 ExpectedType, GenericVerificationMethod, InvalidVerificationMethod, TypedVerificationMethod,
14 VerificationMethod,
15};
16
17pub const ECDSA_SECP_256R1_VERIFICATION_KEY_2019_TYPE: &str = "EcdsaSecp256r1VerificationKey2019";
18
19#[derive(Debug, thiserror::Error)]
23pub enum InvalidPublicKey {
24 #[error(transparent)]
25 Multibase(#[from] multibase::Error),
26
27 #[error(transparent)]
28 Multicodec(#[from] ssi_multicodec::Error),
29
30 #[error("invalid key type")]
31 InvalidKeyType,
32
33 #[error(transparent)]
34 P256(#[from] p256::elliptic_curve::Error),
35}
36
37#[derive(
43 Debug,
44 Clone,
45 PartialEq,
46 Eq,
47 Hash,
48 Serialize,
49 Deserialize,
50 linked_data::Serialize,
51 linked_data::Deserialize,
52)]
53#[serde(tag = "type", rename = "EcdsaSecp256r1VerificationKey2019")]
54#[ld(prefix("sec" = "https://w3id.org/security#"))]
55#[ld(type = "sec:EcdsaSecp256r1VerificationKey2019")]
56pub struct EcdsaSecp256r1VerificationKey2019 {
57 #[ld(id)]
59 pub id: IriBuf,
60
61 #[ld("sec:controller")]
63 pub controller: UriBuf,
64
65 #[serde(rename = "publicKeyMultibase")]
67 #[ld("sec:publicKeyMultibase")]
68 pub public_key: PublicKey,
69}
70
71pub enum SecretKeyRef<'a> {
72 P256(&'a p256::SecretKey),
73 Jwk(&'a JWK),
74}
75
76impl<'a> From<&'a p256::SecretKey> for SecretKeyRef<'a> {
77 fn from(value: &'a p256::SecretKey) -> Self {
78 Self::P256(value)
79 }
80}
81
82impl<'a> From<&'a JWK> for SecretKeyRef<'a> {
83 fn from(value: &'a JWK) -> Self {
84 Self::Jwk(value)
85 }
86}
87
88impl EcdsaSecp256r1VerificationKey2019 {
89 pub const NAME: &'static str = ECDSA_SECP_256R1_VERIFICATION_KEY_2019_TYPE;
90 pub const IRI: &'static Iri =
91 iri!("https://w3id.org/security#EcdsaSecp256r1VerificationKey2019");
92
93 pub fn from_public_key(id: IriBuf, controller: UriBuf, public_key: p256::PublicKey) -> Self {
94 Self {
95 id,
96 controller,
97 public_key: PublicKey::encode(public_key),
98 }
99 }
100
101 pub fn public_key_jwk(&self) -> JWK {
102 self.public_key.to_jwk()
103 }
104
105 pub fn sign_bytes<'a>(
106 &self,
107 secret_key: impl Into<SecretKeyRef<'a>>,
108 signing_bytes: &[u8],
109 ) -> Result<Vec<u8>, MessageSignatureError> {
110 use p256::ecdsa::signature::Signer;
111
112 match secret_key.into() {
113 SecretKeyRef::P256(secret_key) => {
114 let signing_key = p256::ecdsa::SigningKey::from(secret_key);
115 let signature: p256::ecdsa::Signature =
116 signing_key.try_sign(signing_bytes).unwrap();
117 Ok(signature.to_bytes().to_vec())
118 }
119 SecretKeyRef::Jwk(secret_key) => {
120 let algorithm = ssi_jwk::Algorithm::ES256;
121 let key_algorithm = secret_key.algorithm.unwrap_or(algorithm);
122 if !algorithm.is_compatible_with(key_algorithm) {
123 return Err(MessageSignatureError::InvalidSecretKey);
124 }
125
126 ssi_jws::sign_bytes(algorithm, signing_bytes, secret_key)
127 .map_err(|_| MessageSignatureError::InvalidSecretKey)
128 }
129 }
130 }
131
132 pub fn verify_bytes(
133 &self,
134 data: &[u8],
135 signature_bytes: &[u8],
136 ) -> Result<ProofValidity, ProofValidationError> {
137 let signature = p256::ecdsa::Signature::try_from(signature_bytes)
138 .map_err(|_| ProofValidationError::InvalidSignature)?;
139
140 Ok(self.public_key.verify(data, &signature))
141 }
142}
143
144impl VerificationMethod for EcdsaSecp256r1VerificationKey2019 {
145 fn id(&self) -> &Iri {
147 self.id.as_iri()
148 }
149
150 fn controller(&self) -> Option<&Iri> {
152 Some(self.controller.as_iri())
153 }
154}
155
156impl VerificationMethodSet for EcdsaSecp256r1VerificationKey2019 {
157 type TypeSet = &'static str;
158
159 fn type_set() -> Self::TypeSet {
160 Self::NAME
161 }
162}
163
164impl TypedVerificationMethod for EcdsaSecp256r1VerificationKey2019 {
165 fn expected_type() -> Option<ExpectedType> {
166 Some(
167 ECDSA_SECP_256R1_VERIFICATION_KEY_2019_TYPE
168 .to_string()
169 .into(),
170 )
171 }
172
173 fn type_match(ty: &str) -> bool {
174 ty == ECDSA_SECP_256R1_VERIFICATION_KEY_2019_TYPE
175 }
176
177 fn type_(&self) -> &str {
179 ECDSA_SECP_256R1_VERIFICATION_KEY_2019_TYPE
180 }
181}
182
183impl JwkVerificationMethod for EcdsaSecp256r1VerificationKey2019 {
184 fn to_jwk(&'_ self) -> Cow<'_, JWK> {
185 Cow::Owned(self.public_key_jwk())
186 }
187}
188
189impl VerifyBytes<ssi_crypto::algorithm::ES256> for EcdsaSecp256r1VerificationKey2019 {
190 fn verify_bytes(
191 &self,
192 _: ssi_crypto::algorithm::ES256,
193 signing_bytes: &[u8],
194 signature: &[u8],
195 ) -> Result<ProofValidity, ProofValidationError> {
196 self.verify_bytes(signing_bytes, signature)
197 }
198}
199
200impl TryFrom<GenericVerificationMethod> for EcdsaSecp256r1VerificationKey2019 {
201 type Error = InvalidVerificationMethod;
202
203 fn try_from(m: GenericVerificationMethod) -> Result<Self, Self::Error> {
204 Ok(Self {
205 id: m.id,
206 controller: m.controller,
207 public_key: m
208 .properties
209 .get("publicKeyMultibase")
210 .ok_or_else(|| InvalidVerificationMethod::missing_property("publicKeyMultibase"))?
211 .as_str()
212 .ok_or_else(|| {
213 InvalidVerificationMethod::invalid_property(
214 "publicKeyMultibase is not a string",
215 )
216 })?
217 .parse()
218 .map_err(|e| {
219 InvalidVerificationMethod::invalid_property(&format!(
220 "publicKeyMultibase parsing failed because: {e}"
221 ))
222 })?,
223 })
224 }
225}
226
227#[derive(Debug, Clone)]
229pub struct PublicKey {
230 encoded: MultibaseBuf,
237
238 decoded: p256::PublicKey,
240}
241
242impl PublicKey {
243 pub fn encode(decoded: p256::PublicKey) -> Self {
244 let multi_encoded =
245 MultiEncodedBuf::encode_bytes(ssi_multicodec::P256_PUB, &decoded.to_sec1_bytes());
246
247 Self {
248 encoded: MultibaseBuf::encode(multibase::Base::Base58Btc, multi_encoded.as_bytes()),
249 decoded,
250 }
251 }
252
253 pub fn decode(encoded: MultibaseBuf) -> Result<Self, InvalidPublicKey> {
254 let pk_multi_encoded = MultiEncodedBuf::new(encoded.decode()?.1)?;
255
256 let (pk_codec, pk_data) = pk_multi_encoded.parts();
257 if pk_codec == ssi_multicodec::P256_PUB {
258 let decoded = p256::PublicKey::from_sec1_bytes(pk_data)?;
259 Ok(Self { encoded, decoded })
260 } else {
261 Err(InvalidPublicKey::InvalidKeyType)
262 }
263 }
264
265 pub fn encoded(&self) -> &Multibase {
266 &self.encoded
267 }
268
269 pub fn decoded(&self) -> &p256::PublicKey {
270 &self.decoded
271 }
272
273 pub fn to_jwk(&self) -> JWK {
274 self.decoded.into()
275 }
276
277 pub fn verify(&self, data: &[u8], signature: &p256::ecdsa::Signature) -> ProofValidity {
278 use p256::ecdsa::signature::Verifier;
279 let verifying_key = p256::ecdsa::VerifyingKey::from(self.decoded);
280 verifying_key
281 .verify(data, signature)
282 .map_err(|_| InvalidProof::Signature)
283 }
284}
285
286impl Serialize for PublicKey {
287 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
288 where
289 S: serde::Serializer,
290 {
291 self.encoded.serialize(serializer)
292 }
293}
294
295impl<'a> Deserialize<'a> for PublicKey {
296 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
297 where
298 D: serde::Deserializer<'a>,
299 {
300 use serde::de::Error;
301 let encoded = MultibaseBuf::deserialize(deserializer)?;
302 Self::decode(encoded).map_err(D::Error::custom)
303 }
304}
305
306impl FromStr for PublicKey {
307 type Err = InvalidPublicKey;
308
309 fn from_str(s: &str) -> Result<Self, Self::Err> {
310 Self::decode(MultibaseBuf::new(s.to_owned()))
311 }
312}
313
314impl PartialEq for PublicKey {
315 fn eq(&self, other: &Self) -> bool {
316 self.decoded.eq(&other.decoded)
317 }
318}
319
320impl Eq for PublicKey {}
321
322impl Hash for PublicKey {
323 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
324 self.encoded.hash(state)
325 }
326}
327
328impl<I: Interpretation, V: Vocabulary> linked_data::LinkedDataResource<I, V> for PublicKey
329where
330 MultibaseBuf: linked_data::LinkedDataResource<I, V>,
331{
332 fn interpretation(
333 &'_ self,
334 vocabulary: &mut V,
335 interpretation: &mut I,
336 ) -> linked_data::ResourceInterpretation<'_, I, V> {
337 self.encoded.interpretation(vocabulary, interpretation)
338 }
339}
340
341impl<I: Interpretation, V: Vocabulary> linked_data::LinkedDataSubject<I, V> for PublicKey
342where
343 MultibaseBuf: linked_data::LinkedDataSubject<I, V>,
344{
345 fn visit_subject<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
346 where
347 S: linked_data::SubjectVisitor<I, V>,
348 {
349 self.encoded.visit_subject(serializer)
350 }
351}
352
353impl<I: Interpretation, V: Vocabulary> linked_data::LinkedDataPredicateObjects<I, V> for PublicKey
354where
355 MultibaseBuf: linked_data::LinkedDataPredicateObjects<I, V>,
356{
357 fn visit_objects<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
358 where
359 S: linked_data::PredicateObjectsVisitor<I, V>,
360 {
361 self.encoded.visit_objects(visitor)
362 }
363}