cml_crypto/chain_crypto/
sign.rs

1use crate::chain_crypto::{
2    bech32::{self, Bech32},
3    key,
4};
5use crate::typed_bytes::{ByteArray, ByteSlice};
6use cbor_event::{de::Deserializer, se::Serializer};
7use hex::FromHexError;
8use std::{fmt, marker::PhantomData, str::FromStr};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum Verification {
12    Failed,
13    Success,
14}
15
16impl From<bool> for Verification {
17    fn from(b: bool) -> Self {
18        if b {
19            Verification::Success
20        } else {
21            Verification::Failed
22        }
23    }
24}
25
26#[derive(Debug, Copy, Clone, PartialEq, Eq)]
27pub enum SignatureError {
28    SizeInvalid { expected: usize, got: usize }, // expected, got in bytes
29    StructureInvalid,
30}
31
32#[derive(Debug, Clone, PartialEq)]
33pub enum SignatureFromStrError {
34    HexMalformed(FromHexError),
35    Invalid(SignatureError),
36}
37
38pub trait VerificationAlgorithm: key::AsymmetricPublicKey {
39    type Signature: AsRef<[u8]> + Clone;
40
41    const SIGNATURE_SIZE: usize;
42    const SIGNATURE_BECH32_HRP: &'static str;
43
44    fn verify_bytes(pubkey: &Self::Public, signature: &Self::Signature, msg: &[u8])
45        -> Verification;
46
47    fn signature_from_bytes(data: &[u8]) -> Result<Self::Signature, SignatureError>;
48}
49
50pub trait SigningAlgorithm: key::AsymmetricKey
51where
52    Self::PubAlg: VerificationAlgorithm,
53{
54    fn sign(key: &Self::Secret, msg: &[u8]) -> <Self::PubAlg as VerificationAlgorithm>::Signature;
55}
56
57pub struct Signature<T: ?Sized, A: VerificationAlgorithm> {
58    pub signdata: A::Signature,
59    phantom: PhantomData<T>,
60}
61
62impl<A: VerificationAlgorithm, T> fmt::Debug for Signature<T, A> {
63    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64        write!(f, "{}", hex::encode(self.signdata.as_ref()))
65    }
66}
67impl<A: VerificationAlgorithm, T> fmt::Display for Signature<T, A> {
68    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69        write!(f, "{}", hex::encode(self.signdata.as_ref()))
70    }
71}
72impl<T, A: VerificationAlgorithm> FromStr for Signature<T, A> {
73    type Err = SignatureFromStrError;
74
75    fn from_str(hex: &str) -> Result<Self, Self::Err> {
76        let bytes = hex::decode(hex).map_err(SignatureFromStrError::HexMalformed)?;
77        Self::from_binary(&bytes).map_err(SignatureFromStrError::Invalid)
78    }
79}
80
81impl fmt::Display for SignatureError {
82    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83        match self {
84            SignatureError::SizeInvalid { expected, got } => {
85                write!(f, "Invalid Signature size expecting {expected} got {got}")
86            }
87            SignatureError::StructureInvalid => write!(f, "Invalid Signature structure"),
88        }
89    }
90}
91impl fmt::Display for SignatureFromStrError {
92    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93        match self {
94            SignatureFromStrError::HexMalformed(_) => "hex encoding malformed",
95            SignatureFromStrError::Invalid(_) => "invalid signature data",
96        }
97        .fmt(f)
98    }
99}
100
101impl std::error::Error for SignatureError {}
102impl std::error::Error for SignatureFromStrError {
103    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
104        match self {
105            SignatureFromStrError::HexMalformed(e) => Some(e),
106            SignatureFromStrError::Invalid(e) => Some(e),
107        }
108    }
109}
110
111impl<A: VerificationAlgorithm, T> Signature<T, A> {
112    pub fn from_binary(sig: &[u8]) -> Result<Self, SignatureError> {
113        Ok(Signature {
114            signdata: A::signature_from_bytes(sig)?,
115            phantom: PhantomData,
116        })
117    }
118    pub fn coerce<U>(self) -> Signature<U, A> {
119        Signature {
120            signdata: self.signdata,
121            phantom: PhantomData,
122        }
123    }
124
125    pub fn safe_coerce<U: SafeSignatureCoerce<T>>(self) -> Signature<U, A> {
126        Signature {
127            signdata: self.signdata,
128            phantom: PhantomData,
129        }
130    }
131}
132
133pub trait SafeSignatureCoerce<T> {}
134
135impl<'a, T> SafeSignatureCoerce<ByteArray<T>> for ByteSlice<'a, T> {}
136
137impl<A: VerificationAlgorithm, T: AsRef<[u8]>> Signature<T, A> {
138    #[must_use]
139    pub fn verify(&self, publickey: &key::PublicKey<A>, object: &T) -> Verification {
140        <A as VerificationAlgorithm>::verify_bytes(&publickey.0, &self.signdata, object.as_ref())
141    }
142}
143
144impl<A: VerificationAlgorithm, T: ?Sized> Signature<T, A> {
145    #[must_use]
146    pub fn verify_slice(&self, publickey: &key::PublicKey<A>, slice: &[u8]) -> Verification {
147        <A as VerificationAlgorithm>::verify_bytes(&publickey.0, &self.signdata, slice)
148    }
149}
150
151/*
152impl<A: SigningAlgorithm, T: AsRef<[u8]>> Signature<T, A::Public>
153    where <A as key::AsymmetricKey>::Public: VerificationAlgorithm,
154{
155    pub fn generate(secretkey: &key::SecretKey<A>, object: &T) -> Signature<T, A::Public> {
156        Signature {
157            signdata: <A as SigningAlgorithm>::sign(&secretkey.0, object.as_ref()),
158            phantom: PhantomData,
159        }
160    }
161}
162*/
163impl<A: SigningAlgorithm> key::SecretKey<A>
164where
165    <A as key::AsymmetricKey>::PubAlg: VerificationAlgorithm,
166{
167    pub fn sign<T: AsRef<[u8]>>(&self, object: &T) -> Signature<T, A::PubAlg> {
168        Signature {
169            signdata: <A as SigningAlgorithm>::sign(&self.0, object.as_ref()),
170            phantom: PhantomData,
171        }
172    }
173
174    pub fn sign_slice<T: ?Sized>(&self, slice: &[u8]) -> Signature<T, A::PubAlg> {
175        Signature {
176            signdata: <A as SigningAlgorithm>::sign(&self.0, slice),
177            phantom: PhantomData,
178        }
179    }
180}
181
182impl<T, A: VerificationAlgorithm> Clone for Signature<T, A> {
183    fn clone(&self) -> Self {
184        Signature {
185            signdata: self.signdata.clone(),
186            phantom: std::marker::PhantomData,
187        }
188    }
189}
190
191impl<T: ?Sized, A: VerificationAlgorithm> AsRef<[u8]> for Signature<T, A> {
192    fn as_ref(&self) -> &[u8] {
193        self.signdata.as_ref()
194    }
195}
196
197impl<T, A: VerificationAlgorithm> Bech32 for Signature<T, A> {
198    const BECH32_HRP: &'static str = A::SIGNATURE_BECH32_HRP;
199
200    fn try_from_bech32_str(bech32_str: &str) -> Result<Self, bech32::Error> {
201        let bytes = bech32::try_from_bech32_to_bytes::<Self>(bech32_str)?;
202        Self::from_binary(&bytes).map_err(bech32::Error::data_invalid)
203    }
204
205    fn to_bech32_str(&self) -> String {
206        bech32::to_bech32_from_bytes::<Self>(self.as_ref())
207    }
208}
209
210impl<T, A: VerificationAlgorithm> std::cmp::PartialEq<Self> for Signature<T, A> {
211    fn eq(&self, other: &Self) -> bool {
212        self.as_ref().eq(other.as_ref())
213    }
214}
215
216impl<T, A: VerificationAlgorithm> std::cmp::Eq for Signature<T, A> {}
217
218impl<U, A: VerificationAlgorithm> cbor_event::se::Serialize for Signature<U, A> {
219    fn serialize<'se, W: std::io::Write>(
220        &self,
221        serializer: &'se mut Serializer<W>,
222    ) -> cbor_event::Result<&'se mut Serializer<W>> {
223        serializer.write_bytes(self.as_ref())
224    }
225}
226
227impl<U, A: VerificationAlgorithm> cbor_event::de::Deserialize for Signature<U, A> {
228    fn deserialize<R: std::io::BufRead>(raw: &mut Deserializer<R>) -> cbor_event::Result<Self> {
229        let result = Signature::<U, A>::from_binary(raw.bytes()?.as_ref())
230            .map_err(|err| cbor_event::Error::CustomError(format!("{err}")))?;
231        Ok(result)
232    }
233}
234
235impl<U, A: VerificationAlgorithm> serde::Serialize for Signature<U, A> {
236    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
237    where
238        S: serde::Serializer,
239    {
240        serializer.serialize_str(&hex::encode(self.as_ref()))
241    }
242}
243
244impl<'de, U, A: VerificationAlgorithm> serde::de::Deserialize<'de> for Signature<U, A> {
245    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
246    where
247        D: serde::de::Deserializer<'de>,
248    {
249        let s = <String as serde::de::Deserialize>::deserialize(deserializer)?;
250        Signature::<U, A>::from_str(&s).map_err(|_e| {
251            serde::de::Error::invalid_value(
252                serde::de::Unexpected::Str(&s),
253                &"hex bytes for signature",
254            )
255        })
256    }
257}
258
259#[cfg(test)]
260pub(crate) mod test {
261    use super::*;
262    use crate::chain_crypto::key::{AsymmetricKey, KeyPair};
263
264    pub(crate) fn keypair_signing_ok<A: AsymmetricKey + SigningAlgorithm>(
265        input: (KeyPair<A>, Vec<u8>),
266    ) -> bool
267    where
268        <A as AsymmetricKey>::PubAlg: VerificationAlgorithm,
269    {
270        let (sk, pk) = input.0.into_keys();
271        let data = input.1;
272
273        let signature = sk.sign(&data);
274        signature.verify(&pk, &data) == Verification::Success
275    }
276
277    pub(crate) fn keypair_signing_ko<A: AsymmetricKey + SigningAlgorithm>(
278        input: (KeyPair<A>, KeyPair<A>, Vec<u8>),
279    ) -> bool
280    where
281        <A as AsymmetricKey>::PubAlg: VerificationAlgorithm,
282    {
283        let (sk, pk) = input.0.into_keys();
284        let pk_random = input.1.public_key();
285        let data = input.2;
286
287        if &pk == pk_random {
288            return true;
289        }
290
291        let signature = sk.sign(&data);
292        signature.verify(pk_random, &data) == Verification::Failed
293    }
294}