cardano_serialization_lib/chain_crypto/
sign.rs

1use crate::chain_crypto::{
2    bech32::{self, Bech32},
3    key,
4};
5use crate::typed_bytes::{ByteArray, ByteSlice};
6use hex::FromHexError;
7use std::{fmt, marker::PhantomData, str::FromStr};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum Verification {
11    Failed,
12    Success,
13}
14
15impl From<bool> for Verification {
16    fn from(b: bool) -> Self {
17        if b {
18            Verification::Success
19        } else {
20            Verification::Failed
21        }
22    }
23}
24
25#[derive(Debug, Copy, Clone, PartialEq, Eq)]
26pub enum SignatureError {
27    SizeInvalid { expected: usize, got: usize }, // expected, got in bytes
28    StructureInvalid,
29}
30
31#[derive(Debug, Clone, PartialEq)]
32pub enum SignatureFromStrError {
33    HexMalformed(FromHexError),
34    Invalid(SignatureError),
35}
36
37pub trait VerificationAlgorithm: key::AsymmetricPublicKey {
38    type Signature: AsRef<[u8]> + Clone;
39
40    const SIGNATURE_SIZE: usize;
41    const SIGNATURE_BECH32_HRP: &'static str;
42
43    fn verify_bytes(pubkey: &Self::Public, signature: &Self::Signature, msg: &[u8])
44        -> Verification;
45
46    fn signature_from_bytes(data: &[u8]) -> Result<Self::Signature, SignatureError>;
47}
48
49pub trait SigningAlgorithm: key::AsymmetricKey
50where
51    Self::PubAlg: VerificationAlgorithm,
52{
53    fn sign(key: &Self::Secret, msg: &[u8]) -> <Self::PubAlg as VerificationAlgorithm>::Signature;
54}
55
56#[derive(Hash)]
57pub struct Signature<T: ?Sized, A: VerificationAlgorithm> {
58    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 } => write!(
85                f,
86                "Invalid Signature size expecting {} got {}",
87                expected, got
88            ),
89            SignatureError::StructureInvalid => write!(f, "Invalid Signature structure"),
90        }
91    }
92}
93impl fmt::Display for SignatureFromStrError {
94    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95        match self {
96            SignatureFromStrError::HexMalformed(_) => "hex encoding malformed",
97            SignatureFromStrError::Invalid(_) => "invalid signature data",
98        }
99        .fmt(f)
100    }
101}
102
103impl std::error::Error for SignatureError {}
104impl std::error::Error for SignatureFromStrError {
105    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
106        match self {
107            SignatureFromStrError::HexMalformed(e) => Some(e),
108            SignatureFromStrError::Invalid(e) => Some(e),
109        }
110    }
111}
112
113impl<A: VerificationAlgorithm, T> Signature<T, A> {
114    pub fn from_binary(sig: &[u8]) -> Result<Self, SignatureError> {
115        Ok(Signature {
116            signdata: A::signature_from_bytes(sig)?,
117            phantom: PhantomData,
118        })
119    }
120    pub fn coerce<U>(self) -> Signature<U, A> {
121        Signature {
122            signdata: self.signdata,
123            phantom: PhantomData,
124        }
125    }
126
127    pub fn safe_coerce<U: SafeSignatureCoerce<T>>(self) -> Signature<U, A> {
128        Signature {
129            signdata: self.signdata,
130            phantom: PhantomData,
131        }
132    }
133}
134
135pub trait SafeSignatureCoerce<T> {}
136
137impl<'a, T> SafeSignatureCoerce<ByteArray<T>> for ByteSlice<'a, T> {}
138
139impl<A: VerificationAlgorithm, T: AsRef<[u8]>> Signature<T, A> {
140    #[must_use]
141    pub fn verify(&self, publickey: &key::PublicKey<A>, object: &T) -> Verification {
142        <A as VerificationAlgorithm>::verify_bytes(&publickey.0, &self.signdata, object.as_ref())
143    }
144}
145
146impl<A: VerificationAlgorithm, T: ?Sized> Signature<T, A> {
147    #[must_use]
148    pub fn verify_slice(&self, publickey: &key::PublicKey<A>, slice: &[u8]) -> Verification {
149        <A as VerificationAlgorithm>::verify_bytes(&publickey.0, &self.signdata, slice)
150    }
151}
152
153/*
154impl<A: SigningAlgorithm, T: AsRef<[u8]>> Signature<T, A::Public>
155    where <A as key::AsymmetricKey>::Public: VerificationAlgorithm,
156{
157    pub fn generate(secretkey: &key::SecretKey<A>, object: &T) -> Signature<T, A::Public> {
158        Signature {
159            signdata: <A as SigningAlgorithm>::sign(&secretkey.0, object.as_ref()),
160            phantom: PhantomData,
161        }
162    }
163}
164*/
165impl<A: SigningAlgorithm> key::SecretKey<A>
166where
167    <A as key::AsymmetricKey>::PubAlg: VerificationAlgorithm,
168{
169    pub fn sign<T: AsRef<[u8]>>(&self, object: &T) -> Signature<T, A::PubAlg> {
170        Signature {
171            signdata: <A as SigningAlgorithm>::sign(&self.0, object.as_ref()),
172            phantom: PhantomData,
173        }
174    }
175
176    pub fn sign_slice<T: ?Sized>(&self, slice: &[u8]) -> Signature<T, A::PubAlg> {
177        Signature {
178            signdata: <A as SigningAlgorithm>::sign(&self.0, slice),
179            phantom: PhantomData,
180        }
181    }
182}
183
184impl<T, A: VerificationAlgorithm> Clone for Signature<T, A> {
185    fn clone(&self) -> Self {
186        Signature {
187            signdata: self.signdata.clone(),
188            phantom: std::marker::PhantomData,
189        }
190    }
191}
192
193impl<T, A: VerificationAlgorithm> PartialEq<Self> for Signature<T, A> {
194    fn eq(&self, other: &Self) -> bool {
195        self.signdata.as_ref() == other.signdata.as_ref() && self.phantom == other.phantom
196    }
197}
198
199impl<T, A: VerificationAlgorithm> Eq for Signature<T, A> {}
200
201impl<T: ?Sized, A: VerificationAlgorithm> AsRef<[u8]> for Signature<T, A> {
202    fn as_ref(&self) -> &[u8] {
203        self.signdata.as_ref()
204    }
205}
206
207impl<T, A: VerificationAlgorithm> Bech32 for Signature<T, A> {
208    const BECH32_HRP: &'static str = A::SIGNATURE_BECH32_HRP;
209
210    fn try_from_bech32_str(bech32_str: &str) -> Result<Self, bech32::Error> {
211        let bytes = bech32::try_from_bech32_to_bytes::<Self>(bech32_str)?;
212        Self::from_binary(&bytes).map_err(bech32::Error::data_invalid)
213    }
214
215    fn to_bech32_str(&self) -> String {
216        bech32::to_bech32_from_bytes::<Self>(self.as_ref())
217    }
218}
219
220#[cfg(test)]
221pub(crate) mod test {
222    use super::*;
223    use crate::chain_crypto::key::{AsymmetricKey, KeyPair};
224
225    pub(crate) fn keypair_signing_ok<A: AsymmetricKey + SigningAlgorithm>(
226        input: (KeyPair<A>, Vec<u8>),
227    ) -> bool
228    where
229        <A as AsymmetricKey>::PubAlg: VerificationAlgorithm,
230    {
231        let (sk, pk) = input.0.into_keys();
232        let data = input.1;
233
234        let signature = sk.sign(&data);
235        signature.verify(&pk, &data) == Verification::Success
236    }
237
238    pub(crate) fn keypair_signing_ko<A: AsymmetricKey + SigningAlgorithm>(
239        input: (KeyPair<A>, KeyPair<A>, Vec<u8>),
240    ) -> bool
241    where
242        <A as AsymmetricKey>::PubAlg: VerificationAlgorithm,
243    {
244        let (sk, pk) = input.0.into_keys();
245        let pk_random = input.1.public_key();
246        let data = input.2;
247
248        if &pk == pk_random {
249            return true;
250        }
251
252        let signature = sk.sign(&data);
253        signature.verify(&pk_random, &data) == Verification::Failed
254    }
255}