Skip to main content

aries_bbssignatures/
keys.rs

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