1use ark_bls12_381::fr::Fr;
10use ark_bls12_381::g2::Config as G2Config;
11use ark_bls12_381::Bls12_381;
12use ark_bls12_381::G1Projective;
13use ark_bls12_381::G2Projective;
14use ark_ec::hashing::curve_maps::wb::WBMap;
15use ark_ec::hashing::map_to_curve_hasher::MapToCurveBasedHasher;
16use ark_ec::hashing::HashToCurve;
17use ark_ec::pairing::Pairing;
18use ark_ec::Group;
19use ark_ff::fields::field_hashers::DefaultFieldHasher;
20use ark_serialize::CanonicalDeserialize;
21use ark_serialize::CanonicalSerialize;
22use ark_std::UniformRand;
23use libsecp256k1;
24use rand::SeedableRng;
25use rand_hc::Hc128Rng;
26
27use crate::ecc::PublicKey;
28use crate::ecc::SecretKey;
29use crate::error::Error;
30use crate::error::Result;
31
32const CSUITE: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_";
34
35#[derive(Clone, Debug, Eq, PartialEq)]
37pub struct Signature(pub [u8; 96]);
38
39pub fn random_sk() -> Result<SecretKey> {
41 let mut rng = Hc128Rng::from_entropy();
42 Fr::rand(&mut rng).try_into()
43}
44
45fn from_compressed<T: CanonicalDeserialize, const S: usize>(a: &[u8; S]) -> Result<T> {
46 T::deserialize_compressed(&a[..]).map_err(|_| Error::EccDeserializeFailed)
47}
48
49fn to_compressed<T: CanonicalSerialize, const S: usize>(s: &T) -> Result<[u8; S]> {
50 let mut data: Vec<u8> = vec![];
51 s.serialize_compressed(&mut data)
52 .map_err(|_| Error::EccSerializeFailed)?;
53 assert_eq!(s.compressed_size(), S);
54 assert_eq!(data.len(), S);
55 let ret: [u8; S] = data.try_into().map_err(|_| Error::EccSerializeFailed)?;
56 Ok(ret)
57}
58
59impl TryFrom<SecretKey> for Fr {
60 type Error = Error;
61 fn try_from(sk: SecretKey) -> Result<Fr> {
62 let data: [u8; 32] = sk.0.serialize();
63 let ret: Fr = from_compressed(&data)?;
64 Ok(ret)
65 }
66}
67
68impl TryFrom<Fr> for SecretKey {
69 type Error = Error;
70 fn try_from(sk: Fr) -> Result<SecretKey> {
71 let data: [u8; 32] = to_compressed(&sk)?;
72 let sk = libsecp256k1::SecretKey::parse(&data)?;
73 Ok(SecretKey(sk))
74 }
75}
76
77impl TryFrom<Signature> for G2Projective {
78 type Error = Error;
79 fn try_from(s: Signature) -> Result<Self> {
80 from_compressed(&s.0)
81 }
82}
83
84impl TryFrom<G2Projective> for Signature {
85 type Error = Error;
86 fn try_from(s: G2Projective) -> Result<Self> {
87 Ok(Signature(to_compressed(&s)?))
88 }
89}
90
91impl TryFrom<G1Projective> for PublicKey<48> {
92 type Error = Error;
93 fn try_from(p: G1Projective) -> Result<Self> {
94 Ok(PublicKey(to_compressed::<G1Projective, 48>(&p)?))
95 }
96}
97
98impl TryFrom<PublicKey<48>> for G1Projective {
99 type Error = Error;
100 fn try_from(pk: PublicKey<48>) -> Result<Self> {
101 let data: [u8; 48] = pk.0;
102 let ret: Self = from_compressed(&data)?;
103 Ok(ret)
104 }
105}
106
107pub fn hash_to_curve(msg: &[u8]) -> Result<[u8; 96]> {
110 let hasher = MapToCurveBasedHasher::<
112 G2Projective,
113 DefaultFieldHasher<sha2::Sha256, 128>,
114 WBMap<G2Config>,
115 >::new(CSUITE)
116 .map_err(|_| Error::CurveHasherInitFailed)?;
117 let hashed = hasher.hash(msg).map_err(|_| Error::CurveHasherFailed)?;
118 let ret: [u8; 96] = to_compressed(&hashed)?;
119 Ok(ret)
120}
121
122pub fn sign_hash(sk: SecretKey, hashed_msg: &[u8; 96]) -> Result<Signature> {
124 let sk: Fr = sk.try_into()?;
125 let msg: G2Projective = from_compressed(hashed_msg)?;
126 Ok(Signature(to_compressed(&(msg * sk))?))
127}
128
129pub fn sign(sk: SecretKey, msg: &[u8]) -> Result<Signature> {
132 let sk: Fr = sk.try_into()?;
133 let hashed_msg = hash_to_curve(msg)?;
134 let msg: G2Projective = from_compressed(&hashed_msg)?;
135 Ok(Signature(to_compressed(&(msg * sk))?))
136}
137
138pub fn verify_hash(hashes: &[[u8; 96]], sig: &Signature, pks: &[PublicKey<48>]) -> Result<bool> {
141 let sig: G2Projective = sig.clone().try_into()?;
142 let g1 = G1Projective::generator();
143 let e1 = Bls12_381::pairing(g1, sig);
144
145 let hashes: Vec<G2Projective> = hashes
146 .iter()
147 .map(from_compressed)
148 .collect::<Result<Vec<G2Projective>>>()?;
149
150 let pks: Vec<G1Projective> = pks
151 .iter()
152 .map(|pk| (*pk).try_into())
153 .collect::<Result<Vec<G1Projective>>>()?;
154
155 let mm_out = Bls12_381::multi_miller_loop(pks, hashes);
156 if let Some(e2) = Bls12_381::final_exponentiation(mm_out) {
157 Ok(e1 == e2)
158 } else {
159 Ok(false)
160 }
161}
162
163pub fn verify(msgs: &[&[u8]], sig: &Signature, pks: &[PublicKey<48>]) -> Result<bool> {
166 let hashes: Vec<[u8; 96]> = msgs
167 .iter()
168 .map(|msg| hash_to_curve(msg))
169 .collect::<Result<Vec<[u8; 96]>>>()?;
170 verify_hash(hashes.as_slice(), sig, pks)
171}
172
173pub fn aggregate(signatures: &[Signature]) -> Result<Signature> {
175 signatures
176 .iter()
177 .map(|sig| sig.clone().try_into())
178 .collect::<Result<Vec<G2Projective>>>()?
179 .iter()
180 .sum::<G2Projective>()
181 .try_into()
182}
183
184pub fn public_key(key: &SecretKey) -> Result<PublicKey<48>> {
187 let sk: Fr = (*key).try_into()?;
188 let g1 = G1Projective::generator();
189 (g1 * sk).try_into()
190}
191
192#[cfg(test)]
193mod test {
194 use super::*;
195
196 #[test]
197 fn test_sign_and_verify() {
198 let key = random_sk().unwrap();
199 let msg = "hello world";
200 let pk = public_key(&key).unwrap();
201 let h = hash_to_curve(msg.as_bytes()).unwrap();
202 let sig = sign_hash(key, &h).unwrap();
203 assert!(super::verify_hash(vec![h].as_slice(), &sig, vec![pk].as_slice()).unwrap());
204 assert!(super::verify(vec![msg.as_bytes()].as_slice(), &sig, vec![pk].as_slice()).unwrap());
205 }
206
207 #[test]
208 fn test_hash_result() {
209 let hashed_data: [u8; 96] = [
212 138, 203, 106, 10, 25, 0, 11, 120, 167, 254, 109, 207, 27, 42, 63, 46, 108, 179, 30,
213 196, 146, 10, 94, 148, 237, 209, 198, 48, 23, 211, 67, 188, 147, 170, 94, 52, 176, 113,
214 111, 214, 28, 35, 235, 16, 215, 69, 185, 65, 15, 66, 199, 2, 245, 101, 145, 144, 209,
215 52, 71, 179, 27, 209, 127, 155, 231, 9, 235, 11, 82, 89, 83, 171, 47, 179, 253, 128,
216 26, 104, 238, 91, 182, 207, 152, 70, 243, 206, 65, 226, 81, 113, 69, 125, 85, 142, 27,
217 254,
218 ];
219 let msg = "hello world";
220 let h = hash_to_curve(msg.as_bytes()).unwrap();
221 assert_eq!(h, hashed_data);
222 }
223
224 #[test]
225 fn test_aggregate() {
226 let key1 = random_sk().unwrap();
227 let key2 = random_sk().unwrap();
228
229 let msg1 = "hello alice";
230 let msg2 = "hello bob";
231
232 let pk1 = public_key(&key1).unwrap();
233 let pk2 = public_key(&key2).unwrap();
234
235 let h1 = hash_to_curve(msg1.as_bytes()).unwrap();
236 let h2 = hash_to_curve(msg2.as_bytes()).unwrap();
237
238 let sig1 = sign_hash(key1, &h1).unwrap();
239 let sig2 = sign_hash(key2, &h2).unwrap();
240
241 let sig_agg = aggregate(&[sig1, sig2]).unwrap();
242
243 assert!(
244 super::verify_hash(vec![h1, h2].as_slice(), &sig_agg, vec![pk1, pk2].as_slice())
245 .unwrap()
246 );
247 }
248}