Skip to main content

blueprint_crypto_bn254/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3pub mod aggregation;
4pub mod error;
5use error::{Bn254Error, Result};
6
7#[cfg(test)]
8mod tests;
9
10use ark_bn254::{Bn254, Fq, Fr, G1Affine, G1Projective, G2Affine};
11use ark_ec::{AffineRepr, CurveGroup, pairing::Pairing};
12#[cfg(feature = "std")]
13use ark_ff::UniformRand;
14use ark_ff::{BigInteger256, Field, One, PrimeField};
15use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
16use blueprint_crypto_core::BytesEncoding;
17use blueprint_crypto_core::{KeyType, KeyTypeId};
18use blueprint_std::hash::Hash;
19use blueprint_std::vec::Vec;
20use blueprint_std::{
21    str::FromStr,
22    string::{String, ToString},
23};
24use num_bigint::BigUint;
25use serde::{Deserialize, Serialize};
26use sha2::{Digest, Sha256};
27
28/// Serialize this to a vector of bytes.
29pub fn to_bytes<T: CanonicalSerialize>(elt: T) -> Vec<u8> {
30    let mut bytes = Vec::with_capacity(elt.compressed_size());
31
32    <T as CanonicalSerialize>::serialize_compressed(&elt, &mut bytes).unwrap();
33
34    bytes
35}
36
37/// Deserialize this from a slice of bytes.
38pub fn from_bytes<T: CanonicalDeserialize>(bytes: &[u8]) -> T {
39    <T as CanonicalDeserialize>::deserialize_compressed(&mut &bytes[..]).unwrap()
40}
41
42fn hash_to_curve(digest: &[u8]) -> G1Affine {
43    let one = Fq::one();
44    let three = Fq::from(3u64);
45
46    let mut hasher = Sha256::new();
47    hasher.update(digest);
48    let hashed_result = hasher.finalize();
49
50    // Convert digest to a big integer and then to a field element
51    let mut x = {
52        let big_int = BigUint::from_bytes_be(&hashed_result);
53        let mut bytes = [0u8; 32];
54        big_int
55            .to_bytes_be()
56            .iter()
57            .rev()
58            .enumerate()
59            .for_each(|(i, &b)| bytes[i] = b);
60        Fq::from_le_bytes_mod_order(&bytes)
61    };
62
63    loop {
64        // y = x^3 + 3
65        let mut y = x;
66        y.square_in_place();
67        y *= x;
68        y += three;
69
70        // Check if y is a quadratic residue (i.e., has a square root in the field)
71        if let Some(y) = y.sqrt() {
72            return G1Projective::new(x, y, Fq::one()).into_affine();
73        }
74        // x = x + 1
75        x += one;
76    }
77}
78
79pub fn sign(sk: Fr, message: &[u8]) -> Result<G1Affine> {
80    let q = hash_to_curve(message);
81
82    let sk_int: BigInteger256 = sk.into();
83    let r = q.mul_bigint(sk_int);
84
85    if !r.into_affine().is_on_curve() || !r.into_affine().is_in_correct_subgroup_assuming_on_curve()
86    {
87        return Err(Bn254Error::SignatureNotInSubgroup);
88    }
89
90    Ok(r.into_affine())
91}
92
93pub fn verify(public_key: G2Affine, message: &[u8], signature: G1Affine) -> bool {
94    if !signature.is_in_correct_subgroup_assuming_on_curve() || !signature.is_on_curve() {
95        return false;
96    }
97
98    let q = hash_to_curve(message);
99    let c1 = Bn254::pairing(q, public_key);
100    let c2 = Bn254::pairing(signature, G2Affine::generator());
101    c1 == c2
102}
103
104/// BLS-BN254 key type
105#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
106pub struct ArkBlsBn254;
107
108macro_rules! impl_ark_serde {
109    ($name:ident, $inner:ty) => {
110        #[derive(Clone, PartialEq, Eq, Debug)]
111        pub struct $name(pub $inner);
112
113        impl PartialOrd for $name {
114            fn partial_cmp(&self, other: &Self) -> Option<blueprint_std::cmp::Ordering> {
115                Some(self.cmp(other))
116            }
117        }
118
119        impl Ord for $name {
120            fn cmp(&self, other: &Self) -> blueprint_std::cmp::Ordering {
121                self.to_bytes().cmp(&other.to_bytes())
122            }
123        }
124
125        impl Hash for $name {
126            fn hash<H: blueprint_std::hash::Hasher>(&self, state: &mut H) {
127                self.to_bytes().hash(state);
128            }
129        }
130
131        impl BytesEncoding for $name {
132            fn to_bytes(&self) -> Vec<u8> {
133                crate::to_bytes(self.0)
134            }
135
136            fn from_bytes(bytes: &[u8]) -> core::result::Result<Self, serde::de::value::Error> {
137                let inner = from_bytes::<$inner>(&bytes);
138                Ok($name(inner))
139            }
140        }
141
142        impl serde::Serialize for $name {
143            fn serialize<S: serde::Serializer>(
144                &self,
145                serializer: S,
146            ) -> core::result::Result<S::Ok, S::Error> {
147                let bytes = self.to_bytes();
148                Vec::serialize(&bytes, serializer)
149            }
150        }
151
152        impl<'de> serde::Deserialize<'de> for $name {
153            fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
154            where
155                D: serde::Deserializer<'de>,
156            {
157                let bytes = <Vec<u8>>::deserialize(deserializer)?;
158                let inner = from_bytes::<$inner>(&bytes);
159                Ok($name(inner))
160            }
161        }
162    };
163}
164
165impl_ark_serde!(ArkBlsBn254Public, G2Affine);
166impl_ark_serde!(ArkBlsBn254Secret, Fr);
167impl_ark_serde!(ArkBlsBn254Signature, G1Affine);
168
169impl zeroize::Zeroize for ArkBlsBn254Secret {
170    fn zeroize(&mut self) {
171        let ptr = (&raw mut self.0).cast::<u8>();
172        let len = core::mem::size_of::<Fr>();
173        unsafe { core::ptr::write_bytes(ptr, 0, len) };
174        core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
175    }
176}
177
178impl Drop for ArkBlsBn254Secret {
179    fn drop(&mut self) {
180        use zeroize::Zeroize;
181        self.zeroize();
182    }
183}
184
185impl KeyType for ArkBlsBn254 {
186    type Public = ArkBlsBn254Public;
187    type Secret = ArkBlsBn254Secret;
188    type Signature = ArkBlsBn254Signature;
189    type Error = Bn254Error;
190
191    fn key_type_id() -> KeyTypeId {
192        KeyTypeId::Bn254
193    }
194
195    fn generate_with_seed(seed: Option<&[u8]>) -> Result<Self::Secret> {
196        let secret = if let Some(seed) = seed {
197            Fr::from_random_bytes(seed)
198                .ok_or_else(|| Bn254Error::InvalidSeed("None value".to_string()))?
199        } else {
200            #[cfg(feature = "std")]
201            {
202                let mut rng = Self::get_rng();
203                Fr::rand(&mut rng)
204            }
205            #[cfg(not(feature = "std"))]
206            return Err(Bn254Error::InvalidSeed(
207                "Random key generation requires the std feature".into(),
208            ));
209        };
210        Ok(ArkBlsBn254Secret(secret))
211    }
212
213    fn generate_with_string(secret: String) -> Result<Self::Secret> {
214        let secret = Fr::from_str(&secret)
215            .map_err(|()| Bn254Error::InvalidSeed("Invalid secret string".to_string()))?;
216        Ok(ArkBlsBn254Secret(secret))
217    }
218
219    fn public_from_secret(secret: &Self::Secret) -> Self::Public {
220        ArkBlsBn254Public(
221            G2Affine::generator()
222                .mul_bigint(secret.0.into_bigint())
223                .into_affine(),
224        )
225    }
226
227    fn sign_with_secret(secret: &mut Self::Secret, msg: &[u8]) -> Result<Self::Signature> {
228        let signature =
229            sign(secret.0, msg).map_err(|e| Bn254Error::SignatureFailed(e.to_string()))?;
230        Ok(ArkBlsBn254Signature(signature))
231    }
232
233    fn sign_with_secret_pre_hashed(
234        secret: &mut Self::Secret,
235        msg: &[u8; 32],
236    ) -> Result<Self::Signature> {
237        let signature =
238            sign(secret.0, msg).map_err(|e| Bn254Error::SignatureFailed(e.to_string()))?;
239        Ok(ArkBlsBn254Signature(signature))
240    }
241
242    fn verify(public: &Self::Public, msg: &[u8], signature: &Self::Signature) -> bool {
243        verify(public.0, msg, signature.0)
244    }
245}