ssi_verification_methods/methods/unspecified/tezos/
tezos_method_2021.rs1use iref::{Iri, IriBuf, UriBuf};
2use serde::{Deserialize, Serialize};
3use ssi_claims_core::{InvalidProof, MessageSignatureError, ProofValidationError, ProofValidity};
4use ssi_crypto::algorithm::AnyBlake2b;
5use ssi_jwk::JWK;
6use ssi_verification_methods_core::VerificationMethodSet;
7use static_iref::iri;
8use std::{collections::BTreeMap, hash::Hash};
9
10use crate::{
11 ExpectedType, GenericVerificationMethod, InvalidVerificationMethod, SigningMethod,
12 TypedVerificationMethod, VerificationMethod,
13};
14
15pub const TEZOS_METHOD_2021_IRI: &Iri = iri!("https://w3id.org/security#TezosMethod2021");
16
17pub const TEZOS_METHOD_2021_TYPE: &str = "TezosMethod2021";
18
19#[derive(
40 Debug,
41 Clone,
42 PartialEq,
43 Eq,
44 Hash,
45 Serialize,
46 Deserialize,
47 linked_data::Serialize,
48 linked_data::Deserialize,
49)]
50#[serde(tag = "type", rename = "TezosMethod2021")]
51#[ld(prefix("sec" = "https://w3id.org/security#"))]
52pub struct TezosMethod2021 {
53 #[ld(id)]
55 pub id: IriBuf,
56
57 #[ld("sec:controller")]
59 pub controller: UriBuf,
60
61 #[serde(flatten)]
62 #[ld(flatten)]
63 pub public_key: PublicKey,
64}
65
66impl TezosMethod2021 {
67 pub const NAME: &'static str = TEZOS_METHOD_2021_TYPE;
68 pub const IRI: &'static Iri = TEZOS_METHOD_2021_IRI;
69
70 pub fn public_key_jwk(&self) -> Option<&JWK> {
71 self.public_key.as_jwk()
72 }
73
74 pub fn verify_bytes(
75 &self,
76 public_key_jwk: Option<&JWK>,
77 message: &[u8],
78 algorithm: AnyBlake2b,
79 signature: &[u8],
80 ) -> Result<ProofValidity, ProofValidationError> {
81 self.public_key
82 .verify_bytes(public_key_jwk, message, algorithm, signature)
83 }
84}
85
86#[derive(
87 Debug,
88 Clone,
89 PartialEq,
90 Eq,
91 Hash,
92 Serialize,
93 Deserialize,
94 linked_data::Serialize,
95 linked_data::Deserialize,
96)]
97#[ld(prefix("sec" = "https://w3id.org/security#"))]
98pub enum PublicKey {
99 #[serde(rename = "publicKeyJwk")]
100 #[ld("sec:publicKeyJwk")]
101 Jwk(Box<JWK>),
102
103 #[serde(rename = "blockchainAccountId")]
104 #[ld("sec:blockchainAccountId")]
105 BlockchainAccountId(ssi_caips::caip10::BlockchainAccountId),
106}
107
108impl PublicKey {
109 pub fn as_jwk(&self) -> Option<&JWK> {
110 match self {
111 Self::Jwk(jwk) => Some(jwk),
112 Self::BlockchainAccountId(_) => None,
113 }
114 }
115
116 pub fn matches(&self, other: &JWK) -> Result<bool, ProofValidationError> {
117 use ssi_caips::caip10::BlockchainAccountIdVerifyError as VerifyError;
118 match self {
119 Self::Jwk(jwk) => Ok(jwk.equals_public(other)),
120 Self::BlockchainAccountId(id) => match id.verify(other) {
121 Err(VerifyError::UnknownChainId(_) | VerifyError::HashError(_)) => {
122 Err(ProofValidationError::InvalidKey)
123 }
124 Err(VerifyError::KeyMismatch(_, _)) => Ok(false),
125 Ok(()) => Ok(true),
126 },
127 }
128 }
129
130 fn from_generic(
131 properties: &BTreeMap<String, serde_json::Value>,
132 ) -> Result<Self, InvalidVerificationMethod> {
133 match properties.get("publicKeyJwk") {
134 Some(value) => Ok(Self::Jwk(Box::new(
135 serde_json::from_value(value.clone())
136 .map_err(|_| InvalidVerificationMethod::invalid_property("publicKeyJwk"))?,
137 ))),
138 None => match properties.get("blockchainAccountId") {
139 Some(serde_json::Value::String(value)) => {
140 Ok(Self::BlockchainAccountId(value.parse().map_err(|_| {
141 InvalidVerificationMethod::invalid_property("blockchainAccountId")
142 })?))
143 }
144 Some(_) => Err(InvalidVerificationMethod::invalid_property(
145 "blockchainAccountId",
146 )),
147 None => Err(InvalidVerificationMethod::missing_property("publicKeyJwk")),
148 },
149 }
150 }
151
152 pub fn verify_bytes(
153 &self,
154 public_key_jwk: Option<&JWK>,
155 message: &[u8],
156 algorithm: AnyBlake2b,
157 signature: &[u8],
158 ) -> Result<ProofValidity, ProofValidationError> {
159 match self {
160 Self::BlockchainAccountId(account_id) => match public_key_jwk {
161 Some(jwk) => match account_id.verify(jwk) {
162 Ok(()) => Ok(
163 ssi_jws::verify_bytes(algorithm.into(), message, jwk, signature)
164 .map_err(|_| InvalidProof::Signature),
165 ),
166 Err(_) => Ok(Err(InvalidProof::KeyMismatch)),
167 },
168 None => Err(ProofValidationError::MissingPublicKey),
169 },
170 Self::Jwk(jwk) => Ok(
171 ssi_jws::verify_bytes(algorithm.into(), message, jwk, signature)
172 .map_err(|_| InvalidProof::Signature),
173 ),
174 }
175 }
176
177 pub fn sign_bytes(
178 &self,
179 key: &JWK,
180 algorithm: ssi_crypto::algorithm::AnyBlake2b,
181 bytes: &[u8],
182 ) -> Result<Vec<u8>, MessageSignatureError> {
183 ssi_jws::sign_bytes(algorithm.into(), bytes, key)
184 .map_err(MessageSignatureError::signature_failed)
185 }
186}
187
188impl VerificationMethod for TezosMethod2021 {
189 fn id(&self) -> &Iri {
190 self.id.as_iri()
191 }
192
193 fn controller(&self) -> Option<&Iri> {
194 Some(self.controller.as_iri())
195 }
196}
197
198impl VerificationMethodSet for TezosMethod2021 {
199 type TypeSet = &'static str;
200
201 fn type_set() -> Self::TypeSet {
202 Self::NAME
203 }
204}
205
206impl TypedVerificationMethod for TezosMethod2021 {
207 fn expected_type() -> Option<ExpectedType> {
208 Some(TEZOS_METHOD_2021_TYPE.to_string().into())
209 }
210
211 fn type_match(ty: &str) -> bool {
212 ty == TEZOS_METHOD_2021_TYPE
213 }
214
215 fn type_(&self) -> &str {
216 TEZOS_METHOD_2021_TYPE
217 }
218}
219
220impl TryFrom<GenericVerificationMethod> for TezosMethod2021 {
221 type Error = InvalidVerificationMethod;
222
223 fn try_from(value: GenericVerificationMethod) -> Result<Self, Self::Error> {
224 if value.type_ == TEZOS_METHOD_2021_TYPE {
225 Ok(Self {
226 id: value.id,
227 controller: value.controller,
228 public_key: PublicKey::from_generic(&value.properties)?,
229 })
230 } else {
231 Err(InvalidVerificationMethod::invalid_type_name(
232 &value.type_,
233 TEZOS_METHOD_2021_TYPE,
234 ))
235 }
236 }
237}
238
239impl SigningMethod<JWK, ssi_crypto::algorithm::AnyBlake2b> for TezosMethod2021 {
240 fn sign_bytes(
241 &self,
242 key: &JWK,
243 algorithm: ssi_crypto::algorithm::AnyBlake2b,
244 bytes: &[u8],
245 ) -> Result<Vec<u8>, MessageSignatureError> {
246 ssi_jws::sign_bytes(algorithm.into(), bytes, key)
247 .map_err(MessageSignatureError::signature_failed)
248 }
249}