Skip to content

Commit 015c4cb

Browse files
committed
perf(crypto): CRP-1559 Use affine points in multi_sig
1 parent 955ccb9 commit 015c4cb

File tree

5 files changed

+42
-47
lines changed

5 files changed

+42
-47
lines changed

rs/crypto/internal/crypto_lib/bls12_381/type/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,6 +1302,15 @@ macro_rules! define_affine_and_projective_types {
13021302
let v = scalars.clone().map(|s| self * s);
13031303
$projective::batch_normalize_array(&v)
13041304
}
1305+
1306+
/// Sum some points
1307+
pub fn sum(pts: &[Self]) -> $projective {
1308+
let mut sum = ic_bls12_381::$projective::identity();
1309+
for pt in pts {
1310+
sum += pt.inner();
1311+
}
1312+
$projective::new(sum)
1313+
}
13051314
}
13061315

13071316
paste! {

rs/crypto/internal/crypto_lib/multi_sig/bls12_381/src/crypto.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::types::{
77
};
88

99
use ic_crypto_internal_bls12_381_type::{
10-
G1Projective, G2Affine, G2Projective, Scalar, verify_bls_signature,
10+
G1Affine, G1Projective, G2Affine, Scalar, verify_bls_signature,
1111
};
1212

1313
use ic_crypto_sha2::DomainSeparationContext;
@@ -56,12 +56,12 @@ pub fn keypair_from_seed(seed: [u64; 4]) -> (SecretKey, PublicKey) {
5656

5757
pub fn keypair_from_rng<R: Rng + CryptoRng>(rng: &mut R) -> (SecretKey, PublicKey) {
5858
let secret_key = Scalar::random(rng);
59-
let public_key = G2Affine::generator() * &secret_key;
59+
let public_key = (G2Affine::generator() * &secret_key).to_affine();
6060
(secret_key, public_key)
6161
}
6262

6363
pub fn sign_point(point: &G1Projective, secret_key: &SecretKey) -> IndividualSignature {
64-
point * secret_key
64+
(point * secret_key).to_affine()
6565
}
6666
pub fn sign_message(message: &[u8], secret_key: &SecretKey) -> IndividualSignature {
6767
sign_point(&hash_message_to_g1(message), secret_key)
@@ -80,22 +80,23 @@ pub fn create_pop(public_key: &PublicKey, secret_key: &SecretKey) -> Pop {
8080
}
8181

8282
pub fn combine_signatures(signatures: &[IndividualSignature]) -> CombinedSignature {
83-
G1Projective::sum(signatures)
83+
G1Affine::sum(signatures).to_affine()
8484
}
8585
pub fn combine_public_keys(public_keys: &[PublicKey]) -> CombinedPublicKey {
86-
G2Projective::sum(public_keys)
86+
G2Affine::sum(public_keys).to_affine()
8787
}
8888

89-
pub fn verify_point(hash: &G1Projective, signature: &G1Projective, public_key: &PublicKey) -> bool {
90-
verify_bls_signature(&signature.into(), &public_key.into(), &hash.into())
89+
pub fn verify_point(hash: &G1Affine, signature: &G1Affine, public_key: &PublicKey) -> bool {
90+
verify_bls_signature(signature, public_key, hash)
9191
}
92+
9293
pub fn verify_individual_message_signature(
9394
message: &[u8],
9495
signature: &IndividualSignature,
9596
public_key: &PublicKey,
9697
) -> bool {
9798
let hash = hash_message_to_g1(message);
98-
verify_point(&hash, signature, public_key)
99+
verify_point(&hash.to_affine(), signature, public_key)
99100
}
100101
pub fn verify_pop(pop: &Pop, public_key: &PublicKey) -> bool {
101102
let public_key_bytes = PublicKeyBytes::from(public_key);
@@ -104,7 +105,7 @@ pub fn verify_pop(pop: &Pop, public_key: &PublicKey) -> bool {
104105
.extend(DomainSeparationContext::new(DOMAIN_MULTI_SIG_BLS12_381_POP).as_bytes());
105106
domain_separated_public_key.extend(&public_key_bytes.0[..]);
106107
let hash = hash_public_key_to_g1(&domain_separated_public_key);
107-
verify_point(&hash, pop, public_key)
108+
verify_point(&hash.to_affine(), pop, public_key)
108109
}
109110

110111
pub fn verify_combined_message_signature(
@@ -114,5 +115,5 @@ pub fn verify_combined_message_signature(
114115
) -> bool {
115116
let hash = hash_message_to_g1(message);
116117
let public_key = combine_public_keys(public_keys);
117-
verify_point(&hash, signature, &public_key)
118+
verify_point(&hash.to_affine(), signature, &public_key)
118119
}

rs/crypto/internal/crypto_lib/multi_sig/bls12_381/src/tests.rs

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,8 @@ use crate::{
55
types::IndividualSignature, types::PublicKey, types::SecretKey, types::SecretKeyBytes,
66
types::arbitrary,
77
};
8-
use ic_crypto_internal_bls12_381_type::G1Projective;
98
use ic_crypto_test_utils_reproducible_rng::reproducible_rng;
109

11-
fn check_single_point_signature_verifies(
12-
secret_key: &SecretKey,
13-
public_key: &PublicKey,
14-
point: &G1Projective,
15-
) {
16-
let signature = multi_crypto::sign_point(point, secret_key);
17-
assert!(multi_crypto::verify_point(point, &signature, public_key));
18-
}
19-
20-
fn check_individual_multi_signature_contribution_verifies(
21-
secret_key: &SecretKey,
22-
public_key: &PublicKey,
23-
message: &[u8],
24-
) {
25-
let signature = multi_crypto::sign_message(message, secret_key);
26-
assert!(multi_crypto::verify_individual_message_signature(
27-
message, &signature, public_key
28-
));
29-
}
30-
3110
fn check_multi_signature_verifies(keys: &[(SecretKey, PublicKey)], message: &[u8]) {
3211
let signatures: Vec<IndividualSignature> = keys
3312
.iter()
@@ -177,14 +156,20 @@ mod advanced_functionality {
177156
fn single_point_signature_verifies() {
178157
let (secret_key, public_key) = multi_crypto::keypair_from_seed([1, 2, 3, 4]);
179158
let point = multi_crypto::hash_message_to_g1(b"abba");
180-
check_single_point_signature_verifies(&secret_key, &public_key, &point);
159+
let signature = multi_crypto::sign_point(&point, &secret_key);
160+
assert!(multi_crypto::verify_point(&point.to_affine(), &signature, &public_key));
181161
}
182162

183163
#[test]
184164
fn individual_multi_signature_contribution_verifies() {
185165
let (secret_key, public_key) = multi_crypto::keypair_from_seed([1, 2, 3, 4]);
186-
check_individual_multi_signature_contribution_verifies(&secret_key, &public_key, b"abba");
166+
let message = b"bjork";
167+
let signature = multi_crypto::sign_message(message, &secret_key);
168+
assert!(multi_crypto::verify_individual_message_signature(
169+
message, &signature, &public_key
170+
));
187171
}
172+
188173
#[test]
189174
fn pop_verifies() {
190175
let (secret_key, public_key) = multi_crypto::keypair_from_seed([1, 2, 3, 4]);

rs/crypto/internal/crypto_lib/multi_sig/bls12_381/src/types.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! BLS12-381 multisignature types.
22
#![allow(clippy::unit_arg)] // Arbitrary is a unit arg in: derive(proptest_derive::Arbitrary)
3-
use ic_crypto_internal_bls12_381_type::{G1Projective, G2Projective, Scalar};
3+
use ic_crypto_internal_bls12_381_type::{G1Affine, G2Affine, Scalar};
44
use ic_crypto_secrets_containers::SecretArray;
55
use serde::{Deserialize, Serialize};
66
use zeroize::{Zeroize, ZeroizeOnDrop};
@@ -15,20 +15,20 @@ mod generic_traits;
1515
pub type SecretKey = Scalar;
1616

1717
/// A BLS public key is a curve point in the G2 group.
18-
pub type PublicKey = G2Projective;
18+
pub type PublicKey = G2Affine;
1919

2020
/// A BLS combined public key is a curve point in the G2 group.
21-
pub type CombinedPublicKey = G2Projective;
21+
pub type CombinedPublicKey = G2Affine;
2222

2323
/// A BLS signature is a curve point in the G1 group.
24-
pub type IndividualSignature = G1Projective;
24+
pub type IndividualSignature = G1Affine;
2525

2626
/// A BLS Proof of Possession is a curve point in the G1 group (a
2727
/// domain-separated signature on the public key).
28-
pub type Pop = G1Projective;
28+
pub type Pop = G1Affine;
2929

3030
/// A BLS multisignature is a curve point in the G1 group.
31-
pub type CombinedSignature = G1Projective;
31+
pub type CombinedSignature = G1Affine;
3232

3333
/// Wrapper for a serialized secret key.
3434
#[derive(Clone, Eq, PartialEq, Deserialize, Serialize, Zeroize, ZeroizeOnDrop)]
@@ -46,29 +46,29 @@ impl SecretKeyBytes {
4646
pub struct IndividualSignatureBytes(pub [u8; IndividualSignatureBytes::SIZE]);
4747
ic_crypto_internal_types::derive_serde!(IndividualSignatureBytes, IndividualSignatureBytes::SIZE);
4848
impl IndividualSignatureBytes {
49-
pub const SIZE: usize = G1Projective::BYTES;
49+
pub const SIZE: usize = G1Affine::BYTES;
5050
}
5151

5252
/// Wrapper for a serialized proof of possession.
5353
#[derive(Copy, Clone)]
5454
pub struct PopBytes(pub [u8; PopBytes::SIZE]);
5555
ic_crypto_internal_types::derive_serde!(PopBytes, PopBytes::SIZE);
5656
impl PopBytes {
57-
pub const SIZE: usize = G1Projective::BYTES;
57+
pub const SIZE: usize = G1Affine::BYTES;
5858
}
5959

6060
/// Wrapper for a serialized combined signature.
6161
#[derive(Copy, Clone)]
6262
pub struct CombinedSignatureBytes(pub [u8; CombinedSignatureBytes::SIZE]);
6363
ic_crypto_internal_types::derive_serde!(CombinedSignatureBytes, CombinedSignatureBytes::SIZE);
6464
impl CombinedSignatureBytes {
65-
pub const SIZE: usize = G1Projective::BYTES;
65+
pub const SIZE: usize = G1Affine::BYTES;
6666
}
6767

6868
/// Wrapper for a serialized public key.
6969
#[derive(Copy, Clone)]
7070
pub struct PublicKeyBytes(pub [u8; PublicKeyBytes::SIZE]);
7171
ic_crypto_internal_types::derive_serde!(PublicKeyBytes, PublicKeyBytes::SIZE);
7272
impl PublicKeyBytes {
73-
pub const SIZE: usize = G2Projective::BYTES;
73+
pub const SIZE: usize = G2Affine::BYTES;
7474
}

rs/crypto/internal/crypto_lib/multi_sig/bls12_381/src/types/conversions.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ impl TryFrom<&PublicKeyBytes> for PublicKey {
2626
type Error = CryptoError;
2727

2828
fn try_from(public_key_bytes: &PublicKeyBytes) -> Result<Self, Self::Error> {
29-
G2Projective::deserialize(&public_key_bytes.0).map_err(|_| {
29+
G2Affine::deserialize(&public_key_bytes.0).map_err(|_| {
3030
CryptoError::MalformedPublicKey {
3131
algorithm: AlgorithmId::MultiBls12_381,
3232
key_bytes: Some(public_key_bytes.0.to_vec()),
@@ -44,7 +44,7 @@ impl From<&PublicKey> for PublicKeyBytes {
4444
impl TryFrom<&IndividualSignatureBytes> for IndividualSignature {
4545
type Error = CryptoError;
4646
fn try_from(signature: &IndividualSignatureBytes) -> Result<Self, Self::Error> {
47-
G1Projective::deserialize(&signature.0).map_err(|_| CryptoError::MalformedSignature {
47+
G1Affine::deserialize(&signature.0).map_err(|_| CryptoError::MalformedSignature {
4848
algorithm: AlgorithmId::MultiBls12_381,
4949
sig_bytes: signature.0.to_vec(),
5050
internal_error: "Point decoding failed".to_string(),
@@ -62,7 +62,7 @@ impl TryFrom<&PopBytes> for Pop {
6262
type Error = CryptoError;
6363

6464
fn try_from(pop_bytes: &PopBytes) -> Result<Self, Self::Error> {
65-
G1Projective::deserialize(&pop_bytes.0).map_err(|_| CryptoError::MalformedPop {
65+
G1Affine::deserialize(&pop_bytes.0).map_err(|_| CryptoError::MalformedPop {
6666
algorithm: AlgorithmId::MultiBls12_381,
6767
pop_bytes: pop_bytes.0.to_vec(),
6868
internal_error: "Point decoding failed".to_string(),
@@ -78,7 +78,7 @@ impl From<&Pop> for PopBytes {
7878
impl TryFrom<&CombinedSignatureBytes> for CombinedSignature {
7979
type Error = CryptoError;
8080
fn try_from(signature: &CombinedSignatureBytes) -> Result<Self, Self::Error> {
81-
G1Projective::deserialize(&signature.0).map_err(|_| CryptoError::MalformedSignature {
81+
G1Affine::deserialize(&signature.0).map_err(|_| CryptoError::MalformedSignature {
8282
algorithm: AlgorithmId::MultiBls12_381,
8383
sig_bytes: signature.0.to_vec(),
8484
internal_error: "Point decoding failed".to_string(),

0 commit comments

Comments
 (0)