Skip to main content

bbs/
keys.rs

1use crate::errors::prelude::*;
2use crate::{
3    hash_to_g2, GeneratorG1, GeneratorG2, HashElem, RandomElem, ToVariableLengthBytes,
4    FR_COMPRESSED_SIZE, FR_UNCOMPRESSED_SIZE, G1_COMPRESSED_SIZE, G1_UNCOMPRESSED_SIZE,
5    G2_COMPRESSED_SIZE, G2_UNCOMPRESSED_SIZE,
6};
7use blake2::{digest::generic_array::GenericArray, Blake2b};
8use ff_zeroize::Field;
9use pairing_plus::{
10    bls12_381::{Fr, G1, G2},
11    hash_to_field::BaseFromRO,
12    serdes::SerDes,
13    CurveProjective,
14};
15use rand::prelude::*;
16#[cfg(feature = "rayon")]
17use rayon::prelude::*;
18use serde::{
19    de::{Error as DError, Visitor},
20    Deserialize, Deserializer, Serialize, Serializer,
21};
22use std::io::{Cursor, Read};
23use std::{
24    convert::TryFrom,
25    fmt::{Display, Formatter},
26};
27#[cfg(feature = "wasm")]
28use wasm_bindgen::JsValue;
29use zeroize::Zeroize;
30
31/// Convenience importing module
32pub mod prelude {
33    pub use super::{
34        generate, DeterministicPublicKey, KeyGenOption, PublicKey, SecretKey,
35        DETERMINISTIC_PUBLIC_KEY_COMPRESSED_SIZE,
36    };
37}
38
39/// The various ways a key can be constructed other than random
40#[derive(Debug, Clone)]
41pub enum KeyGenOption {
42    /// The hash of these bytes will be used as the private key
43    UseSeed(Vec<u8>),
44    /// The actual secret key, used to construct the public key
45    FromSecretKey(SecretKey),
46}
47
48/// The secret key is field element 0 < `x` < `r`
49/// where `r` is the curve order. See Section 4.3 in
50/// <https://eprint.iacr.org/2016/663.pdf>
51#[derive(Clone, Debug, Eq, PartialEq)]
52pub struct SecretKey(pub(crate) Fr);
53
54impl SecretKey {
55    to_fixed_length_bytes_impl!(SecretKey, Fr, FR_COMPRESSED_SIZE, FR_COMPRESSED_SIZE);
56}
57
58default_zero_impl!(SecretKey, Fr);
59from_impl!(SecretKey, Fr, FR_COMPRESSED_SIZE);
60display_impl!(SecretKey);
61serdes_impl!(SecretKey);
62hash_elem_impl!(SecretKey, |data| { generate_secret_key(Some(data)) });
63random_elem_impl!(SecretKey, { generate_secret_key(None) });
64
65#[cfg(feature = "wasm")]
66wasm_slice_impl!(SecretKey);
67
68impl Zeroize for SecretKey {
69    fn zeroize(&mut self) {
70        self.0.zeroize();
71    }
72}
73
74impl Drop for SecretKey {
75    fn drop(&mut self) {
76        self.0.zeroize();
77    }
78}
79
80/// `PublicKey` consists of a blinding generator `h_0`,
81/// a commitment to the secret key `w`
82/// and a generator for each message in `h`
83#[derive(Clone, Debug, PartialEq, Eq)]
84pub struct PublicKey {
85    /// Blinding factor generator
86    pub h0: GeneratorG1,
87    /// Base for each message to be signed
88    pub h: Vec<GeneratorG1>,
89    /// Commitment to the private key
90    pub w: GeneratorG2,
91}
92
93impl PublicKey {
94    /// Return how many messages this public key can be used to sign
95    pub fn message_count(&self) -> usize {
96        self.h.len()
97    }
98
99    /// Convert the key to raw bytes
100    pub(crate) fn to_bytes(&self, compressed: bool) -> Vec<u8> {
101        let mut out = Vec::new();
102        self.w.0.serialize(&mut out, compressed).unwrap();
103        self.h0.0.serialize(&mut out, compressed).unwrap();
104        out.extend_from_slice(&(self.h.len() as u32).to_be_bytes());
105        for p in &self.h {
106            p.0.serialize(&mut out, compressed).unwrap();
107        }
108        out
109    }
110
111    /// Convert the byte slice into a public key
112    pub(crate) fn from_bytes(
113        data: &[u8],
114        g1_size: usize,
115        compressed: bool,
116    ) -> Result<Self, BBSError> {
117        if (data.len() - 4) % g1_size != 0 {
118            return Err(BBSErrorKind::MalformedPublicKey.into());
119        }
120        let mut c = Cursor::new(data);
121        let w = GeneratorG2(G2::deserialize(&mut c, compressed)?);
122        let h0 = GeneratorG1(G1::deserialize(&mut c, compressed)?);
123
124        let mut h_bytes = [0u8; 4];
125        c.read_exact(&mut h_bytes).unwrap();
126
127        let h_size = u32::from_be_bytes(h_bytes) as usize;
128        let mut h = Vec::with_capacity(h_size);
129        for _ in 0..h_size {
130            let p = GeneratorG1(G1::deserialize(&mut c, compressed)?);
131            h.push(p);
132        }
133        let pk = Self { w, h0, h };
134        pk.validate()?;
135        Ok(pk)
136    }
137
138    /// Make sure no generator is identity
139    pub fn validate(&self) -> Result<(), BBSError> {
140        if self.h0.0.is_zero() || self.w.0.is_zero() || self.h.iter().any(|v| v.0.is_zero()) {
141            Err(BBSError::from_kind(BBSErrorKind::MalformedPublicKey))
142        } else {
143            Ok(())
144        }
145    }
146}
147
148impl ToVariableLengthBytes for PublicKey {
149    type Output = PublicKey;
150    type Error = BBSError;
151
152    fn to_bytes_compressed_form(&self) -> Vec<u8> {
153        self.to_bytes(true)
154    }
155
156    fn from_bytes_compressed_form<I: AsRef<[u8]>>(data: I) -> Result<Self::Output, Self::Error> {
157        Self::from_bytes(data.as_ref(), G1_COMPRESSED_SIZE, true)
158    }
159
160    fn to_bytes_uncompressed_form(&self) -> Vec<u8> {
161        self.to_bytes(false)
162    }
163
164    fn from_bytes_uncompressed_form<I: AsRef<[u8]>>(data: I) -> Result<Self::Output, Self::Error> {
165        Self::from_bytes(data.as_ref(), G1_UNCOMPRESSED_SIZE, false)
166    }
167}
168
169impl Default for PublicKey {
170    fn default() -> Self {
171        Self {
172            h0: GeneratorG1::default(),
173            h: Vec::new(),
174            w: GeneratorG2::default(),
175        }
176    }
177}
178
179try_from_impl!(PublicKey, BBSError);
180display_impl!(PublicKey);
181serdes_impl!(PublicKey);
182#[cfg(feature = "wasm")]
183wasm_slice_impl!(PublicKey);
184
185/// Size of a compressed deterministic public key
186pub const DETERMINISTIC_PUBLIC_KEY_COMPRESSED_SIZE: usize = G2_COMPRESSED_SIZE;
187
188/// Used to deterministically generate all other generators given a commitment to a private key
189/// This is effectively a BLS signature public key
190#[derive(Clone, Copy, Debug, PartialEq, Eq)]
191pub struct DeterministicPublicKey(pub(crate) G2);
192
193impl DeterministicPublicKey {
194    to_fixed_length_bytes_impl!(
195        DeterministicPublicKey,
196        G2,
197        G2_COMPRESSED_SIZE,
198        G2_UNCOMPRESSED_SIZE
199    );
200}
201
202default_zero_impl!(DeterministicPublicKey, G2);
203as_ref_impl!(DeterministicPublicKey, G2);
204from_impl!(
205    DeterministicPublicKey,
206    G2,
207    G2_COMPRESSED_SIZE,
208    G2_UNCOMPRESSED_SIZE
209);
210display_impl!(DeterministicPublicKey);
211serdes_impl!(DeterministicPublicKey);
212hash_elem_impl!(DeterministicPublicKey, |data| {
213    DeterministicPublicKey(hash_to_g2(data))
214});
215
216impl DeterministicPublicKey {
217    /// Generates a random `Secretkey` and only creates the commitment to it
218    pub fn new(option: Option<KeyGenOption>) -> (Self, SecretKey) {
219        let secret = match option {
220            Some(ref o) => match o {
221                KeyGenOption::UseSeed(ref v) => generate_secret_key(Some(v)),
222                KeyGenOption::FromSecretKey(ref sk) => sk.clone(),
223            },
224            None => generate_secret_key(None),
225        };
226        let mut w = G2::one();
227        w.mul_assign(secret.0.clone());
228        (Self(w), secret)
229    }
230
231    /// Convert to a normal public key but deterministically derive all the generators
232    /// using the hash to curve algorithm BLS12381G1_XMD:SHA-256_SSWU_RO denoted as H2C
233    /// h_0 <- H2C(w || I2OSP(0, 4) || I2OSP(0, 1) || I2OSP(message_count, 4))
234    /// h_i <- H2C(w || I2OSP(i, 4) || I2OSP(0, 1) || I2OSP(message_count, 4))
235    pub fn to_public_key(&self, message_count: usize) -> Result<PublicKey, BBSError> {
236        if message_count == 0 {
237            return Err(BBSErrorKind::KeyGenError.into());
238        }
239        let mc_bytes = (message_count as u32).to_be_bytes();
240        let mut data = Vec::with_capacity(9 + G2_UNCOMPRESSED_SIZE);
241        self.0.serialize(&mut data, false)?;
242        // Spacer
243        data.push(0u8);
244        let offset = data.len();
245        // i
246        data.push(0u8);
247        data.push(0u8);
248        data.push(0u8);
249        data.push(0u8);
250        let end = data.len();
251        // Spacer
252        data.push(0u8);
253        // message_count
254        data.extend_from_slice(&mc_bytes[..]);
255
256        let gen_count: Vec<usize> = (0..=message_count).collect();
257
258        #[cfg(feature = "rayon")]
259        let temp_iter = gen_count.par_iter();
260        #[cfg(not(feature = "rayon"))]
261        let temp_iter = gen_count.iter();
262
263        let h = temp_iter
264            .map(|i| {
265                let mut temp = data.clone();
266                let ii = *i as u32;
267                temp[offset..end].copy_from_slice(&(ii.to_be_bytes())[..]);
268                GeneratorG1::hash(temp)
269            })
270            .collect::<Vec<GeneratorG1>>();
271
272        Ok(PublicKey {
273            w: GeneratorG2(self.0),
274            h0: h[0],
275            h: h[1..].to_vec(),
276        })
277    }
278}
279
280#[cfg(feature = "wasm")]
281wasm_slice_impl!(DeterministicPublicKey);
282
283/// Create a new BBS+ keypair. The generators of the public key are generated at random
284pub fn generate(message_count: usize) -> Result<(PublicKey, SecretKey), BBSError> {
285    if message_count == 0 {
286        return Err(BBSError::from_kind(BBSErrorKind::KeyGenError));
287    }
288    let secret = generate_secret_key(None);
289
290    let mut w = G2::one();
291    w.mul_assign(secret.0.clone());
292    let gen_count: Vec<usize> = (0..=message_count).collect();
293
294    #[cfg(feature = "rayon")]
295    let temp_iter = gen_count.par_iter();
296    #[cfg(not(feature = "rayon"))]
297    let temp_iter = gen_count.iter();
298
299    let h = temp_iter
300        .map(|_| {
301            let mut rng = thread_rng();
302            let mut seed = [0u8; 32];
303            rng.fill_bytes(&mut seed);
304            GeneratorG1::hash(seed)
305        })
306        .collect::<Vec<GeneratorG1>>();
307    Ok((
308        PublicKey {
309            w: GeneratorG2(w),
310            h0: h[0],
311            h: h[1..].to_vec(),
312        },
313        secret,
314    ))
315}
316
317/// Similar to https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-02#section-2.3
318/// info is left blank
319fn generate_secret_key(ikm: Option<&[u8]>) -> SecretKey {
320    let salt = b"BBS-SIG-KEYGEN-SALT-";
321    let info = [0u8, FR_UNCOMPRESSED_SIZE as u8]; // I2OSP(L, 2)
322    let ikm = match ikm {
323        Some(v) => {
324            let mut t = vec![0u8; v.len() + 1];
325            t[..v.len()].copy_from_slice(v);
326            t
327        }
328        None => {
329            let mut bytes = vec![0u8; FR_COMPRESSED_SIZE + 1];
330            thread_rng().fill_bytes(bytes.as_mut_slice());
331            bytes[FR_COMPRESSED_SIZE] = 0;
332            bytes
333        }
334    };
335    let mut okm = [0u8; FR_UNCOMPRESSED_SIZE];
336    let h = hkdf::Hkdf::<Blake2b>::new(Some(&salt[..]), &ikm);
337    h.expand(&info[..], &mut okm).unwrap();
338    SecretKey(Fr::from_okm(GenericArray::from_slice(&okm[..])))
339}
340
341#[cfg(test)]
342mod tests {
343    use super::*;
344
345    #[test]
346    fn key_generate() {
347        let res = generate(0);
348        assert!(res.is_err());
349        //Check to make sure key has correct size
350        let (public_key, _) = generate(1).unwrap();
351        let bytes = public_key.to_bytes_uncompressed_form();
352        assert_eq!(
353            bytes.len(),
354            G1_UNCOMPRESSED_SIZE * 2 + 4 + G2_UNCOMPRESSED_SIZE
355        );
356
357        let (public_key, _) = generate(5).unwrap();
358        assert_eq!(public_key.message_count(), 5);
359        //Check key doesn't contain any invalid points
360        assert!(public_key.validate().is_ok());
361        let bytes = public_key.to_bytes_uncompressed_form();
362        assert_eq!(
363            bytes.len(),
364            G1_UNCOMPRESSED_SIZE * 6 + 4 + G2_UNCOMPRESSED_SIZE
365        );
366        //Check serialization is working
367        let public_key_2 = PublicKey::from_bytes_uncompressed_form(bytes.as_slice()).unwrap();
368        assert_eq!(public_key_2, public_key);
369
370        let bytes = public_key.to_bytes_compressed_form();
371        assert_eq!(bytes.len(), G1_COMPRESSED_SIZE * 6 + 4 + G2_COMPRESSED_SIZE);
372        let public_key_3 = PublicKey::from_bytes_compressed_form(bytes.as_slice());
373        assert!(public_key_3.is_ok());
374        assert_eq!(public_key_3.unwrap(), public_key);
375    }
376
377    #[test]
378    fn key_conversion() {
379        let (dpk, _) = DeterministicPublicKey::new(None);
380        let res = dpk.to_public_key(5);
381
382        assert!(res.is_ok());
383
384        let pk = res.unwrap();
385        assert_eq!(pk.message_count(), 5);
386
387        for i in 0..pk.h.len() {
388            assert_ne!(pk.h0, pk.h[i], "h[0] == h[{}]", i + 1);
389
390            for j in (i + 1)..pk.h.len() {
391                assert_ne!(pk.h[i], pk.h[j], "h[{}] == h[{}]", i + 1, j + 1);
392            }
393        }
394
395        let res = dpk.to_public_key(0);
396
397        assert!(res.is_err());
398    }
399
400    #[test]
401    fn key_from_seed() {
402        let seed = vec![0u8; 32];
403        let (dpk, sk) = DeterministicPublicKey::new(Some(KeyGenOption::UseSeed(seed)));
404
405        assert_eq!("a171467362a8fbbc444889efc39e53a5e683ec85fbed19aa1fd89edb5cdb9751871b4db568d8476892f0b6444ca854b50a1c354388c17055a6b8a9d8d5a647b25d41055ce73fb57e158394aea51a9c824b726f258f3e97a90723cc753a459eec", hex::encode(&dpk.to_bytes_compressed_form()[..]));
406        assert_eq!(
407            "0eb25c421350947e8c99faeaee643d64f9e01c568467e5de41050cc4190e8db8",
408            hex::encode(&sk.to_bytes_compressed_form()[..])
409        );
410
411        let seed = vec![1u8; 24];
412        let (dpk, sk) = DeterministicPublicKey::new(Some(KeyGenOption::UseSeed(seed)));
413
414        assert_eq!("8dae8c4d40a8ec909e0d5c8541fc0edcfd46d302078edd246ea626853d5376d0a789481abd39ddba5e5145b950a580781802f6c7e70b24f492a1bd4d8edd596e0413fb88c9664bcca65e77460b8cf46680b4f689f28a2731f39891cdb96229c4", hex::encode(&dpk.to_bytes_compressed_form()[..]));
415        assert_eq!(
416            "3ac2bb3f5bfe0db27d5da9842ddb750326f7094d7aeeed78d474862f233f2948",
417            hex::encode(&sk.to_bytes_compressed_form()[..])
418        );
419    }
420
421    #[test]
422    fn key_compression() {
423        let (pk, sk) = generate(3).unwrap();
424
425        assert_eq!(292, pk.to_bytes_compressed_form().len());
426        assert_eq!(FR_COMPRESSED_SIZE, sk.to_bytes_compressed_form().len());
427
428        let (dpk, sk) = DeterministicPublicKey::new(Some(KeyGenOption::FromSecretKey(sk)));
429        assert_eq!(96, dpk.to_bytes_compressed_form().len());
430
431        let res = PublicKey::from_bytes_compressed_form(pk.to_bytes_compressed_form());
432        assert!(res.is_ok());
433
434        assert!(res.unwrap().to_bytes_compressed_form() == pk.to_bytes_compressed_form());
435
436        let dpk1 = DeterministicPublicKey::from(dpk.to_bytes_compressed_form());
437        assert!(&dpk1.to_bytes_compressed_form()[..] == &dpk.to_bytes_compressed_form()[..]);
438
439        let sk1 = SecretKey::from(sk.to_bytes_compressed_form());
440        assert!(&sk1.to_bytes_compressed_form()[..] == &sk.to_bytes_compressed_form()[..]);
441    }
442}