Skip to content

Commit 60964fc

Browse files
authored
Expose blst internals (#6829)
1 parent 01df433 commit 60964fc

File tree

6 files changed

+101
-6
lines changed

6 files changed

+101
-6
lines changed

crypto/bls/src/generic_secret_key.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ where
6161
GenericPublicKey::from_point(self.point.public_key())
6262
}
6363

64+
/// Returns a reference to the underlying BLS point.
65+
pub fn point(&self) -> &Sec {
66+
&self.point
67+
}
68+
6469
/// Serialize `self` as compressed bytes.
6570
///
6671
/// ## Note
@@ -89,3 +94,20 @@ where
8994
}
9095
}
9196
}
97+
98+
impl<Sig, Pub, Sec> GenericSecretKey<Sig, Pub, Sec>
99+
where
100+
Sig: TSignature<Pub>,
101+
Pub: TPublicKey,
102+
Sec: TSecretKey<Sig, Pub> + Clone,
103+
{
104+
/// Instantiates `Self` from a `point`.
105+
/// Takes a reference, as moves might accidentally leave behind key material
106+
pub fn from_point(point: &Sec) -> Self {
107+
Self {
108+
point: point.clone(),
109+
_phantom_signature: PhantomData,
110+
_phantom_public_key: PhantomData,
111+
}
112+
}
113+
}

crypto/bls/src/generic_signature.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ use tree_hash::TreeHash;
1414
/// The byte-length of a BLS signature when serialized in compressed form.
1515
pub const SIGNATURE_BYTES_LEN: usize = 96;
1616

17+
/// The byte-length of a BLS signature when serialized in uncompressed form.
18+
pub const SIGNATURE_UNCOMPRESSED_BYTES_LEN: usize = 192;
19+
1720
/// Represents the signature at infinity.
1821
pub const INFINITY_SIGNATURE: [u8; SIGNATURE_BYTES_LEN] = [
1922
0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -22,6 +25,16 @@ pub const INFINITY_SIGNATURE: [u8; SIGNATURE_BYTES_LEN] = [
2225
0,
2326
];
2427

28+
pub const INFINITY_SIGNATURE_UNCOMPRESSED: [u8; SIGNATURE_UNCOMPRESSED_BYTES_LEN] = [
29+
0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35+
0,
36+
];
37+
2538
/// The compressed bytes used to represent `GenericSignature::empty()`.
2639
pub const NONE_SIGNATURE: [u8; SIGNATURE_BYTES_LEN] = [0; SIGNATURE_BYTES_LEN];
2740

@@ -31,9 +44,15 @@ pub trait TSignature<GenericPublicKey>: Sized + Clone {
3144
/// Serialize `self` as compressed bytes.
3245
fn serialize(&self) -> [u8; SIGNATURE_BYTES_LEN];
3346

47+
/// Serialize `self` as uncompressed bytes.
48+
fn serialize_uncompressed(&self) -> [u8; SIGNATURE_UNCOMPRESSED_BYTES_LEN];
49+
3450
/// Deserialize `self` from compressed bytes.
3551
fn deserialize(bytes: &[u8]) -> Result<Self, Error>;
3652

53+
/// Serialize `self` from uncompressed bytes.
54+
fn deserialize_uncompressed(bytes: &[u8]) -> Result<Self, Error>;
55+
3756
/// Returns `true` if `self` is a signature across `msg` by `pubkey`.
3857
fn verify(&self, pubkey: &GenericPublicKey, msg: Hash256) -> bool;
3958
}
@@ -93,12 +112,12 @@ where
93112
}
94113

95114
/// Returns a reference to the underlying BLS point.
96-
pub(crate) fn point(&self) -> Option<&Sig> {
115+
pub fn point(&self) -> Option<&Sig> {
97116
self.point.as_ref()
98117
}
99118

100119
/// Instantiates `Self` from a `point`.
101-
pub(crate) fn from_point(point: Sig, is_infinity: bool) -> Self {
120+
pub fn from_point(point: Sig, is_infinity: bool) -> Self {
102121
Self {
103122
point: Some(point),
104123
is_infinity,
@@ -115,6 +134,13 @@ where
115134
}
116135
}
117136

137+
/// Serialize `self` as compressed bytes.
138+
pub fn serialize_uncompressed(&self) -> Option<[u8; SIGNATURE_UNCOMPRESSED_BYTES_LEN]> {
139+
self.point
140+
.as_ref()
141+
.map(|point| point.serialize_uncompressed())
142+
}
143+
118144
/// Deserialize `self` from compressed bytes.
119145
pub fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
120146
let point = if bytes == &NONE_SIGNATURE[..] {
@@ -129,6 +155,17 @@ where
129155
_phantom: PhantomData,
130156
})
131157
}
158+
159+
/// Deserialize `self` from uncompressed bytes.
160+
pub fn deserialize_uncompressed(bytes: &[u8]) -> Result<Self, Error> {
161+
// The "none signature" is a beacon chain concept. As we never directly deal with
162+
// uncompressed signatures on the beacon chain, it does not apply here.
163+
Ok(Self {
164+
point: Some(Sig::deserialize_uncompressed(bytes)?),
165+
is_infinity: bytes == &INFINITY_SIGNATURE_UNCOMPRESSED[..],
166+
_phantom: PhantomData,
167+
})
168+
}
132169
}
133170

134171
impl<Pub, Sig> GenericSignature<Pub, Sig>

crypto/bls/src/impls/blst.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
GenericPublicKey, TPublicKey, PUBLIC_KEY_BYTES_LEN, PUBLIC_KEY_UNCOMPRESSED_BYTES_LEN,
66
},
77
generic_secret_key::TSecretKey,
8-
generic_signature::{TSignature, SIGNATURE_BYTES_LEN},
8+
generic_signature::{TSignature, SIGNATURE_BYTES_LEN, SIGNATURE_UNCOMPRESSED_BYTES_LEN},
99
BlstError, Error, Hash256, ZeroizeHash, INFINITY_SIGNATURE,
1010
};
1111
pub use blst::min_pk as blst_core;
@@ -189,10 +189,18 @@ impl TSignature<blst_core::PublicKey> for blst_core::Signature {
189189
self.to_bytes()
190190
}
191191

192+
fn serialize_uncompressed(&self) -> [u8; SIGNATURE_UNCOMPRESSED_BYTES_LEN] {
193+
self.serialize()
194+
}
195+
192196
fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
193197
Self::from_bytes(bytes).map_err(Into::into)
194198
}
195199

200+
fn deserialize_uncompressed(bytes: &[u8]) -> Result<Self, Error> {
201+
Self::deserialize(bytes).map_err(Into::into)
202+
}
203+
196204
fn verify(&self, pubkey: &blst_core::PublicKey, msg: Hash256) -> bool {
197205
// Public keys have already been checked for subgroup and infinity
198206
// Check Signature inside function for subgroup

crypto/bls/src/impls/fake_crypto.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
GenericPublicKey, TPublicKey, PUBLIC_KEY_BYTES_LEN, PUBLIC_KEY_UNCOMPRESSED_BYTES_LEN,
66
},
77
generic_secret_key::{TSecretKey, SECRET_KEY_BYTES_LEN},
8-
generic_signature::{TSignature, SIGNATURE_BYTES_LEN},
8+
generic_signature::{TSignature, SIGNATURE_BYTES_LEN, SIGNATURE_UNCOMPRESSED_BYTES_LEN},
99
Error, Hash256, ZeroizeHash, INFINITY_PUBLIC_KEY, INFINITY_SIGNATURE,
1010
};
1111

@@ -106,12 +106,22 @@ impl TSignature<PublicKey> for Signature {
106106
self.0
107107
}
108108

109+
fn serialize_uncompressed(&self) -> [u8; SIGNATURE_UNCOMPRESSED_BYTES_LEN] {
110+
let mut ret = [0; SIGNATURE_UNCOMPRESSED_BYTES_LEN];
111+
ret[0..SIGNATURE_BYTES_LEN].copy_from_slice(&self.0);
112+
ret
113+
}
114+
109115
fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
110116
let mut signature = Self::infinity();
111117
signature.0[..].copy_from_slice(&bytes[0..SIGNATURE_BYTES_LEN]);
112118
Ok(signature)
113119
}
114120

121+
fn deserialize_uncompressed(bytes: &[u8]) -> Result<Self, Error> {
122+
Self::deserialize(bytes)
123+
}
124+
115125
fn verify(&self, _pubkey: &PublicKey, _msg: Hash256) -> bool {
116126
true
117127
}

crypto/bls/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ pub use generic_public_key::{
3737
INFINITY_PUBLIC_KEY, PUBLIC_KEY_BYTES_LEN, PUBLIC_KEY_UNCOMPRESSED_BYTES_LEN,
3838
};
3939
pub use generic_secret_key::SECRET_KEY_BYTES_LEN;
40-
pub use generic_signature::{INFINITY_SIGNATURE, SIGNATURE_BYTES_LEN};
40+
pub use generic_signature::{
41+
INFINITY_SIGNATURE, INFINITY_SIGNATURE_UNCOMPRESSED, SIGNATURE_BYTES_LEN,
42+
SIGNATURE_UNCOMPRESSED_BYTES_LEN,
43+
};
4144
pub use get_withdrawal_credentials::get_withdrawal_credentials;
4245
pub use zeroize_hash::ZeroizeHash;
4346

crypto/bls/tests/tests.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use bls::{FixedBytesExtended, Hash256, INFINITY_SIGNATURE, SECRET_KEY_BYTES_LEN};
1+
use bls::{
2+
FixedBytesExtended, Hash256, INFINITY_SIGNATURE, INFINITY_SIGNATURE_UNCOMPRESSED,
3+
SECRET_KEY_BYTES_LEN,
4+
};
25
use ssz::{Decode, Encode};
36
use std::borrow::Cow;
47
use std::fmt::Debug;
@@ -37,6 +40,18 @@ macro_rules! test_suite {
3740
assert!(AggregateSignature::infinity().is_infinity());
3841
}
3942

43+
#[test]
44+
fn infinity_sig_serializations_match() {
45+
let sig = Signature::deserialize(&INFINITY_SIGNATURE).unwrap();
46+
assert_eq!(
47+
sig.serialize_uncompressed().unwrap(),
48+
INFINITY_SIGNATURE_UNCOMPRESSED
49+
);
50+
let sig =
51+
Signature::deserialize_uncompressed(&INFINITY_SIGNATURE_UNCOMPRESSED).unwrap();
52+
assert_eq!(sig.serialize(), INFINITY_SIGNATURE);
53+
}
54+
4055
#[test]
4156
fn ssz_round_trip_multiple_types() {
4257
let mut agg_sig = AggregateSignature::infinity();

0 commit comments

Comments
 (0)