cml_crypto/impl_mockchain/
key.rs

1//! Module provides cryptographic utilities and types related to
2//! the user keys.
3//!
4use crate::chain_core::mempack::{read_mut_slice, ReadBuf, ReadError, Readable};
5use crate::chain_core::property;
6use crate::chain_crypto as crypto;
7use crate::chain_crypto::{
8    AsymmetricKey, AsymmetricPublicKey, SecretKey, SigningAlgorithm, VerificationAlgorithm,
9};
10use rand::{CryptoRng, RngCore};
11
12#[derive(Clone)]
13pub enum EitherEd25519SecretKey {
14    Extended(crypto::SecretKey<crypto::Ed25519Extended>),
15    Normal(crypto::SecretKey<crypto::Ed25519>),
16}
17
18impl EitherEd25519SecretKey {
19    pub fn generate<R: RngCore + CryptoRng>(rng: R) -> Self {
20        EitherEd25519SecretKey::Extended(SecretKey::generate(rng))
21    }
22
23    pub fn to_public(&self) -> crypto::PublicKey<crypto::Ed25519> {
24        match self {
25            EitherEd25519SecretKey::Extended(sk) => sk.to_public(),
26            EitherEd25519SecretKey::Normal(sk) => sk.to_public(),
27        }
28    }
29
30    pub fn sign<T: AsRef<[u8]>>(&self, dat: &T) -> crypto::Signature<T, crypto::Ed25519> {
31        match self {
32            EitherEd25519SecretKey::Extended(sk) => sk.sign(dat),
33            EitherEd25519SecretKey::Normal(sk) => sk.sign(dat),
34        }
35    }
36
37    pub fn sign_slice<T: ?Sized>(&self, dat: &[u8]) -> crypto::Signature<T, crypto::Ed25519> {
38        match self {
39            EitherEd25519SecretKey::Extended(sk) => sk.sign_slice(dat),
40            EitherEd25519SecretKey::Normal(sk) => sk.sign_slice(dat),
41        }
42    }
43}
44
45pub type SpendingPublicKey = crypto::PublicKey<crypto::Ed25519>;
46pub type SpendingSignature<T> = crypto::Signature<T, crypto::Ed25519>;
47
48pub type Ed25519Signature<T> = crypto::Signature<T, crypto::Ed25519>;
49
50fn chain_crypto_pub_err(e: crypto::PublicKeyError) -> ReadError {
51    match e {
52        crypto::PublicKeyError::SizeInvalid => {
53            ReadError::StructureInvalid("publickey size invalid".to_string())
54        }
55        crypto::PublicKeyError::StructureInvalid => {
56            ReadError::StructureInvalid("publickey structure invalid".to_string())
57        }
58    }
59}
60fn chain_crypto_sig_err(e: crypto::SignatureError) -> ReadError {
61    match e {
62        crypto::SignatureError::SizeInvalid { expected, got } => ReadError::StructureInvalid(
63            format!("signature size invalid, expected {expected} got {got}"),
64        ),
65        crypto::SignatureError::StructureInvalid => {
66            ReadError::StructureInvalid("signature structure invalid".to_string())
67        }
68    }
69}
70
71#[inline]
72pub fn serialize_public_key<A: AsymmetricPublicKey, W: std::io::Write>(
73    key: &crypto::PublicKey<A>,
74    mut writer: W,
75) -> Result<(), std::io::Error> {
76    writer.write_all(key.as_ref())
77}
78#[inline]
79pub fn serialize_signature<A: VerificationAlgorithm, T, W: std::io::Write>(
80    signature: &crypto::Signature<T, A>,
81    mut writer: W,
82) -> Result<(), std::io::Error> {
83    writer.write_all(signature.as_ref())
84}
85#[inline]
86pub fn deserialize_public_key<A>(buf: &mut ReadBuf) -> Result<crypto::PublicKey<A>, ReadError>
87where
88    A: AsymmetricPublicKey,
89{
90    let mut bytes = vec![0u8; A::PUBLIC_KEY_SIZE];
91    read_mut_slice(buf, &mut bytes[..])?;
92    crypto::PublicKey::from_binary(&bytes).map_err(chain_crypto_pub_err)
93}
94#[inline]
95pub fn deserialize_signature<A, T>(buf: &mut ReadBuf) -> Result<crypto::Signature<T, A>, ReadError>
96where
97    A: VerificationAlgorithm,
98{
99    let mut bytes = vec![0u8; A::SIGNATURE_SIZE];
100    read_mut_slice(buf, &mut bytes[..])?;
101    crypto::Signature::from_binary(&bytes).map_err(chain_crypto_sig_err)
102}
103
104pub fn make_signature<T, A>(
105    spending_key: &crypto::SecretKey<A>,
106    data: &T,
107) -> crypto::Signature<T, A::PubAlg>
108where
109    A: SigningAlgorithm,
110    <A as AsymmetricKey>::PubAlg: VerificationAlgorithm,
111    T: property::Serialize,
112{
113    let bytes = data.serialize_as_vec().unwrap();
114    spending_key.sign(&bytes).coerce()
115}
116
117pub fn verify_signature<T, A>(
118    signature: &crypto::Signature<T, A>,
119    public_key: &crypto::PublicKey<A>,
120    data: &T,
121) -> crypto::Verification
122where
123    A: VerificationAlgorithm,
124    T: property::Serialize,
125{
126    let bytes = data.serialize_as_vec().unwrap();
127    signature.clone().coerce().verify(public_key, &bytes)
128}
129
130/// A serializable type T with a signature.
131pub struct Signed<T, A: VerificationAlgorithm> {
132    pub data: T,
133    pub sig: crypto::Signature<T, A>,
134}
135
136pub fn signed_new<T: property::Serialize, A: SigningAlgorithm>(
137    secret_key: &crypto::SecretKey<A>,
138    data: T,
139) -> Signed<T, A::PubAlg>
140where
141    A::PubAlg: VerificationAlgorithm,
142{
143    let bytes = data.serialize_as_vec().unwrap();
144    let signature = secret_key.sign(&bytes).coerce();
145    Signed {
146        data,
147        sig: signature,
148    }
149}
150
151impl<T: property::Serialize, A: VerificationAlgorithm> property::Serialize for Signed<T, A>
152where
153    std::io::Error: From<T::Error>,
154{
155    type Error = std::io::Error;
156    fn serialize<W: std::io::Write>(&self, mut writer: W) -> Result<(), Self::Error> {
157        self.data.serialize(&mut writer)?;
158        serialize_signature(&self.sig, &mut writer)?;
159        Ok(())
160    }
161}
162
163impl<T: Readable, A: VerificationAlgorithm> Readable for Signed<T, A> {
164    fn read(buf: &mut ReadBuf) -> Result<Self, ReadError> {
165        Ok(Signed {
166            data: T::read(buf)?,
167            sig: deserialize_signature(buf)?,
168        })
169    }
170}
171
172impl<T: PartialEq, A: VerificationAlgorithm> PartialEq<Self> for Signed<T, A> {
173    fn eq(&self, other: &Self) -> bool {
174        self.data.eq(&other.data) && self.sig.as_ref() == other.sig.as_ref()
175    }
176}
177impl<T: PartialEq, A: VerificationAlgorithm> Eq for Signed<T, A> {}
178impl<T: std::fmt::Debug, A: VerificationAlgorithm> std::fmt::Debug for Signed<T, A> {
179    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
180        write!(
181            f,
182            "Signed ( data: {:?}, signature: {:?} )",
183            self.data,
184            self.sig.as_ref()
185        )
186    }
187}
188impl<T: Clone, A: VerificationAlgorithm> Clone for Signed<T, A> {
189    fn clone(&self) -> Self {
190        Signed {
191            data: self.data.clone(),
192            sig: self.sig.clone(),
193        }
194    }
195}