Skip to main content

blueprint_crypto_bls/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(feature = "aggregation")]
4pub mod aggregation;
5
6pub mod error;
7#[cfg(test)]
8mod tests;
9
10pub use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
11use blueprint_std::vec::Vec;
12
13/// Serialize this to a vector of bytes.
14pub fn to_bytes<T: CanonicalSerialize>(elt: T) -> Vec<u8> {
15    let mut bytes = Vec::with_capacity(elt.compressed_size());
16
17    <T as CanonicalSerialize>::serialize_compressed(&elt, &mut bytes).unwrap();
18
19    bytes
20}
21
22/// Deserialize this from a slice of bytes.
23pub fn from_bytes<T: CanonicalDeserialize>(bytes: &[u8]) -> T {
24    <T as CanonicalDeserialize>::deserialize_compressed(&mut &bytes[..]).unwrap()
25}
26
27pub const CONTEXT: &[u8] = b"tangle";
28
29macro_rules! impl_w3f_serde {
30    ($name:ident, $inner:ty) => {
31        #[derive(Clone)]
32        pub struct $name(pub $inner);
33
34        impl PartialEq for $name {
35            fn eq(&self, other: &Self) -> bool {
36                self.to_bytes() == other.to_bytes()
37            }
38        }
39
40        impl Eq for $name {}
41
42        impl PartialOrd for $name {
43            fn partial_cmp(&self, other: &Self) -> Option<blueprint_std::cmp::Ordering> {
44                Some(self.cmp(other))
45            }
46        }
47
48        impl blueprint_std::hash::Hash for $name {
49            fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
50                self.to_bytes().hash(state);
51            }
52        }
53
54        impl Ord for $name {
55            fn cmp(&self, other: &Self) -> blueprint_std::cmp::Ordering {
56                self.to_bytes().cmp(&other.to_bytes())
57            }
58        }
59
60        impl blueprint_std::fmt::Debug for $name {
61            fn fmt(&self, f: &mut blueprint_std::fmt::Formatter<'_>) -> blueprint_std::fmt::Result {
62                write!(f, "{:?}", self.to_bytes())
63            }
64        }
65
66        impl BytesEncoding for $name {
67            fn to_bytes(&self) -> Vec<u8> {
68                crate::to_bytes(self.0.clone())
69            }
70
71            fn from_bytes(bytes: &[u8]) -> core::result::Result<Self, serde::de::value::Error> {
72                Ok($name(crate::from_bytes(bytes)))
73            }
74        }
75
76        impl serde::Serialize for $name {
77            fn serialize<S: serde::Serializer>(
78                &self,
79                serializer: S,
80            ) -> core::result::Result<S::Ok, S::Error> {
81                let bytes = self.to_bytes();
82                Vec::serialize(&bytes, serializer)
83            }
84        }
85
86        impl<'de> serde::Deserialize<'de> for $name {
87            fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
88            where
89                D: serde::Deserializer<'de>,
90            {
91                // Deserialize as Vec
92                let bytes = <Vec<u8>>::deserialize(deserializer)?;
93
94                // Convert bytes back to inner type
95                let inner = from_bytes::<$inner>(&bytes);
96
97                Ok($name(inner))
98            }
99        }
100    };
101}
102
103macro_rules! define_bls_key {
104    ($($ty:ident),+) => {
105        paste::paste! {
106            $(
107            pub mod [<$ty:lower>] {
108                use crate::error::{BlsError, Result};
109                use crate::from_bytes;
110                use blueprint_crypto_core::{KeyType, KeyTypeId, BytesEncoding};
111                use blueprint_std::{UniformRand, string::{String, ToString}};
112                use tnt_bls::{Message, PublicKey, SecretKey, SerializableToBytes, Signature, [<Tiny $ty:upper>]};
113
114                #[doc = $ty:upper]
115                /// key type
116                #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
117                pub struct [<W3f $ty>];
118
119                impl_w3f_serde!([<W3f $ty Public>], PublicKey<[<Tiny $ty:upper>]>);
120                impl_w3f_serde!([<W3f $ty Secret>], SecretKey<[<Tiny $ty:upper>]>);
121                impl_w3f_serde!([<W3f $ty Signature>], Signature<[<Tiny $ty:upper>]>);
122
123                impl zeroize::Zeroize for [<W3f $ty Secret>] {
124                    fn zeroize(&mut self) {
125                        let ptr = (&raw mut self.0).cast::<u8>();
126                        let len = core::mem::size_of::<SecretKey<[<Tiny $ty:upper>]>>();
127                        unsafe { core::ptr::write_bytes(ptr, 0, len) };
128                        core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
129                    }
130                }
131
132                impl Drop for [<W3f $ty Secret>] {
133                    fn drop(&mut self) {
134                        use zeroize::Zeroize;
135                        self.zeroize();
136                    }
137                }
138
139                impl KeyType for [<W3f $ty>] {
140                    type Public = [<W3f $ty Public>];
141                    type Secret = [<W3f $ty Secret>];
142                    type Signature = [<W3f $ty Signature>];
143                    type Error = BlsError;
144
145                    fn key_type_id() -> KeyTypeId {
146                        KeyTypeId::$ty
147                    }
148
149                    fn generate_with_seed(seed: Option<&[u8]>) -> Result<Self::Secret> {
150                        if let Some(seed) = seed {
151                            Ok([<W3f $ty Secret>](SecretKey::from_seed(seed)))
152                        } else {
153                            #[cfg(feature = "std")]
154                            {
155                                let mut rng = Self::get_rng();
156                                let rand_bytes = <[u8; 32]>::rand(&mut rng);
157                                Ok([<W3f $ty Secret>](SecretKey::from_seed(&rand_bytes)))
158                            }
159                            #[cfg(not(feature = "std"))]
160                            Err(BlsError::InvalidSeed(
161                                "Random key generation requires the std feature".into(),
162                            ))
163                        }
164                    }
165
166                    fn generate_with_string(secret: String) -> Result<Self::Secret> {
167                        let hex_encoded = hex::decode(secret)?;
168                        let secret =
169                            SecretKey::from_bytes(&hex_encoded).map_err(|e| BlsError::InvalidSeed(e.to_string()))?;
170                        Ok([<W3f $ty Secret>](secret))
171                    }
172
173                    fn public_from_secret(secret: &Self::Secret) -> Self::Public {
174                        [<W3f $ty Public>](secret.0.into_public())
175                    }
176
177                    #[cfg(feature = "std")]
178                    fn sign_with_secret(secret: &mut Self::Secret, msg: &[u8]) -> Result<Self::Signature> {
179                        let mut rng = Self::get_rng();
180                        let message: Message = Message::new(super::CONTEXT, msg);
181                        Ok([<W3f $ty Signature>](secret.0.sign(&message, &mut rng)))
182                    }
183
184                    #[cfg(not(feature = "std"))]
185                    fn sign_with_secret(_secret: &mut Self::Secret, _msg: &[u8]) -> Result<Self::Signature> {
186                        Err(BlsError::InvalidSeed("BLS signing requires the std feature".into()))
187                    }
188
189                    #[cfg(feature = "std")]
190                    fn sign_with_secret_pre_hashed(
191                        secret: &mut Self::Secret,
192                        msg: &[u8; 32],
193                    ) -> Result<Self::Signature> {
194                        let mut rng = Self::get_rng();
195                        let message: Message = Message::new(super::CONTEXT, msg);
196                        Ok([<W3f $ty Signature>](secret.0.sign(&message, &mut rng)))
197                    }
198
199                    #[cfg(not(feature = "std"))]
200                    fn sign_with_secret_pre_hashed(
201                        _secret: &mut Self::Secret,
202                        _msg: &[u8; 32],
203                    ) -> Result<Self::Signature> {
204                        Err(BlsError::InvalidSeed("BLS signing requires the std feature".into()))
205                    }
206
207                    fn verify(public: &Self::Public, msg: &[u8], signature: &Self::Signature) -> bool {
208                        let message = Message::new(super::CONTEXT, msg);
209                        signature.0.verify(&message, &public.0)
210                    }
211                }
212            }
213            )+
214        }
215    }
216}
217
218define_bls_key!(Bls377, Bls381);