1#![warn(unused_crate_dependencies)]
2#![cfg_attr(not(feature = "std"), no_std)]
3extern crate alloc;
4
5#[cfg(test)]
6use hex_literal as _;
7
8#[cfg(test)]
9use json as _;
10
11#[cfg(test)]
12use proptest as _;
13
14#[cfg(test)]
15use rand_core as _;
16
17#[cfg(test)]
18use assert_matches as _;
19
20use ark_bn254::{Bn254, Fq, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
21use ark_ec::{
22 pairing::{Pairing, PairingOutput},
23 AffineRepr, CurveGroup,
24};
25use ark_ff::{BigInteger256, Field, PrimeField, Zero};
26use ark_serialize::CanonicalSerialize;
27use ark_std::One;
28use consts::{BLS_SIG_KEYGEN_SALT, BN254_CURVE_ORDER};
29use errors::BLSError;
30use hkdf::Hkdf;
31use num_bigint::BigUint;
32use sha2::{Digest, Sha256};
33
34pub mod consts;
35pub mod errors;
36pub mod keystores;
37pub mod mnemonics;
38pub mod utils;
39
40pub const CHINESE_SIMPLIFIED_WORD_LIST: &str = include_str!("word_lists/chinese_simplified.txt");
41pub const CHINESE_TRADITIONAL_WORD_LIST: &str = include_str!("word_lists/chinese_traditional.txt");
42pub const CZECH_WORD_LIST: &str = include_str!("word_lists/czech.txt");
43pub const ENGLISH_WORD_LIST: &str = include_str!("word_lists/english.txt");
44pub const ITALIAN_WORD_LIST: &str = include_str!("word_lists/italian.txt");
45pub const KOREAN_WORD_LIST: &str = include_str!("word_lists/korean.txt");
46pub const PORTUGUESE_WORD_LIST: &str = include_str!("word_lists/portuguese.txt");
47pub const SPANISH_WORD_LIST: &str = include_str!("word_lists/spanish.txt");
48
49pub fn pairing(u: G2Affine, v: G1Affine) -> PairingOutput<Bn254> {
50 Bn254::pairing(v, u)
51}
52
53fn xmd_hash_function(input: &[u8]) -> Vec<u8> {
54 let mut hasher = Sha256::new();
55 hasher.update(input);
56 hasher.finalize().to_vec()
57}
58
59fn i2osp(x: usize, x_len: usize) -> Vec<u8> {
60 let mut result = vec![0u8; x_len];
61 let mut x = x;
62 for i in (0..x_len).rev() {
63 result[i] = (x & 0xff) as u8;
64 x >>= 8;
65 }
66 result
67}
68
69fn os2ip(bytes: &[u8]) -> BigUint {
70 BigUint::from_bytes_be(bytes)
71}
72
73pub fn key_gen(ikm: &[u8], key_info: &[u8]) -> BigUint {
74 let curve_order = BigUint::parse_bytes(BN254_CURVE_ORDER.as_bytes(), 10).unwrap();
75 let mut salt = BLS_SIG_KEYGEN_SALT.to_vec();
76 let mut sk = BigUint::zero();
77
78 while sk.is_zero() {
79 salt = xmd_hash_function(&salt);
80 let mut temp_idk = ikm.to_vec();
81 temp_idk.extend_from_slice(&[0u8]);
82 let hkdf = Hkdf::<Sha256>::new(Some(&salt), &temp_idk);
83 let mut okm = vec![0u8; (1.5 * ((curve_order.bits() as f64) / 8.0)).ceil() as usize];
84 let mut temp_key_info = key_info.to_vec();
85 temp_key_info.extend_from_slice(&i2osp(okm.len(), 2));
86 hkdf.expand(&temp_key_info, &mut okm).unwrap();
87 sk = os2ip(&okm) % &curve_order;
88 }
89 sk
90}
91
92pub fn sk_to_pk_g2(sk: &[u8]) -> Vec<u8> {
93 let _sk = Fr::from_be_bytes_mod_order(sk);
94 let mut compressed_bytes = Vec::new();
95 let pk = G2Projective::from(G2Affine::generator()) * _sk;
96 pk.serialize_uncompressed(&mut compressed_bytes).unwrap();
97 compressed_bytes
98}
99
100pub fn sk_to_pk_g1(sk: &[u8]) -> Vec<u8> {
101 let _sk = Fr::from_be_bytes_mod_order(sk);
102 let mut compressed_bytes = Vec::new();
103 let pk = G1Projective::from(G1Affine::generator()) * _sk;
104 pk.serialize_uncompressed(&mut compressed_bytes).unwrap();
105 compressed_bytes
106}
107
108fn hash_to_curve(digest: &[u8]) -> G1Affine {
109 let one = Fq::one();
110 let three = Fq::from(3u64);
111
112 let mut hasher = Sha256::new();
113 hasher.update(digest);
114 let hashed_result = hasher.finalize();
115
116 let mut x = {
118 let big_int = BigUint::from_bytes_be(&hashed_result);
119 let mut bytes = [0u8; 32];
120 big_int
121 .to_bytes_be()
122 .iter()
123 .rev()
124 .enumerate()
125 .for_each(|(i, &b)| bytes[i] = b);
126 Fq::from_le_bytes_mod_order(&bytes)
127 };
128
129 loop {
130 let mut y = x;
132 y.square_in_place();
133 y *= x;
134 y += three;
135
136 if let Some(y) = y.sqrt() {
138 return G1Projective::new(x, y, Fq::one()).into_affine();
139 } else {
140 x += one;
142 }
143 }
144}
145
146pub fn sign(sk: Fr, message: &[u8]) -> Result<G1Affine, BLSError> {
147 let q = hash_to_curve(message);
148
149 let sk_int: BigInteger256 = sk.into();
150 let r = q.mul_bigint(sk_int);
151
152 if !r.into_affine().is_on_curve() || !r.into_affine().is_in_correct_subgroup_assuming_on_curve()
153 {
154 return Err(BLSError::SignatureNotInSubgroup);
155 }
156
157 Ok(r.into_affine())
158}
159
160pub fn verify(public_key: G2Affine, message: &[u8], signature: G1Affine) -> bool {
161 if !signature.is_in_correct_subgroup_assuming_on_curve() || !signature.is_on_curve() {
162 return false;
163 }
164
165 let q = hash_to_curve(message);
166 let c1 = pairing(public_key, q);
167 let c2 = pairing(G2Affine::generator(), signature);
168 c1 == c2
169}
170
171pub fn aggregate_signatures(signatures: &[G1Affine]) -> Result<G1Affine, BLSError> {
172 if signatures.is_empty() {
173 return Err(BLSError::SignatureListEmpty);
174 }
175
176 let signatures_in_projective: Vec<G1Projective> = signatures
177 .iter()
178 .map(|sig| {
179 let proj = G1Projective::from(*sig);
180 if !sig.is_on_curve() || !sig.is_in_correct_subgroup_assuming_on_curve() {
181 return Err(BLSError::SignatureNotInSubgroup);
182 }
183 Ok(proj)
184 })
185 .collect::<Result<Vec<_>, _>>()?;
186
187 let mut aggregated = signatures_in_projective[0];
188 for sig in &signatures[1..] {
189 aggregated += sig;
190 }
191 Ok(aggregated.into_affine())
192}
193
194pub fn aggregate_public_keys(public_keys: &[G2Affine]) -> Result<G2Affine, BLSError> {
195 if public_keys.is_empty() {
196 return Err(BLSError::PublicKeyListEmpty);
197 }
198
199 let public_keys_in_projective: Vec<G2Projective> = public_keys
200 .iter()
201 .map(|pk| {
202 let proj = G2Projective::from(*pk);
203 if !pk.is_on_curve() || !pk.is_in_correct_subgroup_assuming_on_curve() {
204 return Err(BLSError::PublicKeyNotInSubgroup);
205 }
206 Ok(proj)
207 })
208 .collect::<Result<Vec<_>, _>>()?;
209
210 let mut aggregated = public_keys_in_projective[0];
211 for pk in &public_keys_in_projective[1..] {
212 aggregated += *pk;
213 }
214
215 Ok(aggregated.into_affine())
216}
217
218#[cfg(test)]
219mod test {
220 use super::*;
221use ark_ec::AdditiveGroup;
222 use ark_bn254::G2Projective;
223 use ark_ff::UniformRand;
224 use ark_std::{ops::Mul, test_rng};
225
226 #[test]
227 fn test_aggregate_and_verify() {
228 let mut rng = test_rng();
229
230 let private_keys: Vec<Fr> = (0..500).map(|_| Fr::rand(&mut rng)).collect();
232 let public_keys: Vec<G2Affine> = private_keys
233 .iter()
234 .map(|sk| (G2Affine::generator() * sk).into_affine())
235 .collect();
236
237 let message = b"Test message";
238
239 let signatures: Vec<G1Affine> = private_keys
241 .iter()
242 .map(|sk| sign(*sk, message).unwrap())
243 .collect();
244
245 let aggregated_signature = aggregate_signatures(&signatures).unwrap();
247 let aggregated_public_key = aggregate_public_keys(&public_keys).unwrap();
248
249 let is_valid = verify(aggregated_public_key, message, aggregated_signature);
251 assert!(is_valid, "Aggregated signature verification failed");
252 }
253
254 #[test]
255 fn test_generic() {
256 let mut rng = ark_std::test_rng();
257 let sk = Fr::rand(&mut rng);
258 let pubkey = G2Projective::from(G2Affine::generator())
259 .mul(sk)
260 .into_affine();
261
262 let message = "random".as_bytes();
263 let message2 = "random2".as_bytes();
264
265 let sig = sign(sk, &message.to_vec()).unwrap();
266
267 let res = verify(pubkey, &message2.to_vec(), sig);
268 print!("{}", res);
269 }
270
271 #[test]
272 fn test_aggregate_signatures() {
273 let mut rng = test_rng();
274
275 let signatures: Vec<G1Affine> = (0..5).map(|_| G1Affine::rand(&mut rng)).collect();
277
278 let result = aggregate_signatures(&signatures);
280 assert!(result.is_ok());
281
282 let empty_signatures: Vec<G1Affine> = vec![];
284 let result = aggregate_signatures(&empty_signatures);
285 assert!(result.is_err());
286 assert_eq!(
287 result.unwrap_err().to_string(),
288 BLSError::SignatureListEmpty.to_string()
289 );
290
291 let mut invalid_signature = G1Affine::rand(&mut rng);
293 invalid_signature.y = invalid_signature.y.double(); let mut invalid_signatures = signatures.clone();
295 invalid_signatures.push(invalid_signature);
296 let result = aggregate_signatures(&invalid_signatures);
297 assert!(result.is_err());
298 assert_eq!(
299 result.unwrap_err().to_string(),
300 BLSError::SignatureNotInSubgroup.to_string()
301 );
302 }
303
304 #[test]
305 fn test_aggregate_public_keys() {
306 let mut rng = test_rng();
307
308 let public_keys: Vec<G2Affine> = (0..5).map(|_| G2Affine::rand(&mut rng)).collect();
310
311 let result = aggregate_public_keys(&public_keys);
313 assert!(result.is_ok());
314
315 let empty_public_keys: Vec<G2Affine> = vec![];
317 let result = aggregate_public_keys(&empty_public_keys);
318 assert!(result.is_err());
319 assert_eq!(
320 result.unwrap_err().to_string(),
321 BLSError::PublicKeyListEmpty.to_string()
322 );
323
324 let mut invalid_public_key = G2Affine::rand(&mut rng);
326 invalid_public_key.y = invalid_public_key.y.double(); let mut invalid_public_keys = public_keys.clone();
328 invalid_public_keys.push(invalid_public_key);
329 let result = aggregate_public_keys(&invalid_public_keys);
330 assert!(result.is_err());
331 assert_eq!(
332 result.unwrap_err().to_string(),
333 BLSError::PublicKeyNotInSubgroup.to_string()
334 );
335 }
336}