ssi_verification_methods/methods/unspecified/
blockchain_verification_method_2021.rs

1use 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
15// pub const BLOCKCHAIN_VERIFICATION_METHOD_2021_IRI: &Iri =
16//     iri!("https://w3id.org/security#BlockchainVerificationMethod2021");
17
18pub const BLOCKCHAIN_VERIFICATION_METHOD_2021_TYPE: &str = "BlockchainVerificationMethod2021";
19
20/// BlockchainVerificationMethod2021.
21///
22/// See: <https://w3id.org/security#BlockchainVerificationMethod2021>.
23#[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    /// Key identifier.
39    #[ld(id)]
40    pub id: IriBuf,
41
42    /// Controller of the verification method.
43    #[ld("sec:controller")]
44    pub controller: UriBuf,
45
46    /// Blockchain accound ID.
47    #[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}