bls_signatures/
key.rs

1use std::io;
2
3use ff::{PrimeField, PrimeFieldBits};
4use group::Curve;
5use rand_core::{CryptoRng, RngCore};
6
7#[cfg(feature = "pairing")]
8use bls12_381::{hash_to_curve::HashToField, G1Affine, G1Projective, Scalar};
9#[cfg(feature = "pairing")]
10use hkdf::Hkdf;
11#[cfg(feature = "pairing")]
12use sha2::{digest::generic_array::typenum::U48, digest::generic_array::GenericArray, Sha256};
13
14#[cfg(feature = "blst")]
15use blstrs::{G1Affine, G1Projective, G2Affine, Scalar};
16#[cfg(feature = "blst")]
17use group::prime::PrimeCurveAffine;
18
19pub(crate) struct ScalarRepr(<Scalar as PrimeFieldBits>::ReprBits);
20
21use crate::error::Error;
22use crate::signature::*;
23
24pub(crate) const G1_COMPRESSED_SIZE: usize = 48;
25
26#[derive(Debug, Copy, Clone, Eq, PartialEq)]
27pub struct PublicKey(pub(crate) G1Projective);
28
29#[derive(Debug, Copy, Clone, Eq, PartialEq)]
30pub struct PrivateKey(pub(crate) Scalar);
31
32impl From<G1Projective> for PublicKey {
33    fn from(val: G1Projective) -> Self {
34        PublicKey(val)
35    }
36}
37impl From<PublicKey> for G1Projective {
38    fn from(val: PublicKey) -> Self {
39        val.0
40    }
41}
42
43impl From<Scalar> for PrivateKey {
44    fn from(val: Scalar) -> Self {
45        PrivateKey(val)
46    }
47}
48
49impl From<PrivateKey> for Scalar {
50    fn from(val: PrivateKey) -> Self {
51        val.0
52    }
53}
54
55impl From<PrivateKey> for ScalarRepr {
56    fn from(val: PrivateKey) -> Self {
57        ScalarRepr(val.0.to_le_bits().into_inner())
58    }
59}
60
61impl<'a> From<&'a PrivateKey> for ScalarRepr {
62    fn from(val: &'a PrivateKey) -> Self {
63        (*val).into()
64    }
65}
66
67pub trait Serialize: ::std::fmt::Debug + Sized {
68    /// Writes the key to the given writer.
69    fn write_bytes(&self, dest: &mut impl io::Write) -> io::Result<()>;
70
71    /// Recreate the key from bytes in the same form as `write_bytes` produced.
72    fn from_bytes(raw: &[u8]) -> Result<Self, Error>;
73
74    fn as_bytes(&self) -> Vec<u8> {
75        let mut res = Vec::with_capacity(8 * 4);
76        self.write_bytes(&mut res).expect("preallocated");
77        res
78    }
79}
80
81impl PrivateKey {
82    /// Generate a deterministic private key from the given bytes.
83    ///
84    /// They must be at least 32 bytes long to be secure, will panic otherwise.
85    pub fn new<T: AsRef<[u8]>>(msg: T) -> Self {
86        PrivateKey(key_gen(msg))
87    }
88
89    /// Generate a new private key.
90    pub fn generate<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
91        // IKM must be at least 32 bytes long:
92        // https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-00#section-2.3
93        let mut ikm = [0u8; 32];
94        rng.try_fill_bytes(&mut ikm)
95            .expect("unable to produce secure randomness");
96
97        Self::new(ikm)
98    }
99
100    /// Sign the given message.
101    /// Calculated by `signature = hash_into_g2(message) * sk`
102    #[cfg(feature = "pairing")]
103    pub fn sign<T: AsRef<[u8]>>(&self, message: T) -> Signature {
104        let mut p = hash(message.as_ref());
105        p *= self.0;
106
107        p.into()
108    }
109
110    /// Sign the given message.
111    /// Calculated by `signature = hash_into_g2(message) * sk`
112    #[cfg(feature = "blst")]
113    pub fn sign<T: AsRef<[u8]>>(&self, message: T) -> Signature {
114        let p = hash(message.as_ref());
115        let mut sig = G2Affine::identity();
116
117        unsafe {
118            blst_lib::blst_sign_pk2_in_g1(
119                std::ptr::null_mut(),
120                sig.as_mut(),
121                p.as_ref(),
122                &self.0.into(),
123            );
124        }
125
126        sig.into()
127    }
128
129    /// Get the public key for this private key.
130    /// Calculated by `pk = g1 * sk`.
131    #[cfg(feature = "pairing")]
132    pub fn public_key(&self) -> PublicKey {
133        let mut pk = G1Projective::generator();
134        pk *= self.0;
135
136        PublicKey(pk)
137    }
138
139    /// Get the public key for this private key.
140    /// Calculated by `pk = g1 * sk`.
141    #[cfg(feature = "blst")]
142    pub fn public_key(&self) -> PublicKey {
143        let mut pk = G1Affine::identity();
144
145        unsafe {
146            blst_lib::blst_sk_to_pk2_in_g1(std::ptr::null_mut(), pk.as_mut(), &self.0.into());
147        }
148
149        PublicKey(pk.into())
150    }
151
152    /// Deserializes a private key from the field element as a decimal number.
153    pub fn from_string<T: AsRef<str>>(s: T) -> Result<Self, Error> {
154        match Scalar::from_str_vartime(s.as_ref()) {
155            Some(f) => Ok(f.into()),
156            None => Err(Error::InvalidPrivateKey),
157        }
158    }
159}
160
161impl Serialize for PrivateKey {
162    fn write_bytes(&self, dest: &mut impl io::Write) -> io::Result<()> {
163        for digit in &self.0.to_le_bits().data {
164            dest.write_all(&digit.to_le_bytes())?;
165        }
166
167        Ok(())
168    }
169
170    fn from_bytes(raw: &[u8]) -> Result<Self, Error> {
171        const FR_SIZE: usize = (Scalar::NUM_BITS as usize + 8 - 1) / 8;
172        if raw.len() != FR_SIZE {
173            return Err(Error::SizeMismatch);
174        }
175
176        let mut res = [0u8; FR_SIZE];
177        res.copy_from_slice(&raw[..FR_SIZE]);
178
179        // TODO: once zero keys are rejected, insert check for zero.
180
181        Scalar::from_repr_vartime(res)
182            .map(Into::into)
183            .ok_or(Error::InvalidPrivateKey)
184    }
185}
186
187impl PublicKey {
188    pub fn as_affine(&self) -> G1Affine {
189        self.0.to_affine()
190    }
191
192    pub fn verify<T: AsRef<[u8]>>(&self, sig: Signature, message: T) -> bool {
193        verify_messages(&sig, &[message.as_ref()], &[*self])
194    }
195}
196
197impl Serialize for PublicKey {
198    fn write_bytes(&self, dest: &mut impl io::Write) -> io::Result<()> {
199        let t = self.0.to_affine();
200        let tmp = t.to_compressed();
201        dest.write_all(tmp.as_ref())?;
202
203        Ok(())
204    }
205
206    fn from_bytes(raw: &[u8]) -> Result<Self, Error> {
207        if raw.len() != G1_COMPRESSED_SIZE {
208            return Err(Error::SizeMismatch);
209        }
210
211        let mut res = [0u8; G1_COMPRESSED_SIZE];
212        res.as_mut().copy_from_slice(raw);
213        let affine: G1Affine =
214            Option::from(G1Affine::from_compressed(&res)).ok_or(Error::GroupDecode)?;
215
216        Ok(PublicKey(affine.into()))
217    }
218}
219
220/// Generates a secret key as defined in
221/// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-02#section-2.3
222#[cfg(feature = "pairing")]
223fn key_gen<T: AsRef<[u8]>>(data: T) -> Scalar {
224    // "BLS-SIG-KEYGEN-SALT-"
225    const SALT: &[u8] = b"BLS-SIG-KEYGEN-SALT-";
226
227    let data = data.as_ref();
228    assert!(data.len() >= 32, "IKM must be at least 32 bytes");
229
230    // HKDF-Extract
231    let mut msg = data.as_ref().to_vec();
232    // append zero byte
233    msg.push(0);
234    let prk = Hkdf::<Sha256>::new(Some(SALT), &msg);
235
236    // HKDF-Expand
237    // `result` has enough length to hold the output from HKDF expansion
238    let mut result = GenericArray::<u8, U48>::default();
239    assert!(prk.expand(&[0, 48], &mut result).is_ok());
240
241    Scalar::from_okm(&result)
242}
243
244/// Generates a secret key as defined in
245/// https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-02#section-2.3
246#[cfg(feature = "blst")]
247fn key_gen<T: AsRef<[u8]>>(data: T) -> Scalar {
248    use std::convert::TryInto;
249
250    let data = data.as_ref();
251    assert!(data.len() >= 32, "IKM must be at least 32 bytes");
252
253    let key_info = &[];
254    let mut out = blst_lib::blst_scalar::default();
255    unsafe {
256        blst_lib::blst_keygen(
257            &mut out,
258            data.as_ptr(),
259            data.len(),
260            key_info.as_ptr(),
261            key_info.len(),
262        )
263    };
264
265    out.try_into().expect("invalid key generated")
266}
267
268#[cfg(test)]
269mod tests {
270    use super::*;
271
272    use rand::SeedableRng;
273    use rand_chacha::ChaCha8Rng;
274
275    #[test]
276    fn test_bytes_roundtrip() {
277        let rng = &mut ChaCha8Rng::seed_from_u64(12);
278        let sk = PrivateKey::generate(rng);
279        let sk_bytes = sk.as_bytes();
280
281        assert_eq!(sk_bytes.len(), 32);
282        assert_eq!(PrivateKey::from_bytes(&sk_bytes).unwrap(), sk);
283
284        let pk = sk.public_key();
285        let pk_bytes = pk.as_bytes();
286
287        assert_eq!(pk_bytes.len(), 48);
288        assert_eq!(PublicKey::from_bytes(&pk_bytes).unwrap(), pk);
289    }
290
291    #[test]
292    fn test_key_gen() {
293        let key_material = "hello world (it's a secret!) very secret stuff";
294        let fr_val = key_gen(key_material);
295        #[cfg(feature = "blst")]
296        let expect = Scalar::from_u64s_le(&[
297            0x8a223b0f9e257f7d,
298            0x2d80f7b7f5ea6cc4,
299            0xcc9e063a0ea0009c,
300            0x4a73baed5cb75109,
301        ])
302        .unwrap();
303
304        #[cfg(feature = "pairing")]
305        let expect = Scalar::from_raw([
306            0xa9f8187b89e6d49a,
307            0xf870f34063ce4b16,
308            0xc2aa3c1fff1bbaa3,
309            0x60417787ee46e23f,
310        ]);
311
312        assert_eq!(fr_val, expect);
313    }
314
315    #[test]
316    fn test_sig() {
317        let msg = "this is the message";
318        let sk = "this is the key and it is very secret";
319
320        let sk = PrivateKey::new(sk);
321        let sig = sk.sign(msg);
322        let pk = sk.public_key();
323
324        assert!(pk.verify(sig, msg));
325    }
326
327    #[test]
328    fn test_from_bytes() {
329        // Larger than the modulus
330        assert!(PrivateKey::from_bytes(&[255u8; 32]).is_err());
331
332        // Scalar field modulus' bigint (i.e. non-Montgomery form) little-endian bytes.
333        let modulus_repr: [u8; 32] = [
334            0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x5b, 0xfe, 0xff, 0x02, 0xa4,
335            0xbd, 0x53, 0x05, 0xd8, 0xa1, 0x09, 0x08, 0xd8, 0x39, 0x33, 0x48, 0x7d, 0x9d, 0x29,
336            0x53, 0xa7, 0xed, 0x73,
337        ];
338
339        // Largest field element.
340        let neg1_repr: [u8; 32] = {
341            let mut repr = modulus_repr;
342            repr[0] -= 1;
343            repr
344        };
345        assert!(PrivateKey::from_bytes(&neg1_repr).is_ok());
346
347        // Smallest integer greater than the modulus.
348        let modulus_plus_1_repr = {
349            let mut repr = modulus_repr;
350            repr[0] += 1;
351            repr
352        };
353        assert!(PrivateKey::from_bytes(&modulus_plus_1_repr).is_err());
354
355        // simple numbers below the modulus
356        assert!(PrivateKey::from_bytes(&Scalar::from(1).to_repr()).is_ok());
357        assert!(PrivateKey::from_bytes(&Scalar::from(10).to_repr()).is_ok());
358        assert!(PrivateKey::from_bytes(&Scalar::from(100).to_repr()).is_ok());
359
360        // Larger than the modulus
361        assert!(PublicKey::from_bytes(&[255u8; 48]).is_err());
362    }
363}