1use std::collections::BTreeMap;
7
8use bls12_381::{G1Affine, G1Projective, G2Affine, G2Projective, Scalar, pairing};
9use fedimint_core::bls12_381_serde;
10use fedimint_core::encoding::{Decodable, Encodable};
11use group::ff::Field;
12use group::{Curve, Group};
13use hex::encode;
14use rand::SeedableRng;
15use rand::rngs::OsRng;
16use rand_chacha::ChaChaRng;
17use serde::{Deserialize, Serialize};
18use sha3::Digest;
19
20const HASH_TAG: &[u8] = b"TBS_BLS12-381_";
21const FINGERPRINT_TAG: &[u8] = b"TBS_KFP24_";
22
23fn hash_bytes_to_g1(data: &[u8]) -> G1Projective {
24 let mut hash_engine = sha3::Sha3_256::new();
25
26 hash_engine.update(HASH_TAG);
27 hash_engine.update(data);
28
29 let mut prng = ChaChaRng::from_seed(hash_engine.finalize().into());
30
31 G1Projective::random(&mut prng)
32}
33
34#[derive(Copy, Clone, Debug, Eq, PartialEq, Encodable, Decodable, Serialize, Deserialize)]
35pub struct SecretKeyShare(#[serde(with = "bls12_381_serde::scalar")] pub Scalar);
36
37#[derive(Copy, Clone, Debug, Eq, PartialEq, Encodable, Decodable, Serialize, Deserialize)]
38pub struct PublicKeyShare(#[serde(with = "bls12_381_serde::g2")] pub G2Affine);
39
40#[derive(Copy, Clone, Debug, Eq, PartialEq, Encodable, Decodable, Serialize, Deserialize)]
41pub struct AggregatePublicKey(#[serde(with = "bls12_381_serde::g2")] pub G2Affine);
42
43#[derive(Copy, Clone, Debug, Eq, PartialEq, Encodable, Decodable, Serialize, Deserialize)]
44pub struct Message(#[serde(with = "bls12_381_serde::g1")] pub G1Affine);
45
46#[derive(Copy, Clone, Eq, PartialEq, Encodable, Decodable, Serialize, Deserialize)]
47pub struct BlindingKey(#[serde(with = "bls12_381_serde::scalar")] pub Scalar);
48
49#[derive(Copy, Clone, Debug, Eq, PartialEq, Encodable, Decodable, Serialize, Deserialize)]
50pub struct BlindedMessage(#[serde(with = "bls12_381_serde::g1")] pub G1Affine);
51
52#[derive(Copy, Clone, Debug, Eq, PartialEq, Encodable, Decodable, Serialize, Deserialize)]
53pub struct BlindedSignatureShare(#[serde(with = "bls12_381_serde::g1")] pub G1Affine);
54
55#[derive(Copy, Clone, Debug, Eq, PartialEq, Encodable, Decodable, Serialize, Deserialize)]
56pub struct BlindedSignature(#[serde(with = "bls12_381_serde::g1")] pub G1Affine);
57
58#[derive(Copy, Clone, Debug, Eq, PartialEq, Encodable, Decodable, Serialize, Deserialize)]
59pub struct Signature(#[serde(with = "bls12_381_serde::g1")] pub G1Affine);
60
61macro_rules! point_hash_impl {
62 ($type:ty) => {
63 impl std::hash::Hash for $type {
64 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
65 self.0.to_compressed().hash(state);
66 }
67 }
68 };
69}
70
71point_hash_impl!(PublicKeyShare);
72point_hash_impl!(AggregatePublicKey);
73point_hash_impl!(Message);
74point_hash_impl!(BlindedMessage);
75point_hash_impl!(BlindedSignatureShare);
76point_hash_impl!(BlindedSignature);
77point_hash_impl!(Signature);
78
79pub fn derive_pk_share(sk: &SecretKeyShare) -> PublicKeyShare {
80 PublicKeyShare((G2Projective::generator() * sk.0).to_affine())
81}
82
83impl BlindingKey {
84 pub fn random() -> BlindingKey {
85 BlindingKey(Scalar::random(OsRng))
87 }
88
89 fn fingerprint(&self) -> [u8; 32] {
90 let mut hash_engine = sha3::Sha3_256::new();
91 hash_engine.update(FINGERPRINT_TAG);
92 hash_engine.update(self.0.to_bytes());
93 let result = hash_engine.finalize();
94 result.into()
95 }
96}
97
98impl ::core::fmt::Debug for BlindingKey {
99 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
100 let fingerprint = self.fingerprint();
101 let fingerprint_hex = encode(&fingerprint[..]);
102 write!(f, "BlindingKey({fingerprint_hex})")
103 }
104}
105
106impl ::core::fmt::Display for BlindingKey {
107 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
108 let fingerprint = self.fingerprint();
109 let fingerprint_hex = encode(&fingerprint[..]);
110 write!(f, "{fingerprint_hex}")
111 }
112}
113
114impl Message {
115 pub fn from_bytes(msg: &[u8]) -> Message {
116 Message(hash_bytes_to_g1(msg).to_affine())
117 }
118}
119
120pub fn blind_message(msg: Message, blinding_key: BlindingKey) -> BlindedMessage {
121 let blinded_msg = msg.0 * blinding_key.0;
122
123 BlindedMessage(blinded_msg.to_affine())
124}
125
126pub fn sign_message(msg: BlindedMessage, sks: SecretKeyShare) -> BlindedSignatureShare {
127 let sig = msg.0 * sks.0;
128 BlindedSignatureShare(sig.to_affine())
129}
130
131pub fn verify_signature_share(
132 msg: BlindedMessage,
133 sig: BlindedSignatureShare,
134 pk: PublicKeyShare,
135) -> bool {
136 pairing(&msg.0, &pk.0) == pairing(&sig.0, &G2Affine::generator())
137}
138
139pub fn aggregate_signature_shares(
145 shares: &BTreeMap<u64, BlindedSignatureShare>,
146) -> BlindedSignature {
147 if shares.len() == 1 {
149 return BlindedSignature(
150 shares
151 .values()
152 .next()
153 .expect("We have at least one value")
154 .0,
155 );
156 }
157
158 BlindedSignature(
159 lagrange_multipliers(
160 shares
161 .keys()
162 .cloned()
163 .map(|peer| Scalar::from(peer + 1))
164 .collect(),
165 )
166 .into_iter()
167 .zip(shares.values())
168 .map(|(lagrange_multiplier, share)| lagrange_multiplier * share.0)
169 .reduce(|a, b| a + b)
170 .expect("We have at least one share")
171 .to_affine(),
172 )
173}
174
175pub fn aggregate_public_key_shares(shares: &BTreeMap<u64, PublicKeyShare>) -> AggregatePublicKey {
180 if shares.len() == 1 {
182 return AggregatePublicKey(
183 shares
184 .values()
185 .next()
186 .expect("We have at least one value")
187 .0,
188 );
189 }
190
191 AggregatePublicKey(
192 lagrange_multipliers(
193 shares
194 .keys()
195 .cloned()
196 .map(|peer| Scalar::from(peer + 1))
197 .collect(),
198 )
199 .into_iter()
200 .zip(shares.values())
201 .map(|(lagrange_multiplier, share)| lagrange_multiplier * share.0)
202 .reduce(|a, b| a + b)
203 .expect("We have at least one share")
204 .to_affine(),
205 )
206}
207
208fn lagrange_multipliers(scalars: Vec<Scalar>) -> Vec<Scalar> {
209 scalars
210 .iter()
211 .map(|i| {
212 scalars
213 .iter()
214 .filter(|j| *j != i)
215 .map(|j| j * (j - i).invert().expect("We filtered the case j == i"))
216 .reduce(|a, b| a * b)
217 .expect("We have at least one share")
218 })
219 .collect()
220}
221
222pub fn verify_blinded_signature(
223 msg: BlindedMessage,
224 sig: BlindedSignature,
225 pk: AggregatePublicKey,
226) -> bool {
227 pairing(&msg.0, &pk.0) == pairing(&sig.0, &G2Affine::generator())
228}
229
230pub fn unblind_signature(blinding_key: BlindingKey, blinded_sig: BlindedSignature) -> Signature {
231 let sig = blinded_sig.0 * blinding_key.0.invert().unwrap();
232 Signature(sig.to_affine())
233}
234
235pub fn verify(msg: Message, sig: Signature, pk: AggregatePublicKey) -> bool {
236 pairing(&msg.0, &pk.0) == pairing(&sig.0, &G2Affine::generator())
237}
238
239#[cfg(test)]
240mod tests;