rings_core/ecc/signers/bls/
mod.rs1use 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::PrimeGroup;
19use ark_ff::fields::field_hashers::DefaultFieldHasher;
20use ark_serialize::CanonicalDeserialize;
21use ark_serialize::CanonicalSerialize;
22use ark_std::UniformRand;
23use rand::SeedableRng;
24use rand_hc::Hc128Rng;
25
26use crate::ecc::PublicKey;
27use crate::ecc::SecretKey;
28use crate::error::Error;
29use crate::error::Result;
30
31const CSUITE: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_";
33
34#[derive(Clone, Debug, Eq, PartialEq)]
36pub struct Signature(pub [u8; 96]);
37
38pub fn random_sk() -> Result<SecretKey> {
40 let mut rng = Hc128Rng::from_entropy();
41 Fr::rand(&mut rng).try_into()
42}
43
44fn from_compressed<T: CanonicalDeserialize, const S: usize>(a: &[u8; S]) -> Result<T> {
45 T::deserialize_compressed(&a[..]).map_err(|_| Error::EccDeserializeFailed)
46}
47
48fn to_compressed<T: CanonicalSerialize, const S: usize>(s: &T) -> Result<[u8; S]> {
49 let mut data: Vec<u8> = vec![];
50 s.serialize_compressed(&mut data)
51 .map_err(|_| Error::EccSerializeFailed)?;
52 assert_eq!(s.compressed_size(), S);
53 assert_eq!(data.len(), S);
54 let ret: [u8; S] = data.try_into().map_err(|_| Error::EccSerializeFailed)?;
55 Ok(ret)
56}
57
58impl TryFrom<SecretKey> for Fr {
59 type Error = Error;
60 fn try_from(sk: SecretKey) -> Result<Fr> {
61 let data: [u8; 32] = sk.ser();
62 let ret: Fr = from_compressed(&data)?;
63 Ok(ret)
64 }
65}
66
67impl TryFrom<Fr> for SecretKey {
68 type Error = Error;
69 fn try_from(sk: Fr) -> Result<SecretKey> {
70 let data: [u8; 32] = to_compressed(&sk)?;
71 SecretKey::from_bytes(data)
72 }
73}
74
75impl TryFrom<Signature> for G2Projective {
76 type Error = Error;
77 fn try_from(s: Signature) -> Result<Self> {
78 from_compressed(&s.0)
79 }
80}
81
82impl TryFrom<G2Projective> for Signature {
83 type Error = Error;
84 fn try_from(s: G2Projective) -> Result<Self> {
85 Ok(Signature(to_compressed(&s)?))
86 }
87}
88
89impl TryFrom<G1Projective> for PublicKey<48> {
90 type Error = Error;
91 fn try_from(p: G1Projective) -> Result<Self> {
92 Ok(PublicKey(to_compressed::<G1Projective, 48>(&p)?))
93 }
94}
95
96impl TryFrom<PublicKey<48>> for G1Projective {
97 type Error = Error;
98 fn try_from(pk: PublicKey<48>) -> Result<Self> {
99 let data: [u8; 48] = pk.0;
100 let ret: Self = from_compressed(&data)?;
101 Ok(ret)
102 }
103}
104
105pub fn hash_to_curve(msg: &[u8]) -> Result<[u8; 96]> {
108 let hasher = MapToCurveBasedHasher::<
110 G2Projective,
111 DefaultFieldHasher<sha2::Sha256, 128>,
112 WBMap<G2Config>,
113 >::new(CSUITE)
114 .map_err(|_| Error::CurveHasherInitFailed)?;
115 let hashed = hasher.hash(msg).map_err(|_| Error::CurveHasherFailed)?;
116 let ret: [u8; 96] = to_compressed(&hashed)?;
117 Ok(ret)
118}
119
120pub fn sign_hash(sk: SecretKey, hashed_msg: &[u8; 96]) -> Result<Signature> {
122 let sk: Fr = sk.try_into()?;
123 let msg: G2Projective = from_compressed(hashed_msg)?;
124 Ok(Signature(to_compressed(&(msg * sk))?))
125}
126
127pub fn sign(sk: SecretKey, msg: &[u8]) -> Result<Signature> {
130 let sk: Fr = sk.try_into()?;
131 let hashed_msg = hash_to_curve(msg)?;
132 let msg: G2Projective = from_compressed(&hashed_msg)?;
133 Ok(Signature(to_compressed(&(msg * sk))?))
134}
135
136pub fn verify_hash(hashes: &[[u8; 96]], sig: &Signature, pks: &[PublicKey<48>]) -> Result<bool> {
139 let sig: G2Projective = sig.clone().try_into()?;
140 let g1 = G1Projective::generator();
141 let e1 = Bls12_381::pairing(g1, sig);
142
143 let hashes: Vec<G2Projective> = hashes
144 .iter()
145 .map(from_compressed)
146 .collect::<Result<Vec<G2Projective>>>()?;
147
148 let pks: Vec<G1Projective> = pks
149 .iter()
150 .map(|pk| (*pk).try_into())
151 .collect::<Result<Vec<G1Projective>>>()?;
152
153 let mm_out = Bls12_381::multi_miller_loop(pks, hashes);
154 if let Some(e2) = Bls12_381::final_exponentiation(mm_out) {
155 Ok(e1 == e2)
156 } else {
157 Ok(false)
158 }
159}
160
161pub fn verify(msgs: &[&[u8]], sig: &Signature, pks: &[PublicKey<48>]) -> Result<bool> {
164 let hashes: Vec<[u8; 96]> = msgs
165 .iter()
166 .map(|msg| hash_to_curve(msg))
167 .collect::<Result<Vec<[u8; 96]>>>()?;
168 verify_hash(hashes.as_slice(), sig, pks)
169}
170
171pub 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_bls;