ssi_verification_methods_core/signature/
protocol.rs1use std::borrow::Cow;
2
3use ssi_claims_core::MessageSignatureError;
4use ssi_crypto::algorithm::{SignatureAlgorithmInstance, SignatureAlgorithmType};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct WithProtocol<A, P>(pub A, pub P);
8
9impl<A, P> WithProtocol<A, P> {
10 pub fn new(algorithm: A, protocol: P) -> Self {
11 Self(algorithm, protocol)
12 }
13}
14
15impl<A: SignatureAlgorithmType, P: Copy> SignatureAlgorithmType for WithProtocol<A, P> {
16 type Instance = WithProtocol<A::Instance, P>;
17}
18
19impl<I: SignatureAlgorithmInstance, P: Copy> SignatureAlgorithmInstance for WithProtocol<I, P> {
20 type Algorithm = WithProtocol<I::Algorithm, P>;
21
22 fn algorithm(&self) -> Self::Algorithm {
23 WithProtocol(self.0.algorithm(), self.1)
24 }
25}
26
27pub trait SignatureProtocol<A>: Copy {
45 fn prepare_message<'b>(&self, bytes: &'b [u8]) -> Cow<'b, [u8]> {
46 Cow::Borrowed(bytes)
47 }
48
49 fn prepare_messages<'b>(&self, bytes: &'b [Vec<u8>]) -> Cow<'b, [Vec<u8>]> {
50 Cow::Borrowed(bytes)
51 }
52
53 fn encode_signature(
54 &self,
55 _algorithm: A,
56 signature: Vec<u8>,
57 ) -> Result<Vec<u8>, MessageSignatureError> {
58 Ok(signature)
59 }
60
61 fn decode_signature<'s>(
62 &self,
63 encoded_signature: &'s [u8],
64 ) -> Result<Cow<'s, [u8]>, InvalidProtocolSignature> {
65 Ok(Cow::Borrowed(encoded_signature))
66 }
67}
68
69#[derive(Debug, thiserror::Error)]
70#[error("invalid protocol signature")]
71pub struct InvalidProtocolSignature;
72
73impl<A> SignatureProtocol<A> for () {}
74
75#[derive(Debug, Clone, Copy)]
82pub struct Base58BtcMultibase;
83
84impl Base58BtcMultibase {
85 pub fn encode_signature(signature: &[u8]) -> Vec<u8> {
88 multibase::encode(multibase::Base::Base58Btc, signature).into_bytes()
89 }
90
91 pub fn decode_signature(encoded_signature: &[u8]) -> Result<Vec<u8>, InvalidProtocolSignature> {
92 let encoded_signature =
93 std::str::from_utf8(encoded_signature).map_err(|_| InvalidProtocolSignature)?;
94 let (base, signature) =
95 multibase::decode(encoded_signature).map_err(|_| InvalidProtocolSignature)?;
96 if base == multibase::Base::Base58Btc {
97 Ok(signature)
98 } else {
99 Err(InvalidProtocolSignature)
100 }
101 }
102}
103
104impl<A> SignatureProtocol<A> for Base58BtcMultibase {
105 fn encode_signature(
106 &self,
107 _algorithm: A,
108 signature: Vec<u8>,
109 ) -> Result<Vec<u8>, MessageSignatureError> {
110 Ok(Self::encode_signature(&signature))
111 }
112
113 fn decode_signature<'s>(
114 &self,
115 encoded_signature: &'s [u8],
116 ) -> Result<Cow<'s, [u8]>, InvalidProtocolSignature> {
117 Self::decode_signature(encoded_signature).map(Cow::Owned)
118 }
119}
120
121#[derive(Debug, Clone, Copy)]
126pub struct Base58Btc;
127
128impl Base58Btc {
129 pub fn encode_signature(signature: &[u8]) -> Vec<u8> {
132 bs58::encode(signature).into_vec()
133 }
134
135 pub fn decode_signature(encoded_signature: &[u8]) -> Result<Vec<u8>, InvalidProtocolSignature> {
136 bs58::decode(encoded_signature)
137 .into_vec()
138 .map_err(|_| InvalidProtocolSignature)
139 }
140}
141
142impl<A> SignatureProtocol<A> for Base58Btc {
143 fn encode_signature(
146 &self,
147 _algorithm: A,
148 signature: Vec<u8>,
149 ) -> Result<Vec<u8>, MessageSignatureError> {
150 Ok(Self::encode_signature(&signature))
151 }
152
153 fn decode_signature<'s>(
154 &self,
155 encoded_signature: &'s [u8],
156 ) -> Result<Cow<'s, [u8]>, InvalidProtocolSignature> {
157 Self::decode_signature(encoded_signature).map(Cow::Owned)
158 }
159}
160
161#[derive(Debug, Clone, Copy)]
169pub struct EthereumWallet;
170
171impl EthereumWallet {
172 pub fn prepare_message(bytes: &[u8]) -> Vec<u8> {
173 let mut result = format!("\x19Ethereum Signed Message:\n{}", bytes.len()).into_bytes();
174 result.extend_from_slice(bytes);
175 result
176 }
177
178 pub fn encode_signature(signature: &[u8]) -> Vec<u8> {
179 assert_eq!(signature.len(), 65);
180 let mut result = Vec::new();
181 result.extend_from_slice(b"0x");
182 result.resize(132, 0);
183
184 hex::encode_to_slice(&signature[..64], &mut result[2..130]).unwrap();
186
187 let rec_id = signature[64] + 27;
189 hex::encode_to_slice(std::slice::from_ref(&rec_id), &mut result[130..]).unwrap();
190
191 result
193 }
194
195 pub fn decode_signature(encoded_signature: &[u8]) -> Result<Vec<u8>, InvalidProtocolSignature> {
196 let hex = encoded_signature
197 .strip_prefix(b"0x")
198 .ok_or(InvalidProtocolSignature)?;
199
200 let mut signature = hex::decode(hex).map_err(|_| InvalidProtocolSignature)?;
201 signature[64] -= 27; Ok(signature)
204 }
205}
206
207impl<A> SignatureProtocol<A> for EthereumWallet {
208 fn prepare_message<'b>(&self, bytes: &'b [u8]) -> Cow<'b, [u8]> {
209 Cow::Owned(Self::prepare_message(bytes))
210 }
211
212 fn encode_signature(
213 &self,
214 _algorithm: A,
215 signature: Vec<u8>,
216 ) -> Result<Vec<u8>, MessageSignatureError> {
217 Ok(Self::encode_signature(&signature))
218 }
219
220 fn decode_signature<'s>(
221 &self,
222 encoded_signature: &'s [u8],
223 ) -> Result<Cow<'s, [u8]>, InvalidProtocolSignature> {
224 Self::decode_signature(encoded_signature).map(Cow::Owned)
225 }
226}