Skip to content

Commit 6f10786

Browse files
committed
feat: add initial implementation of tbls
1 parent 6e7ba2e commit 6f10786

4 files changed

Lines changed: 194 additions & 115 deletions

File tree

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ serde_json = { version = "^1.0" }
3434
hex = { version = "^0.4.3" }
3535
chrono = { version = "0.4", features = ["serde"] }
3636
rand = "0.9"
37-
blst = "0.3.16"
37+
blsful = "2.5.7"
38+
rand_core = "0.9.3"
3839

3940
[workspace.lints.clippy]
4041
arithmetic_side_effects = "deny"

crates/charon-crypto/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ publish.workspace = true
88

99
[dependencies]
1010
rand.workspace = true
11-
blst.workspace = true
11+
blsful.workspace = true
12+
rand_core.workspace = true
13+
serde.workspace = true
1214

1315
[lints]
1416
workspace = true

crates/charon-crypto/src/herumi.rs

Lines changed: 162 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
use std::{collections::HashMap, sync::Once};
1+
use std::collections::HashMap;
22

3-
use blst::min_pk::SecretKey;
4-
use rand::Rng;
5-
6-
use blst::min_pk::{
7-
PublicKey as BlstPublicKey, SecretKey as BlstSecretKey,
3+
use blsful::{
4+
AggregateSignature, Bls12381G2Impl, MultiSignature, PublicKey as BlsPublicKey, SecretKey,
5+
SecretKeyShare, Signature as BlsSignature, SignatureSchemes, SignatureShare,
6+
vsss_rs::elliptic_curve::rand_core::{CryptoRng, RngCore},
87
};
98

10-
use crate::tbls::{Error, PrivateKey, PublicKey, Tbls, Signature};
11-
12-
const INIT_ONCE: Once = Once::new();
9+
use crate::tbls::{Error, PrivateKey, PublicKey, Signature, Tbls};
1310

1411
/// Herumi is an Implementation with Herumi-specific inner logic.
1512
pub struct Herumi {}
@@ -19,123 +16,198 @@ impl Herumi {
1916
pub fn new() -> Self {
2017
Self {}
2118
}
22-
23-
/// Initialize the Herumi instance.
24-
pub fn init() {
25-
INIT_ONCE.call_once(|| {});
26-
}
27-
}
28-
29-
fn generate_insecure_secret(rng: &mut impl Rng) -> Result<SecretKey, Error> {
30-
for _ in 0..100 {
31-
let mut ikm = [0u8; 32];
32-
rng.fill(&mut ikm);
33-
let sk = SecretKey::deserialize(&ikm);
34-
if sk.is_ok() {
35-
return Ok(sk.unwrap());
36-
}
37-
}
38-
Err(Error::InvalidSecretKeyLength)
3919
}
4020

4121
impl Tbls for Herumi {
4222
// todo: this is not aligned with the original implementation
43-
fn generate_secret_key(&self) -> Result<PrivateKey, Error> {
44-
let mut ikm = [0u8; 32];
45-
rand::rng().fill(&mut ikm);
46-
let sk = SecretKey::key_gen(&ikm, &[]).map_err(|_| Error::InvalidSecretKeyLength)?;
47-
Ok(sk.serialize())
23+
fn generate_secret_key(&self, mut rng: impl RngCore + CryptoRng) -> Result<PrivateKey, Error> {
24+
let result: SecretKey<Bls12381G2Impl> = SecretKey::random(&mut rng);
25+
Ok(result.to_be_bytes())
4826
}
4927

50-
fn generate_insecure_secret(&self, rng: &mut impl Rng) -> Result<PrivateKey, Error> {
51-
for _ in 0..100 {
52-
let mut ikm = [0u8; 32];
53-
rng.fill(&mut ikm);
54-
let sk = SecretKey::deserialize(&ikm);
55-
56-
if sk.is_ok() {
57-
return Ok(sk.unwrap().serialize());
58-
}
59-
}
60-
Err(Error::InvalidSecretKeyLength)
28+
fn generate_insecure_secret(
29+
&self,
30+
mut rng: impl RngCore + CryptoRng,
31+
) -> Result<PrivateKey, Error> {
32+
unimplemented!()
6133
}
6234

6335
fn secret_to_public_key(&self, secret_key: &PrivateKey) -> Result<PublicKey, Error> {
64-
let sk =
65-
SecretKey::deserialize(secret_key).map_err(|_| Error::FailedToDeserializeSecretKey)?;
66-
let pk = sk.sk_to_pk();
67-
Ok(pk.to_bytes())
36+
let result = SecretKey::<Bls12381G2Impl>::from_be_bytes(secret_key);
37+
if result.is_none().unwrap_u8() == 1 {
38+
return Err(Error::FailedToDeserializeSecretKey);
39+
}
40+
let secret_key = result.unwrap();
41+
let public_key = secret_key.public_key();
42+
43+
let public_key_vec = Vec::from(&public_key);
44+
45+
if public_key_vec.len() != 48 {
46+
return Err(Error::InvalidPublicKeyLength);
47+
}
48+
49+
let mut public_key = [0u8; 48];
50+
public_key.copy_from_slice(&public_key_vec);
51+
Ok(public_key)
6852
}
6953

7054
fn threshold_split_insecure(
7155
&self,
7256
secret_key: &PrivateKey,
7357
total: u64,
7458
threshold: u64,
75-
rng: &mut impl Rng,
59+
mut rng: impl RngCore + CryptoRng,
7660
) -> Result<HashMap<u64, PrivateKey>, Error> {
77-
if threshold <= 1 {
78-
return Err(Error::InvalidThreshold);
61+
let result = SecretKey::<Bls12381G2Impl>::from_be_bytes(secret_key);
62+
if result.is_none().unwrap_u8() == 1 {
63+
return Err(Error::FailedToDeserializeSecretKey);
7964
}
80-
let sk = SecretKey::deserialize(secret_key).map_err(|_| Error::FailedToDeserializeSecretKey)?;
81-
82-
83-
let mut poly: HashMap<u64, PrivateKey> = HashMap::new();
84-
85-
// Initialize threshold amount of points
86-
for i in 1..threshold {
87-
let secret = generate_insecure_secret(rng)?;
88-
89-
poly.insert(i, secret.serialize());
65+
let secret_key = result.unwrap();
66+
let shares = secret_key
67+
.split_with_rng(threshold as usize, total as usize, &mut rng)
68+
.unwrap();
69+
70+
let mut shares_map = HashMap::new();
71+
for (i, share) in shares.iter().enumerate() {
72+
let share_vec = Vec::from(share.as_raw_value());
73+
let mut share_secret_key = [0u8; 32];
74+
share_secret_key.copy_from_slice(&share_vec);
75+
shares_map.insert(i as u64, share_secret_key);
9076
}
9177

92-
Ok(poly)
78+
Ok(shares_map)
9379
}
9480

9581
fn threshold_split(
9682
&self,
97-
_secret_key: &PrivateKey,
98-
_total: u64,
99-
_threshold: u64,
83+
secret_key: &PrivateKey,
84+
total: u64,
85+
threshold: u64,
10086
) -> Result<HashMap<u64, PrivateKey>, Error> {
101-
unimplemented!()
87+
let result = SecretKey::<Bls12381G2Impl>::from_be_bytes(secret_key);
88+
if result.is_none().unwrap_u8() == 1 {
89+
return Err(Error::FailedToDeserializeSecretKey);
90+
}
91+
let secret_key = result.unwrap();
92+
let shares = secret_key
93+
.split(threshold as usize, total as usize)
94+
.unwrap();
95+
96+
let mut shares_map = HashMap::new();
97+
for (i, share) in shares.iter().enumerate() {
98+
let share_vec = Vec::from(share.as_raw_value());
99+
let mut share_secret_key = [0u8; 32];
100+
share_secret_key.copy_from_slice(&share_vec);
101+
shares_map.insert(i as u64, share_secret_key);
102+
}
103+
104+
Ok(shares_map)
102105
}
103106

104-
fn recover_secret(&self, _shares: HashMap<u64, PrivateKey>) -> Result<PrivateKey, Error> {
105-
unimplemented!()
107+
fn recover_secret(&self, shares: HashMap<u64, PrivateKey>) -> Result<PrivateKey, Error> {
108+
let mut shares_vec = Vec::new();
109+
for (_, share) in shares.iter() {
110+
match SecretKeyShare::<Bls12381G2Impl>::try_from(share.as_slice()) {
111+
Ok(share) => shares_vec.push(share),
112+
Err(_) => return Err(Error::FailedToDeserializeSecretKey),
113+
}
114+
}
115+
let secret_key = SecretKey::<Bls12381G2Impl>::combine(&shares_vec).unwrap();
116+
Ok(secret_key.to_be_bytes())
106117
}
107118

108-
fn aggregate(&self, _signatures: Vec<Signature>) -> Result<Signature, Error> {
109-
unimplemented!()
119+
fn aggregate(&self, signatures: Vec<Signature>) -> Result<Signature, Error> {
120+
let mut signatures_vec = Vec::new();
121+
122+
for signature in signatures {
123+
match BlsSignature::<Bls12381G2Impl>::try_from(signature.as_slice()) {
124+
Ok(signature) => signatures_vec.push(signature),
125+
Err(_) => return Err(Error::FailedToDeserializeSignatureKey),
126+
}
127+
}
128+
129+
let signature = blsful::AggregateSignature::from_signatures(&signatures_vec).unwrap();
130+
131+
let signature_vec = Vec::from(signature);
132+
let mut signature = [0u8; 96];
133+
signature.copy_from_slice(&signature_vec);
134+
Ok(signature)
110135
}
111136

112137
fn threshold_aggregate(
113138
&self,
114-
_partial_signatures_by_idx: HashMap<u64, Signature>,
139+
partial_signatures_by_idx: HashMap<u64, Signature>,
115140
) -> Result<Signature, Error> {
116-
unimplemented!()
141+
let mut partial_signatures_vec = Vec::with_capacity(partial_signatures_by_idx.len());
142+
143+
for (_, signature) in partial_signatures_by_idx.iter() {
144+
match SignatureShare::<Bls12381G2Impl>::try_from(signature.as_slice()) {
145+
Ok(signature) => partial_signatures_vec.push(signature),
146+
Err(_) => return Err(Error::FailedToDeserializeSignatureKey),
147+
}
148+
}
149+
150+
let signature = BlsSignature::from_shares(&partial_signatures_vec)
151+
.map_err(|_| Error::FailedToDeserializeSignatureKey)?;
152+
let signature_vec = Vec::from(signature);
153+
154+
let mut signature = [0u8; 96];
155+
signature.copy_from_slice(&signature_vec);
156+
Ok(signature)
117157
}
118158

119159
fn verify(
120160
&self,
121-
_public_key: &PublicKey,
122-
_data: &[u8],
123-
_raw_signature: &Signature,
161+
public_key: &PublicKey,
162+
data: &[u8],
163+
raw_signature: &Signature,
124164
) -> Result<(), Error> {
125-
unimplemented!()
126-
}
127-
128-
fn sign(&self, _private_key: &PrivateKey, _data: &[u8]) -> Result<Signature, Error> {
129-
unimplemented!()
165+
let public_key = BlsPublicKey::<Bls12381G2Impl>::try_from(public_key.as_slice())
166+
.map_err(|_| Error::FailedToDeserializePublicKey)?;
167+
let signature = BlsSignature::<Bls12381G2Impl>::try_from(raw_signature.as_slice())
168+
.map_err(|_| Error::FailedToDeserializeSignatureKey)?;
169+
signature
170+
.verify(&public_key, data)
171+
.map_err(|_| Error::FailedToVerifySignature)
172+
}
173+
174+
fn sign(&self, private_key: &PrivateKey, data: &[u8]) -> Result<Signature, Error> {
175+
let private_key = SecretKey::<Bls12381G2Impl>::from_be_bytes(private_key);
176+
if private_key.is_none().unwrap_u8() == 1 {
177+
return Err(Error::FailedToDeserializeSecretKey);
178+
}
179+
let private_key = private_key.unwrap();
180+
let signature = private_key
181+
.sign(SignatureSchemes::Basic, data)
182+
.map_err(|_| Error::FailedToGenerateSignature)?;
183+
let signature_vec = Vec::from(signature);
184+
let mut signature = [0u8; 96];
185+
signature.copy_from_slice(&signature_vec);
186+
Ok(signature)
130187
}
131188

132189
fn verify_aggregate(
133190
&self,
134-
_public_keys: Vec<PublicKey>,
135-
_signature: Signature,
136-
_data: &[u8],
191+
public_keys: Vec<PublicKey>,
192+
signature: Signature,
193+
data: &[u8],
137194
) -> Result<(), Error> {
138-
unimplemented!()
195+
let signature = AggregateSignature::try_from(signature.as_slice())
196+
.map_err(|_| Error::FailedToDeserializeSignatureKey)?;
197+
let public_keys = public_keys
198+
.iter()
199+
.map(|public_key| {
200+
BlsPublicKey::<Bls12381G2Impl>::try_from(public_key.as_slice())
201+
.map_err(|_| Error::FailedToDeserializePublicKey)
202+
})
203+
.collect::<Result<Vec<BlsPublicKey<Bls12381G2Impl>>, Error>>()?;
204+
let public_keys = public_keys
205+
.iter()
206+
.map(|public_key| (*public_key, data))
207+
.collect::<Vec<_>>();
208+
signature
209+
.verify(&public_keys)
210+
.map_err(|_| Error::FailedToVerifySignature)
139211
}
140212
}
141213

@@ -151,19 +223,17 @@ impl Herumi {
151223

152224
#[cfg(test)]
153225
mod tests {
154-
use super::*;
226+
use blsful::vsss_rs::elliptic_curve;
155227

156-
#[test]
157-
fn test_generate_secret_key() {
158-
let herumi = Herumi::new();
159-
let sk = herumi.generate_secret_key().unwrap();
160-
println!("{:?}", sk);
161-
}
228+
use super::*;
162229

163230
#[test]
164-
fn test_generate_insecure_secret() {
231+
fn test_secret_to_public_key() {
165232
let herumi = Herumi::new();
166-
let sk = herumi.generate_insecure_secret(&mut rand::rng()).unwrap();
167-
println!("{:?}", sk);
233+
let sk = herumi
234+
.generate_secret_key(&mut elliptic_curve::rand_core::OsRng)
235+
.unwrap();
236+
let pk = herumi.secret_to_public_key(&sk).unwrap();
237+
println!("{:?}", pk);
168238
}
169239
}

0 commit comments

Comments
 (0)