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 fn write_bytes(&self, dest: &mut impl io::Write) -> io::Result<()>;
70
71 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 pub fn new<T: AsRef<[u8]>>(msg: T) -> Self {
86 PrivateKey(key_gen(msg))
87 }
88
89 pub fn generate<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
91 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 #[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 #[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 #[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 #[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 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 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#[cfg(feature = "pairing")]
223fn key_gen<T: AsRef<[u8]>>(data: T) -> Scalar {
224 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 let mut msg = data.as_ref().to_vec();
232 msg.push(0);
234 let prk = Hkdf::<Sha256>::new(Some(SALT), &msg);
235
236 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#[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 assert!(PrivateKey::from_bytes(&[255u8; 32]).is_err());
331
332 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 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 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 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 assert!(PublicKey::from_bytes(&[255u8; 48]).is_err());
362 }
363}