ssi_verification_methods/methods/w3c/
ed25519_verification_key_2020.rs1use std::{borrow::Cow, hash::Hash, str::FromStr};
2
3use ed25519_dalek::{Signer, Verifier};
4use iref::{Iri, IriBuf, UriBuf};
5use rand_core::{CryptoRng, RngCore};
6use rdf_types::{Interpretation, Vocabulary};
7use serde::{Deserialize, Serialize};
8use ssi_claims_core::{InvalidProof, MessageSignatureError, ProofValidationError, ProofValidity};
9use ssi_jwk::JWK;
10use ssi_multicodec::MultiEncodedBuf;
11use ssi_security::{Multibase, MultibaseBuf};
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
20pub const ED25519_VERIFICATION_KEY_2020_TYPE: &str = "Ed25519VerificationKey2020";
22
23#[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 = "Ed25519VerificationKey2020")]
38#[ld(prefix("sec" = "https://w3id.org/security#"))]
39#[ld(type = "sec:Ed25519VerificationKey2020")]
40pub struct Ed25519VerificationKey2020 {
41 #[ld(id)]
43 pub id: IriBuf,
44
45 #[ld("sec:controller")]
47 pub controller: UriBuf,
48
49 #[serde(rename = "publicKeyMultibase")]
60 #[ld("sec:publicKeyMultibase")]
61 pub public_key: PublicKey,
62}
63
64impl Ed25519VerificationKey2020 {
65 pub const NAME: &'static str = ED25519_VERIFICATION_KEY_2020_TYPE;
66 pub const IRI: &'static Iri = iri!("https://w3id.org/security#Ed25519VerificationKey2020");
67
68 pub fn public_key_jwk(&self) -> JWK {
69 self.public_key.to_jwk()
70 }
71
72 pub fn generate_key_pair(
73 id: IriBuf,
74 controller: UriBuf,
75 csprng: &mut (impl RngCore + CryptoRng),
76 ) -> (Self, ed25519_dalek::SigningKey) {
77 let key = ed25519_dalek::SigningKey::generate(csprng);
78 (
79 Self::from_public_key(id, controller, key.verifying_key()),
80 key,
81 )
82 }
83
84 pub fn from_public_key(
85 id: IriBuf,
86 controller: UriBuf,
87 public_key: ed25519_dalek::VerifyingKey,
88 ) -> Self {
89 Self {
90 id,
91 controller,
92 public_key: PublicKey::encode(public_key),
93 }
94 }
95
96 pub fn sign_bytes<'a>(
102 &self,
103 secret_key: impl Into<SecretKeyRef<'a>>,
104 signing_bytes: &[u8],
105 ) -> Result<Vec<u8>, MessageSignatureError> {
106 match secret_key.into() {
107 SecretKeyRef::Ed25519(key_pair) => {
108 let signature = key_pair.sign(signing_bytes);
109 Ok(signature.to_bytes().to_vec())
110 }
111 SecretKeyRef::Jwk(secret_key) => {
112 let algorithm = ssi_jwk::Algorithm::EdDSA;
113 let key_algorithm = secret_key.algorithm.unwrap_or(algorithm);
114 if !algorithm.is_compatible_with(key_algorithm) {
115 return Err(MessageSignatureError::InvalidSecretKey);
116 }
117
118 ssi_jws::sign_bytes(algorithm, signing_bytes, secret_key)
119 .map_err(|_| MessageSignatureError::InvalidSecretKey)
120 }
121 }
122 }
123
124 pub fn verify_bytes(
125 &self,
126 data: &[u8],
127 signature_bytes: &[u8],
128 ) -> Result<ProofValidity, ProofValidationError> {
129 let signature = ed25519_dalek::Signature::try_from(signature_bytes)
130 .map_err(|_| ProofValidationError::InvalidSignature)?;
131 Ok(self.public_key.verify(data, &signature))
132 }
133}
134
135pub enum SecretKeyRef<'a> {
136 Ed25519(&'a ed25519_dalek::SigningKey),
137 Jwk(&'a JWK),
138}
139
140impl<'a> From<&'a ed25519_dalek::SigningKey> for SecretKeyRef<'a> {
141 fn from(value: &'a ed25519_dalek::SigningKey) -> Self {
142 Self::Ed25519(value)
143 }
144}
145
146impl<'a> From<&'a JWK> for SecretKeyRef<'a> {
147 fn from(value: &'a JWK) -> Self {
148 Self::Jwk(value)
149 }
150}
151
152impl VerificationMethod for Ed25519VerificationKey2020 {
153 fn id(&self) -> &Iri {
154 self.id.as_iri()
155 }
156
157 fn controller(&self) -> Option<&Iri> {
158 Some(self.controller.as_iri())
159 }
160}
161
162impl VerificationMethodSet for Ed25519VerificationKey2020 {
163 type TypeSet = &'static str;
164
165 fn type_set() -> Self::TypeSet {
166 Self::NAME
167 }
168}
169
170impl TypedVerificationMethod for Ed25519VerificationKey2020 {
171 fn expected_type() -> Option<ExpectedType> {
172 Some(ED25519_VERIFICATION_KEY_2020_TYPE.to_string().into())
173 }
174
175 fn type_match(ty: &str) -> bool {
176 ty == ED25519_VERIFICATION_KEY_2020_TYPE
177 }
178
179 fn type_(&self) -> &str {
180 ED25519_VERIFICATION_KEY_2020_TYPE
181 }
182}
183
184impl JwkVerificationMethod for Ed25519VerificationKey2020 {
185 fn to_jwk(&self) -> Cow<JWK> {
186 Cow::Owned(self.public_key_jwk())
187 }
188}
189
190impl SigningMethod<ed25519_dalek::SigningKey, ssi_crypto::algorithm::EdDSA>
191 for Ed25519VerificationKey2020
192{
193 fn sign_bytes(
194 &self,
195 secret: &ed25519_dalek::SigningKey,
196 _algorithm: ssi_crypto::algorithm::EdDSA,
197 message: &[u8],
198 ) -> Result<Vec<u8>, MessageSignatureError> {
199 self.sign_bytes(secret, message)
200 }
201}
202
203impl SigningMethod<JWK, ssi_crypto::algorithm::EdDSA> for Ed25519VerificationKey2020 {
204 fn sign_bytes(
205 &self,
206 secret_key: &JWK,
207 _algorithm: ssi_crypto::algorithm::EdDSA,
208 message: &[u8],
209 ) -> Result<Vec<u8>, MessageSignatureError> {
210 self.sign_bytes(secret_key, message)
211 }
212}
213
214impl VerifyBytes<ssi_crypto::algorithm::EdDSA> for Ed25519VerificationKey2020 {
215 fn verify_bytes(
216 &self,
217 _: ssi_crypto::algorithm::EdDSA,
218 signing_bytes: &[u8],
219 signature: &[u8],
220 ) -> Result<ProofValidity, ProofValidationError> {
221 self.verify_bytes(signing_bytes, signature)
222 }
223}
224
225impl TryFrom<GenericVerificationMethod> for Ed25519VerificationKey2020 {
226 type Error = InvalidVerificationMethod;
227
228 fn try_from(m: GenericVerificationMethod) -> Result<Self, Self::Error> {
229 Ok(Self {
230 id: m.id,
231 controller: m.controller,
232 public_key: m
233 .properties
234 .get("publicKeyMultibase")
235 .ok_or_else(|| InvalidVerificationMethod::missing_property("publicKeyMultibase"))?
236 .as_str()
237 .ok_or_else(|| {
238 InvalidVerificationMethod::invalid_property(
239 "publicKeyMultibase is not a string",
240 )
241 })?
242 .parse()
243 .map_err(|e| {
244 InvalidVerificationMethod::invalid_property(&format!(
245 "publicKeyMultibase parsing failed because: {e}"
246 ))
247 })?,
248 })
249 }
250}
251
252#[derive(Debug, Clone)]
254pub struct PublicKey {
255 encoded: MultibaseBuf,
262
263 decoded: ed25519_dalek::VerifyingKey,
265}
266
267impl PublicKey {
268 pub fn encode(decoded: ed25519_dalek::VerifyingKey) -> Self {
269 let multi_encoded =
270 MultiEncodedBuf::encode_bytes(ssi_multicodec::ED25519_PUB, decoded.as_bytes());
271
272 Self {
273 encoded: MultibaseBuf::encode(multibase::Base::Base58Btc, multi_encoded.as_bytes()),
274 decoded,
275 }
276 }
277
278 pub fn decode(encoded: MultibaseBuf) -> Result<Self, InvalidPublicKey> {
279 let pk_multi_encoded = MultiEncodedBuf::new(encoded.decode()?.1)?;
280
281 let (pk_codec, pk_data) = pk_multi_encoded.parts();
282 if pk_codec == ssi_multicodec::ED25519_PUB {
283 let decoded = ed25519_dalek::VerifyingKey::try_from(pk_data)?;
284 Ok(Self { encoded, decoded })
285 } else {
286 Err(InvalidPublicKey::InvalidKeyType)
287 }
288 }
289
290 pub fn encoded(&self) -> &Multibase {
291 &self.encoded
292 }
293
294 pub fn decoded(&self) -> &ed25519_dalek::VerifyingKey {
295 &self.decoded
296 }
297
298 pub fn to_jwk(&self) -> JWK {
299 self.decoded.into()
300 }
301
302 pub fn verify(&self, data: &[u8], signature: &ed25519_dalek::Signature) -> ProofValidity {
303 self.decoded
304 .verify(data, signature)
305 .map_err(|_| InvalidProof::Signature)
306 }
307}
308
309impl Serialize for PublicKey {
310 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
311 where
312 S: serde::Serializer,
313 {
314 self.encoded.serialize(serializer)
315 }
316}
317
318impl<'a> Deserialize<'a> for PublicKey {
319 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
320 where
321 D: serde::Deserializer<'a>,
322 {
323 use serde::de::Error;
324 let encoded = MultibaseBuf::deserialize(deserializer)?;
325 Self::decode(encoded).map_err(D::Error::custom)
326 }
327}
328
329impl FromStr for PublicKey {
330 type Err = InvalidPublicKey;
331
332 fn from_str(s: &str) -> Result<Self, Self::Err> {
333 Self::decode(MultibaseBuf::new(s.to_owned()))
334 }
335}
336
337impl PartialEq for PublicKey {
338 fn eq(&self, other: &Self) -> bool {
339 self.decoded.eq(&other.decoded)
340 }
341}
342
343impl Eq for PublicKey {}
344
345impl Hash for PublicKey {
346 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
347 self.encoded.hash(state)
348 }
349}
350
351impl<I: Interpretation, V: Vocabulary> linked_data::LinkedDataResource<I, V> for PublicKey
352where
353 MultibaseBuf: linked_data::LinkedDataResource<I, V>,
354{
355 fn interpretation(
356 &self,
357 vocabulary: &mut V,
358 interpretation: &mut I,
359 ) -> linked_data::ResourceInterpretation<I, V> {
360 self.encoded.interpretation(vocabulary, interpretation)
361 }
362}
363
364impl<I: Interpretation, V: Vocabulary> linked_data::LinkedDataSubject<I, V> for PublicKey
365where
366 MultibaseBuf: linked_data::LinkedDataSubject<I, V>,
367{
368 fn visit_subject<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
369 where
370 S: linked_data::SubjectVisitor<I, V>,
371 {
372 self.encoded.visit_subject(serializer)
373 }
374}
375
376impl<I: Interpretation, V: Vocabulary> linked_data::LinkedDataPredicateObjects<I, V> for PublicKey
377where
378 MultibaseBuf: linked_data::LinkedDataPredicateObjects<I, V>,
379{
380 fn visit_objects<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
381 where
382 S: linked_data::PredicateObjectsVisitor<I, V>,
383 {
384 self.encoded.visit_objects(visitor)
385 }
386}
387
388#[derive(Debug, thiserror::Error)]
389pub enum InvalidPublicKey {
390 #[error(transparent)]
391 Multibase(#[from] multibase::Error),
392
393 #[error(transparent)]
394 Multicodec(#[from] ssi_multicodec::Error),
395
396 #[error("invalid key type")]
397 InvalidKeyType,
398
399 #[error(transparent)]
400 Ed25519(#[from] ed25519_dalek::SignatureError),
401}