Skip to main content

ssi_verification_methods/methods/w3c/
ecdsa_secp_256r1_verification_key_2019.rs

1use 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// pub const ECDSA_SECP_256R1_VERIFICATION_KEY_2019_IRI: &Iri =
20//     iri!("https://w3id.org/security#EcdsaSecp256r1VerificationKey2019");
21
22#[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/// Key for [Ecdsa Secp256r1 Signature 2019][1].
38///
39/// See: <https://www.w3.org/community/reports/credentials/CG-FINAL-di-ecdsa-2019-20220724/#ecdsasecp256r1verificationkey2019>
40///
41/// [1]: <https://www.w3.org/community/reports/credentials/CG-FINAL-di-ecdsa-2019-20220724/#ecdsasecp256r1signature2019>
42#[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    /// Key identifier.
58    #[ld(id)]
59    pub id: IriBuf,
60
61    /// Key controller.
62    #[ld("sec:controller")]
63    pub controller: UriBuf,
64
65    /// Public key.
66    #[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    /// Returns the identifier of the key.
146    fn id(&self) -> &Iri {
147        self.id.as_iri()
148    }
149
150    /// Returns an URI to the key controller.
151    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    /// Returns the type of the key.
178    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/// Public key of an Ed25519 Verification Key 2020 verification method.
228#[derive(Debug, Clone)]
229pub struct PublicKey {
230    /// Public key encoded according to [MULTICODEC] and formatted according to
231    /// [MULTIBASE].
232    ///
233    /// The multicodec encoding of an P256 public key is the
234    /// two-byte prefix 0x1200 followed by the public key data. The value is
235    /// then encoded using base58-btc (z) as the prefix.
236    encoded: MultibaseBuf,
237
238    /// Decoded public key.
239    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}