Skip to main content

zlicenser_protocol/crypto/
signature.rs

1use ed25519_dalek::{Signer, Verifier};
2use rand::rngs::OsRng;
3use rand::RngCore;
4use subtle::ConstantTimeEq;
5use zeroize::{Zeroize, ZeroizeOnDrop};
6
7use crate::error::Error;
8
9// raw seed bytes so we can derive Zeroize, dalek's SigningKey doesn't impl it
10#[derive(Zeroize, ZeroizeOnDrop)]
11pub struct SigningKey([u8; 32]);
12
13impl SigningKey {
14    pub fn generate() -> Self {
15        let mut b = [0u8; 32];
16        OsRng.fill_bytes(&mut b);
17        Self(b)
18    }
19
20    pub fn from_bytes(b: &[u8; 32]) -> Self {
21        Self(*b)
22    }
23
24    pub fn to_bytes(&self) -> [u8; 32] {
25        self.0
26    }
27
28    pub fn verifying_key(&self) -> VerifyingKey {
29        VerifyingKey(ed25519_dalek::SigningKey::from_bytes(&self.0).verifying_key())
30    }
31
32    pub fn sign(&self, msg: &[u8]) -> Signature {
33        Signature(ed25519_dalek::SigningKey::from_bytes(&self.0).sign(msg))
34    }
35}
36
37impl PartialEq for SigningKey {
38    fn eq(&self, other: &Self) -> bool {
39        self.0.ct_eq(&other.0).into()
40    }
41}
42
43#[derive(Debug, Clone)]
44pub struct VerifyingKey(ed25519_dalek::VerifyingKey);
45
46impl VerifyingKey {
47    pub fn from_bytes(b: &[u8; 32]) -> Result<Self, Error> {
48        ed25519_dalek::VerifyingKey::from_bytes(b)
49            .map(Self)
50            .map_err(|_| Error::Malformed("invalid Ed25519 verifying key"))
51    }
52
53    pub fn to_bytes(&self) -> [u8; 32] {
54        self.0.to_bytes()
55    }
56
57    pub fn verify(&self, msg: &[u8], sig: &Signature) -> Result<(), Error> {
58        self.0
59            .verify(msg, &sig.0)
60            .map_err(|_| Error::SignatureInvalid)
61    }
62}
63
64impl PartialEq for VerifyingKey {
65    fn eq(&self, other: &Self) -> bool {
66        self.0.as_bytes().ct_eq(other.0.as_bytes()).into()
67    }
68}
69
70impl Eq for VerifyingKey {}
71
72#[derive(Debug, Clone)]
73pub struct Signature(ed25519_dalek::Signature);
74
75impl Signature {
76    pub fn from_bytes(b: &[u8; 64]) -> Self {
77        Self(ed25519_dalek::Signature::from_bytes(b))
78    }
79
80    pub fn to_bytes(&self) -> [u8; 64] {
81        self.0.to_bytes()
82    }
83}
84
85impl PartialEq for Signature {
86    fn eq(&self, other: &Self) -> bool {
87        self.0.to_bytes().ct_eq(&other.0.to_bytes()).into()
88    }
89}
90
91impl Eq for Signature {}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96
97    // RFC 8032 chapter 6.1 Test Vector 1, Ed25519 with empty message
98    #[test]
99    fn rfc8032_test_vector_1() {
100        let private_bytes: [u8; 32] = [
101            0x9d, 0x61, 0xb1, 0x9d, 0xef, 0xfd, 0x5a, 0x60, 0xba, 0x84, 0x4a, 0xf4, 0x92, 0xec,
102            0x2c, 0xc4, 0x44, 0x49, 0xc5, 0x69, 0x7b, 0x32, 0x69, 0x19, 0x70, 0x3b, 0xac, 0x03,
103            0x1c, 0xae, 0x7f, 0x60,
104        ];
105        let expected_pub: [u8; 32] = [
106            0xd7, 0x5a, 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7, 0xd5, 0x4b, 0xfe, 0xd3, 0xc9, 0x64,
107            0x07, 0x3a, 0x0e, 0xe1, 0x72, 0xf3, 0xda, 0xa6, 0x23, 0x25, 0xaf, 0x02, 0x1a, 0x68,
108            0xf7, 0x07, 0x51, 0x1a,
109        ];
110        let expected_sig: [u8; 64] = [
111            0xe5, 0x56, 0x43, 0x00, 0xc3, 0x60, 0xac, 0x72, 0x90, 0x86, 0xe2, 0xcc, 0x80, 0x6e,
112            0x82, 0x8a, 0x84, 0x87, 0x7f, 0x1e, 0xb8, 0xe5, 0xd9, 0x74, 0xd8, 0x73, 0xe0, 0x65,
113            0x22, 0x49, 0x01, 0x55, 0x5f, 0xb8, 0x82, 0x15, 0x90, 0xa3, 0x3b, 0xac, 0xc6, 0x1e,
114            0x39, 0x70, 0x1c, 0xf9, 0xb4, 0x6b, 0xd2, 0x5b, 0xf5, 0xf0, 0x59, 0x5b, 0xbe, 0x24,
115            0x65, 0x51, 0x41, 0x43, 0x8e, 0x7a, 0x10, 0x0b,
116        ];
117
118        let sk = SigningKey::from_bytes(&private_bytes);
119        assert_eq!(sk.verifying_key().to_bytes(), expected_pub);
120        let sig = sk.sign(b"");
121        assert_eq!(sig.to_bytes(), expected_sig);
122        sk.verifying_key().verify(b"", &sig).unwrap();
123    }
124
125    #[test]
126    fn bit_flipped_signature_fails() {
127        let sk = SigningKey::generate();
128        let vk = sk.verifying_key();
129        let mut sig_bytes = sk.sign(b"message").to_bytes();
130        sig_bytes[0] ^= 0x01;
131        let bad_sig = Signature::from_bytes(&sig_bytes);
132        assert!(matches!(
133            vk.verify(b"message", &bad_sig),
134            Err(Error::SignatureInvalid)
135        ));
136    }
137
138    #[test]
139    fn sign_verify_roundtrip() {
140        let sk = SigningKey::generate();
141        let msg = b"roundtrip test";
142        let sig = sk.sign(msg);
143        sk.verifying_key().verify(msg, &sig).unwrap();
144    }
145}