blueprint_crypto_bls/
lib.rs1#![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
13pub 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
22pub 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 let bytes = <Vec<u8>>::deserialize(deserializer)?;
93
94 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 #[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);