static_dh_ecdh/
signatures.rs

1#![allow(warnings)]
2
3use core::convert::TryFrom;
4use core::convert::TryInto;
5
6use p256::ecdsa::{signature::Signer, signature::Verifier, Signature, SigningKey, VerifyingKey};
7use p256::EncodedPoint;
8use p384::NistP384;
9
10use rand_chacha::rand_core::{RngCore, SeedableRng};
11use rand_chacha::ChaChaRng;
12
13use crate::ecdh::affine_math::ECSignerType;
14use crate::ecdh::ecdh::{KeyExchange, ToBytes, ECDHNISTP384};
15use elliptic_curve::sec1::EncodedPoint as EncodedPointP384;
16
17use generic_array::GenericArray;
18
19use crate::{CryptoError, Result};
20
21// use libc_print::libc_println;
22
23/// A trait to implement ECDSA signatures for any curve type.
24///
25/// As `RustCrypto` is yet to support (i.e. no `Projective arithmetic` yet) curves P384, p521 or Brainpool
26/// I put together my own affine-point arithemtic impls leveraging types `SecretKey`, `PublicKey`, `EncodedPoint`
27/// from the `elliptic-curve` crate.
28///
29/// For now - all methods in this trait return byte-arrays (this is just a stop-gap solution)
30pub trait ECSignature {
31    /// Type `r` represents the r component of an ECDSA signature.
32    type r: AsRef<[u8]>;
33    /// Type `s` represents the s component of an ECDSA signature.
34    type s: AsRef<[u8]>;
35    /// A type to hold the raw-signature i.e. `r + s in bytes`.
36    type sbytes: AsRef<[u8]>;
37
38    /// Generate a ECDSA keypair.
39    ///
40    /// - This function borrows `SigningKey` and `VerifyingKey` types
41    /// from the p256 impl to compute ECDSASHA256 Signatures
42    ///
43    /// For other impls, we use a mix of `SecretKey`, `PublicKey`, `EncodedPoint` types.
44    /// borrowed from the elliptic-curve crate.
45    fn generate_keypair(&mut self, seed: [u8; 32]);
46    /// Function to sign messages of arbitrary length.
47    ///
48    /// - Returns the `signature as byte-array` or an Error.
49    ///
50    /// Note - we use affine point arithmetic of ECDSA calculation for curves other than p256
51    fn sign(&self, data: &[u8]) -> Result<Self::sbytes>;
52    /// Function to verify a signature.
53    ///
54    /// - Returns a `bool` is successful or an Error.
55    ///
56    /// Note - we use affine point arithmetic of ECDSA calculation for curves other than p256
57    fn verify(&self, data: &[u8], signature: &[u8]) -> Result<bool>;
58    /// The raw `r` component of a signature in bytes
59    fn r(s: Self::sbytes) -> Self::r;
60    /// The raw `s` component of a signature in bytes
61    fn s(s: Self::sbytes) -> Self::s;
62}
63
64/// A type to represent an ECDSA-SHA256 Signature. Tuple elements 0 and 1 represent the `signing and verifying` keys
65pub struct ECDSASHA256Signature(pub [u8; 32], pub [u8; 64]);
66
67impl ECSignature for ECDSASHA256Signature {
68    type r = [u8; 32];
69    type s = [u8; 32];
70    type sbytes = [u8; 64];
71
72    fn generate_keypair(&mut self, seed: [u8; 32]) {
73        let mut rng = ChaChaRng::from_seed(seed); // test seed value.
74        let mut dest = [0; 32];
75        rng.fill_bytes(&mut dest);
76        let signing_key = SigningKey::from_bytes(&dest).unwrap();
77        let verifying_key = VerifyingKey::from(&signing_key);
78        self.0 = signing_key.to_bytes().as_slice().try_into().unwrap();
79        self.1 = verifying_key
80            .to_encoded_point(false)
81            .to_untagged_bytes()
82            .unwrap()
83            .as_slice()
84            .try_into()
85            .unwrap();
86    }
87
88    fn sign(&self, data: &[u8]) -> Result<Self::sbytes> {
89        let signing_key = self.0;
90        let signature = SigningKey::from_bytes(&signing_key)
91            .map(|sk| sk.sign(data))
92            .map_err(|_| CryptoError::SignatureError);
93        signature
94            .map(|s| s.as_ref().try_into().unwrap())
95            .map_err(|_| CryptoError::SignatureError)
96    }
97
98    fn verify(&self, data: &[u8], signature: &[u8]) -> Result<bool> {
99        let verifying_key = self.1;
100        let generic_arr = GenericArray::clone_from_slice(&verifying_key);
101        let encoded_vk = EncodedPoint::from_untagged_bytes(&generic_arr);
102        let verifying_key = VerifyingKey::from_encoded_point(&encoded_vk)
103            .map_err(|_| CryptoError::SignatureError)?;
104        Ok(verifying_key
105            .verify(
106                data,
107                &Signature::try_from(signature)
108                    .expect("failed to parse serialized siganture bytes"),
109            )
110            .is_ok())
111    }
112
113    fn r(s: Self::sbytes) -> [u8; 32] {
114        let r_bytes = s.as_ref()[..32].try_into().unwrap();
115        r_bytes
116    }
117
118    fn s(s: Self::sbytes) -> [u8; 32] {
119        let s_bytes = s.as_ref()[32..].try_into().unwrap();
120        s_bytes
121    }
122}
123
124/// A type to represent an ECDSA-SHA384 Signature. Tuple elements 0 and 1 represent the `signing and verifying` keys
125pub struct ECDSASHA384Signature(pub [u8; 48], pub EncodedPointP384<NistP384>);
126
127impl ECSignature for ECDSASHA384Signature {
128    type r = [u8; 48];
129    type s = [u8; 48];
130    type sbytes = [u8; 96]; // signature bytes
131
132    fn generate_keypair(&mut self, seed: [u8; 32]) {
133        let signing_key = ECDHNISTP384::<48>::generate_private_key(seed); // reusing functionality from ECDH module
134        let verifying_key = ECDHNISTP384::<48>::generate_public_key(&signing_key);
135        self.0 = signing_key.to_bytes().as_slice().try_into().unwrap();
136        self.1 = verifying_key.0;
137    }
138
139    fn sign(&self, data: &[u8]) -> Result<Self::sbytes> {
140        let (r, s) = ECSignerType::<48>::sign(data, &self.0);
141        let r_bytes: [u8; 48] = r.to_bytes_be().1.as_slice().try_into().unwrap();
142        let s_bytes: [u8; 48] = s.to_bytes_be().1.as_slice().try_into().unwrap();
143        let mut sbytes = [0; 96];
144        let _temp: () = r_bytes
145            .iter()
146            .chain(s_bytes.iter())
147            .enumerate()
148            .map(|(i, x)| sbytes[i] = *x)
149            .collect();
150        Ok(sbytes)
151    }
152
153    fn verify(&self, data: &[u8], signature: &[u8]) -> Result<bool> {
154        let verification_status = ECSignerType::<48>::verify(data, signature, self.1);
155        verification_status
156    }
157
158    fn r(s: Self::sbytes) -> [u8; 48] {
159        let r_bytes = s.as_ref()[..48].try_into().unwrap();
160        r_bytes
161    }
162
163    fn s(s: Self::sbytes) -> [u8; 48] {
164        let s_bytes = s.as_ref()[48..].try_into().unwrap();
165        s_bytes
166    }
167}