ssi_verification_methods/methods/unspecified/
blockchain_verification_method_2021.rs1use std::hash::Hash;
2
3use iref::{Iri, IriBuf, UriBuf};
4use serde::{Deserialize, Serialize};
5use ssi_claims_core::{MessageSignatureError, ProofValidationError};
6use ssi_jwk::JWK;
7use ssi_verification_methods_core::VerificationMethodSet;
8use static_iref::iri;
9
10use crate::{
11 ExpectedType, GenericVerificationMethod, InvalidVerificationMethod, TypedVerificationMethod,
12 VerificationMethod,
13};
14
15pub const BLOCKCHAIN_VERIFICATION_METHOD_2021_TYPE: &str = "BlockchainVerificationMethod2021";
19
20#[derive(
24 Debug,
25 Clone,
26 PartialEq,
27 Eq,
28 Hash,
29 Serialize,
30 Deserialize,
31 linked_data::Serialize,
32 linked_data::Deserialize,
33)]
34#[serde(tag = "type", rename = "BlockchainVerificationMethod2021")]
35#[ld(prefix("sec" = "https://w3id.org/security#"))]
36#[ld(type = "sec:BlockchainVerificationMethod2021")]
37pub struct BlockchainVerificationMethod2021 {
38 #[ld(id)]
40 pub id: IriBuf,
41
42 #[ld("sec:controller")]
44 pub controller: UriBuf,
45
46 #[serde(rename = "blockchainAccountId")]
48 #[ld("sec:blockchainAccountId")]
49 pub blockchain_account_id: ssi_caips::caip10::BlockchainAccountId,
50}
51
52impl BlockchainVerificationMethod2021 {
53 pub const NAME: &'static str = BLOCKCHAIN_VERIFICATION_METHOD_2021_TYPE;
54 pub const IRI: &'static Iri =
55 iri!("https://w3id.org/security#BlockchainVerificationMethod2021");
56
57 pub fn verify_bytes(
58 &self,
59 public_key_jwk: Option<&JWK>,
60 message: &[u8],
61 algorithm: ssi_jwk::Algorithm,
62 signature: &[u8],
63 ) -> Result<bool, ProofValidationError> {
64 match public_key_jwk {
65 Some(jwk) => match self.blockchain_account_id.verify(jwk) {
66 Ok(()) => Ok(ssi_jws::verify_bytes(algorithm, message, jwk, signature).is_ok()),
67 Err(_) => Ok(false),
68 },
69 None => Err(ProofValidationError::MissingPublicKey),
70 }
71 }
72
73 pub fn sign_bytes(
74 &self,
75 key: &JWK,
76 algorithm: ssi_jwk::Algorithm,
77 bytes: &[u8],
78 ) -> Result<Vec<u8>, MessageSignatureError> {
79 ssi_jws::sign_bytes(algorithm, bytes, key).map_err(MessageSignatureError::signature_failed)
80 }
81}
82
83impl VerificationMethod for BlockchainVerificationMethod2021 {
84 fn id(&self) -> &Iri {
85 self.id.as_iri()
86 }
87
88 fn controller(&self) -> Option<&Iri> {
89 Some(self.controller.as_iri())
90 }
91}
92
93impl VerificationMethodSet for BlockchainVerificationMethod2021 {
94 type TypeSet = &'static str;
95
96 fn type_set() -> Self::TypeSet {
97 Self::NAME
98 }
99}
100
101impl TypedVerificationMethod for BlockchainVerificationMethod2021 {
102 fn expected_type() -> Option<ExpectedType> {
103 Some(BLOCKCHAIN_VERIFICATION_METHOD_2021_TYPE.to_string().into())
104 }
105
106 fn type_match(ty: &str) -> bool {
107 ty == BLOCKCHAIN_VERIFICATION_METHOD_2021_TYPE
108 }
109
110 fn type_(&self) -> &str {
111 BLOCKCHAIN_VERIFICATION_METHOD_2021_TYPE
112 }
113}
114
115impl TryFrom<GenericVerificationMethod> for BlockchainVerificationMethod2021 {
116 type Error = InvalidVerificationMethod;
117
118 fn try_from(m: GenericVerificationMethod) -> Result<Self, Self::Error> {
119 Ok(Self {
120 id: m.id,
121 controller: m.controller,
122 blockchain_account_id: m
123 .properties
124 .get("blockchainAccountId")
125 .ok_or_else(|| InvalidVerificationMethod::missing_property("blockchainAccountId"))?
126 .as_str()
127 .ok_or_else(|| InvalidVerificationMethod::invalid_property("blockchainAccountId"))?
128 .parse()
129 .map_err(|_| InvalidVerificationMethod::invalid_property("blockchainAccountId"))?,
130 })
131 }
132}