ssi_verification_methods/methods/w3c/
ed25519_verification_key_2018.rs

1use std::{borrow::Cow, hash::Hash, str::FromStr};
2
3use ed25519_dalek::{Signer, Verifier};
4use iref::{Iri, IriBuf, UriBuf};
5use rdf_types::{Interpretation, Vocabulary};
6use serde::{Deserialize, Serialize};
7use ssi_claims_core::{
8    InvalidProof, MessageSignatureError, ProofValidationError, ProofValidity, SignatureError,
9};
10use ssi_jwk::JWK;
11use ssi_jws::JwsString;
12use ssi_verification_methods_core::{JwkVerificationMethod, VerificationMethodSet, VerifyBytes};
13use static_iref::iri;
14
15use crate::{
16    ExpectedType, GenericVerificationMethod, InvalidVerificationMethod, SigningMethod,
17    TypedVerificationMethod, VerificationMethod,
18};
19
20/// Ed25519 Verification Key 2018 type name.
21pub const ED25519_VERIFICATION_KEY_2018_TYPE: &str = "Ed25519VerificationKey2018";
22
23/// Deprecated verification method for the `Ed25519Signature2018` suite.
24///
25/// See: <https://w3c-ccg.github.io/lds-ed25519-2018/#the-ed25519-key-format>
26#[derive(
27    Debug,
28    Clone,
29    PartialEq,
30    Eq,
31    Hash,
32    Serialize,
33    Deserialize,
34    linked_data::Serialize,
35    linked_data::Deserialize,
36)]
37#[serde(tag = "type", rename = "Ed25519VerificationKey2018")]
38#[ld(prefix("sec" = "https://w3id.org/security#"))]
39#[ld(type = "sec:Ed25519VerificationKey2018")]
40pub struct Ed25519VerificationKey2018 {
41    /// Key identifier.
42    #[ld(id)]
43    pub id: IriBuf,
44
45    /// Controller of the verification method.
46    #[ld("sec:controller")]
47    pub controller: UriBuf,
48
49    /// Public key encoded in base58 using the same alphabet as Bitcoin
50    /// addresses and IPFS hashes.
51    #[serde(rename = "publicKeyBase58")]
52    #[ld("sec:publicKeyBase58")]
53    pub public_key: PublicKey,
54}
55
56impl Ed25519VerificationKey2018 {
57    pub const NAME: &'static str = ED25519_VERIFICATION_KEY_2018_TYPE;
58    pub const IRI: &'static Iri = iri!("https://w3id.org/security#Ed25519VerificationKey2018");
59
60    pub fn public_key_jwk(&self) -> JWK {
61        self.public_key.to_jwk()
62    }
63
64    pub fn sign(
65        &self,
66        data: &[u8],
67        secret_key: &ed25519_dalek::SigningKey,
68    ) -> Result<JwsString, SignatureError> {
69        let header = ssi_jws::Header::new_unencoded(ssi_jwk::Algorithm::EdDSA, None);
70        let signing_bytes = header.encode_signing_bytes(data);
71        let signature = secret_key.sign(&signing_bytes);
72
73        Ok(ssi_jws::JwsString::from_signing_bytes_and_signature(
74            // TODO base64 encode signature?
75            signing_bytes,
76            signature.to_bytes(),
77        )
78        .unwrap())
79    }
80
81    pub fn verify_bytes(
82        &self,
83        data: &[u8],
84        signature_bytes: &[u8],
85    ) -> Result<ProofValidity, ProofValidationError> {
86        let signature = ed25519_dalek::Signature::try_from(signature_bytes)
87            .map_err(|_| ProofValidationError::InvalidSignature)?;
88        Ok(self.public_key.verify(data, &signature))
89    }
90}
91
92impl VerificationMethod for Ed25519VerificationKey2018 {
93    fn id(&self) -> &Iri {
94        self.id.as_iri()
95    }
96
97    fn controller(&self) -> Option<&Iri> {
98        Some(self.controller.as_iri())
99    }
100}
101
102impl VerificationMethodSet for Ed25519VerificationKey2018 {
103    type TypeSet = &'static str;
104
105    fn type_set() -> Self::TypeSet {
106        Self::NAME
107    }
108}
109
110impl TypedVerificationMethod for Ed25519VerificationKey2018 {
111    fn expected_type() -> Option<ExpectedType> {
112        Some(ED25519_VERIFICATION_KEY_2018_TYPE.to_string().into())
113    }
114
115    fn type_match(ty: &str) -> bool {
116        ty == ED25519_VERIFICATION_KEY_2018_TYPE
117    }
118
119    fn type_(&self) -> &str {
120        ED25519_VERIFICATION_KEY_2018_TYPE
121    }
122}
123
124impl JwkVerificationMethod for Ed25519VerificationKey2018 {
125    fn to_jwk(&self) -> Cow<JWK> {
126        Cow::Owned(self.public_key_jwk())
127    }
128}
129
130impl TryFrom<GenericVerificationMethod> for Ed25519VerificationKey2018 {
131    type Error = InvalidVerificationMethod;
132
133    fn try_from(m: GenericVerificationMethod) -> Result<Self, Self::Error> {
134        Ok(Self {
135            id: m.id,
136            controller: m.controller,
137            public_key: m
138                .properties
139                .get("publicKeyBase58")
140                .ok_or_else(|| InvalidVerificationMethod::missing_property("publicKeyBase58"))?
141                .as_str()
142                .ok_or_else(|| InvalidVerificationMethod::invalid_property("publicKeyBase58"))?
143                .parse()
144                .map_err(|_| InvalidVerificationMethod::invalid_property("publicKeyBase58"))?,
145        })
146    }
147}
148
149impl SigningMethod<JWK, ssi_crypto::algorithm::EdDSA> for Ed25519VerificationKey2018 {
150    fn sign_bytes(
151        &self,
152        secret: &JWK,
153        _algorithm: ssi_crypto::algorithm::EdDSA,
154        bytes: &[u8],
155    ) -> Result<Vec<u8>, MessageSignatureError> {
156        ssi_jws::sign_bytes(ssi_jwk::Algorithm::EdDSA, bytes, secret)
157            .map_err(MessageSignatureError::signature_failed)
158    }
159}
160
161impl VerifyBytes<ssi_crypto::algorithm::EdDSA> for Ed25519VerificationKey2018 {
162    fn verify_bytes(
163        &self,
164        _: ssi_crypto::algorithm::EdDSA,
165        signing_bytes: &[u8],
166        signature: &[u8],
167    ) -> Result<ProofValidity, ProofValidationError> {
168        self.verify_bytes(signing_bytes, signature)
169    }
170}
171
172/// Public key of an Ed25519 Verification Key 2018 verification method.
173#[derive(Debug, Clone)]
174pub struct PublicKey {
175    /// Base58-BTC encoded public key.
176    encoded: String,
177
178    /// Decoded public key.
179    decoded: ed25519_dalek::VerifyingKey,
180}
181
182impl PublicKey {
183    pub fn decode(encoded: String) -> Result<Self, InvalidPublicKey> {
184        let pk_bytes = multibase::Base::Base58Btc.decode(&encoded)?;
185        let decoded = ed25519_dalek::VerifyingKey::try_from(pk_bytes.as_slice())?;
186        Ok(Self { encoded, decoded })
187    }
188
189    pub fn encoded(&self) -> &str {
190        &self.encoded
191    }
192
193    pub fn decoded(&self) -> &ed25519_dalek::VerifyingKey {
194        &self.decoded
195    }
196
197    pub fn to_jwk(&self) -> JWK {
198        self.decoded.into()
199    }
200
201    pub fn verify(&self, data: &[u8], signature: &ed25519_dalek::Signature) -> ProofValidity {
202        self.decoded
203            .verify(data, signature)
204            .map_err(|_| InvalidProof::Signature)
205    }
206}
207
208impl Serialize for PublicKey {
209    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
210    where
211        S: serde::Serializer,
212    {
213        self.encoded.serialize(serializer)
214    }
215}
216
217impl<'a> Deserialize<'a> for PublicKey {
218    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
219    where
220        D: serde::Deserializer<'a>,
221    {
222        use serde::de::Error;
223        let encoded = String::deserialize(deserializer)?;
224        Self::decode(encoded).map_err(D::Error::custom)
225    }
226}
227
228impl FromStr for PublicKey {
229    type Err = InvalidPublicKey;
230
231    fn from_str(s: &str) -> Result<Self, Self::Err> {
232        Self::decode(s.to_owned())
233    }
234}
235
236impl PartialEq for PublicKey {
237    fn eq(&self, other: &Self) -> bool {
238        self.decoded.eq(&other.decoded)
239    }
240}
241
242impl Eq for PublicKey {}
243
244impl Hash for PublicKey {
245    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
246        self.encoded.hash(state)
247    }
248}
249
250impl<I: Interpretation, V: Vocabulary> linked_data::LinkedDataResource<I, V> for PublicKey
251where
252    String: linked_data::LinkedDataResource<I, V>,
253{
254    fn interpretation(
255        &self,
256        vocabulary: &mut V,
257        interpretation: &mut I,
258    ) -> linked_data::ResourceInterpretation<I, V> {
259        self.encoded.interpretation(vocabulary, interpretation)
260    }
261}
262
263impl<I: Interpretation, V: Vocabulary> linked_data::LinkedDataSubject<I, V> for PublicKey
264where
265    String: linked_data::LinkedDataSubject<I, V>,
266{
267    fn visit_subject<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
268    where
269        S: linked_data::SubjectVisitor<I, V>,
270    {
271        self.encoded.visit_subject(serializer)
272    }
273}
274
275impl<I: Interpretation, V: Vocabulary> linked_data::LinkedDataPredicateObjects<I, V> for PublicKey
276where
277    String: linked_data::LinkedDataPredicateObjects<I, V>,
278{
279    fn visit_objects<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
280    where
281        S: linked_data::PredicateObjectsVisitor<I, V>,
282    {
283        self.encoded.visit_objects(visitor)
284    }
285}
286
287#[derive(Debug, thiserror::Error)]
288pub enum InvalidPublicKey {
289    #[error(transparent)]
290    Multibase(#[from] multibase::Error),
291
292    #[error(transparent)]
293    Ed25519(#[from] ed25519_dalek::SignatureError),
294}