Skip to content

Commit c8f16b9

Browse files
authored
Merge pull request #2322 from input-output-hk/curiecrypt/fix-bls-bindings
Fix BLST bindings: Error handling for infinite values of sigs and vks
2 parents 62ae79e + d0d7787 commit c8f16b9

File tree

5 files changed

+122
-30
lines changed

5 files changed

+122
-30
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mithril-stm/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-stm"
3-
version = "0.3.38"
3+
version = "0.3.39"
44
edition = { workspace = true }
55
authors = { workspace = true }
66
homepage = { workspace = true }

mithril-stm/src/error.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ pub enum MultiSignatureError {
2929
/// At least one signature in the batch is invalid
3030
#[error("One signature in the batch is invalid")]
3131
BatchInvalid,
32+
33+
/// Single signature is the infinity
34+
#[error("Single signature is the infinity")]
35+
SignatureInfinity(Signature),
36+
37+
/// Verification key is the infinity
38+
#[error("Verification key is the infinity")]
39+
VerificationKeyInfinity(Box<VerificationKey>),
3240
}
3341

3442
/// Errors which can be output by Mithril single signature verification.
@@ -138,6 +146,10 @@ pub enum RegisterError {
138146
#[error("This key has already been registered.")]
139147
KeyRegistered(Box<VerificationKey>),
140148

149+
/// Verification key is the infinity
150+
#[error("Verification key is the infinity")]
151+
VerificationKeyInfinity(Box<VerificationKey>),
152+
141153
/// The supplied key is not valid
142154
#[error("The verification of correctness of the supplied key is invalid.")]
143155
KeyInvalid(Box<VerificationKeyPoP>),
@@ -159,6 +171,8 @@ impl From<MultiSignatureError> for StmSignatureError {
159171
MultiSignatureError::BatchInvalid => unreachable!(),
160172
MultiSignatureError::KeyInvalid(_) => unreachable!(),
161173
MultiSignatureError::AggregateSignatureInvalid => unreachable!(),
174+
MultiSignatureError::SignatureInfinity(_) => unreachable!(),
175+
MultiSignatureError::VerificationKeyInfinity(_) => unreachable!(),
162176
}
163177
}
164178
}
@@ -194,6 +208,12 @@ impl<D: Digest + FixedOutput> From<MultiSignatureError> for StmAggregateSignatur
194208
MultiSignatureError::SignatureInvalid(_) => {
195209
Self::CoreVerificationError(CoreVerifierError::from(e))
196210
}
211+
MultiSignatureError::SignatureInfinity(_) => {
212+
Self::CoreVerificationError(CoreVerifierError::from(e))
213+
}
214+
MultiSignatureError::VerificationKeyInfinity(_) => {
215+
Self::CoreVerificationError(CoreVerifierError::from(e))
216+
}
197217
}
198218
}
199219
}
@@ -230,6 +250,8 @@ impl From<MultiSignatureError> for CoreVerifierError {
230250
MultiSignatureError::SerializationError => unreachable!(),
231251
MultiSignatureError::KeyInvalid(_) => unreachable!(),
232252
MultiSignatureError::SignatureInvalid(_e) => unreachable!(),
253+
MultiSignatureError::SignatureInfinity(_) => unreachable!(),
254+
MultiSignatureError::VerificationKeyInfinity(_) => unreachable!(),
233255
}
234256
}
235257
}
@@ -245,6 +267,7 @@ impl From<MultiSignatureError> for RegisterError {
245267
match e {
246268
MultiSignatureError::SerializationError => Self::SerializationError,
247269
MultiSignatureError::KeyInvalid(e) => Self::KeyInvalid(e),
270+
MultiSignatureError::VerificationKeyInfinity(e) => Self::VerificationKeyInfinity(e),
248271
_ => unreachable!(),
249272
}
250273
}
@@ -255,9 +278,19 @@ impl From<MultiSignatureError> for RegisterError {
255278
pub(crate) fn blst_err_to_mithril(
256279
e: BLST_ERROR,
257280
sig: Option<Signature>,
281+
key: Option<VerificationKey>,
258282
) -> Result<(), MultiSignatureError> {
259283
match e {
260284
BLST_ERROR::BLST_SUCCESS => Ok(()),
285+
BLST_ERROR::BLST_PK_IS_INFINITY => {
286+
if let Some(s) = sig {
287+
return Err(MultiSignatureError::SignatureInfinity(s));
288+
}
289+
if let Some(vk) = key {
290+
return Err(MultiSignatureError::VerificationKeyInfinity(Box::new(vk)));
291+
}
292+
Err(MultiSignatureError::SerializationError)
293+
}
261294
BLST_ERROR::BLST_VERIFY_FAIL => {
262295
if let Some(s) = sig {
263296
Err(MultiSignatureError::SignatureInvalid(s))

mithril-stm/src/key_reg.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,9 @@ impl KeyReg {
4242
/// The function fails when the proof of possession is invalid or when the key is already registered.
4343
pub fn register(&mut self, stake: Stake, pk: VerificationKeyPoP) -> Result<(), RegisterError> {
4444
if let Entry::Vacant(e) = self.keys.entry(pk.vk) {
45-
if pk.check().is_ok() {
46-
e.insert(stake);
47-
return Ok(());
48-
} else {
49-
return Err(RegisterError::KeyInvalid(Box::new(pk)));
50-
}
45+
pk.check()?;
46+
e.insert(stake);
47+
return Ok(());
5148
}
5249
Err(RegisterError::KeyRegistered(Box::new(pk.vk)))
5350
}

mithril-stm/src/multi_sig.rs

Lines changed: 84 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ impl SigningKey {
8888
pub fn from_bytes(bytes: &[u8]) -> Result<Self, MultiSignatureError> {
8989
match BlstSk::from_bytes(&bytes[..32]) {
9090
Ok(sk) => Ok(Self(sk)),
91-
Err(e) => Err(blst_err_to_mithril(e, None)
91+
Err(e) => Err(blst_err_to_mithril(e, None, None)
9292
.expect_err("If deserialization is not successful, blst returns and error different to SUCCESS."))
9393
}
9494
}
@@ -108,7 +108,7 @@ impl VerificationKey {
108108
pub fn from_bytes(bytes: &[u8]) -> Result<Self, MultiSignatureError> {
109109
match BlstVk::key_validate(&bytes[..96]) {
110110
Ok(vk) => Ok(Self(vk)),
111-
Err(e) => Err(blst_err_to_mithril(e, None)
111+
Err(e) => Err(blst_err_to_mithril(e, None, None)
112112
.expect_err("If deserialization is not successful, blst returns and error different to SUCCESS."))
113113
}
114114
}
@@ -196,15 +196,19 @@ impl VerificationKeyPoP {
196196
// If we are really looking for performance improvements, we can combine the
197197
// two final exponentiations (for verifying k1 and k2) into a single one.
198198
pub fn check(&self) -> Result<(), MultiSignatureError> {
199-
let result = verify_pairing(&self.vk, &self.pop);
200-
201-
if !(self.pop.k1.verify(false, POP, &[], &[], &self.vk.0, false)
202-
== BLST_ERROR::BLST_SUCCESS
203-
&& result)
204-
{
205-
return Err(MultiSignatureError::KeyInvalid(Box::new(*self)));
199+
match self.vk.0.validate() {
200+
Ok(_) => {
201+
let result = verify_pairing(&self.vk, &self.pop);
202+
if !(self.pop.k1.verify(false, POP, &[], &[], &self.vk.0, false)
203+
== BLST_ERROR::BLST_SUCCESS
204+
&& result)
205+
{
206+
return Err(MultiSignatureError::KeyInvalid(Box::new(*self)));
207+
}
208+
Ok(())
209+
}
210+
Err(e) => blst_err_to_mithril(e, None, Some(self.vk)),
206211
}
207-
Ok(())
208212
}
209213

210214
/// Convert to a 144 byte string.
@@ -261,7 +265,7 @@ impl ProofOfPossession {
261265
let k1 = match BlstSig::from_bytes(&bytes[..48]) {
262266
Ok(key) => key,
263267
Err(e) => {
264-
return Err(blst_err_to_mithril(e, None)
268+
return Err(blst_err_to_mithril(e, None, None)
265269
.expect_err("If it passed, blst returns and error different to SUCCESS."))
266270
}
267271
};
@@ -288,8 +292,12 @@ impl Signature {
288292
/// Verify a signature against a verification key.
289293
pub fn verify(&self, msg: &[u8], mvk: &VerificationKey) -> Result<(), MultiSignatureError> {
290294
blst_err_to_mithril(
291-
self.0.verify(false, msg, &[], &[], &mvk.0, false),
295+
self.0.validate(true).map_or_else(
296+
|e| e,
297+
|_| self.0.verify(false, msg, &[], &[], &mvk.0, false),
298+
),
292299
Some(*self),
300+
None,
293301
)
294302
}
295303

@@ -323,7 +331,7 @@ impl Signature {
323331
pub fn from_bytes(bytes: &[u8]) -> Result<Self, MultiSignatureError> {
324332
match BlstSig::sig_validate(&bytes[..48], true) {
325333
Ok(sig) => Ok(Self(sig)),
326-
Err(e) => Err(blst_err_to_mithril(e, None)
334+
Err(e) => Err(blst_err_to_mithril(e, None, None)
327335
.expect_err("If deserialization is not successful, blst returns and error different to SUCCESS."))
328336
}
329337
}
@@ -376,7 +384,6 @@ impl Signature {
376384
}
377385

378386
let transmuted_vks: Vec<blst_p2> = vks.iter().map(vk_from_p2_affine).collect();
379-
380387
let transmuted_sigs: Vec<blst_p1> = signatures.iter().map(sig_to_p1).collect();
381388

382389
let grouped_vks = p2_affines::from(transmuted_vks.as_slice());
@@ -400,6 +407,7 @@ impl Signature {
400407
blst_err_to_mithril(
401408
aggr_sig.0.verify(false, msg, &[], &[], &aggr_vk.0, false),
402409
Some(aggr_sig),
410+
None,
403411
)
404412
}
405413

@@ -415,7 +423,7 @@ impl Signature {
415423
false,
416424
) {
417425
Ok(sig) => BlstSig::from_aggregate(&sig),
418-
Err(e) => return blst_err_to_mithril(e, None),
426+
Err(e) => return blst_err_to_mithril(e, None, None),
419427
};
420428

421429
let p2_vks: Vec<&BlstVk> = vks.iter().map(|vk| &vk.0).collect();
@@ -427,6 +435,7 @@ impl Signature {
427435
blst_err_to_mithril(
428436
batched_sig.aggregate_verify(false, &slice_msgs, &[], &p2_vks, false),
429437
None,
438+
None,
430439
)
431440
.map_err(|_| MultiSignatureError::BatchInvalid)
432441
}
@@ -628,6 +637,8 @@ mod unsafe_helpers {
628637
#[cfg(test)]
629638
mod tests {
630639
use super::*;
640+
use crate::error::RegisterError;
641+
use crate::key_reg::KeyReg;
631642
use proptest::prelude::*;
632643
use rand_chacha::ChaCha20Rng;
633644
use rand_core::{OsRng, SeedableRng};
@@ -643,19 +654,68 @@ mod tests {
643654
let sk = SigningKey::gen(&mut ChaCha20Rng::from_seed(seed));
644655
let vk = VerificationKey::from(&sk);
645656
let sig = sk.sign(&msg);
646-
assert!(sig.verify(&msg, &vk).is_ok());
657+
658+
sig.verify(&msg, &vk).unwrap();
647659
}
648660

649661
#[test]
650-
fn test_invalid_sig(msg in prop::collection::vec(any::<u8>(), 1..128),
651-
seed in any::<[u8;32]>(),
652-
) {
662+
fn test_invalid_sig(msg in prop::collection::vec(any::<u8>(), 1..128), seed in any::<[u8;32]>()) {
653663
let mut rng = ChaCha20Rng::from_seed(seed);
654664
let sk1 = SigningKey::gen(&mut rng);
655665
let vk1 = VerificationKey::from(&sk1);
656666
let sk2 = SigningKey::gen(&mut rng);
657667
let fake_sig = sk2.sign(&msg);
658-
assert!(fake_sig.verify(&msg, &vk1).is_err());
668+
669+
let result = fake_sig.verify(&msg, &vk1);
670+
assert_eq!(result, Err(MultiSignatureError::SignatureInvalid(fake_sig)));
671+
}
672+
673+
#[test]
674+
fn test_infinity_sig(msg in prop::collection::vec(any::<u8>(), 1..128), seed in any::<[u8;32]>()) {
675+
let mut rng = ChaCha20Rng::from_seed(seed);
676+
let sk = SigningKey::gen(&mut rng);
677+
let vk = VerificationKey::from(&sk);
678+
679+
let p1 = blst_p1::default();
680+
let sig_infinity = Signature(p1_affine_to_sig(&p1));
681+
682+
let result = sig_infinity.verify(&msg, &vk);
683+
assert_eq!(result, Err(MultiSignatureError::SignatureInfinity(sig_infinity)));
684+
}
685+
686+
#[test]
687+
fn test_infinity_vk(seed in any::<[u8;32]>()) {
688+
let mut rng = ChaCha20Rng::from_seed(seed);
689+
let sk = SigningKey::gen(&mut rng);
690+
let pop = ProofOfPossession::from(&sk);
691+
692+
let p2 = blst_p2::default();
693+
let vk_infinity = VerificationKey(p2_affine_to_vk(&p2));
694+
let vkpop_infinity = VerificationKeyPoP { vk: vk_infinity, pop };
695+
696+
let result = vkpop_infinity.check();
697+
assert_eq!(result, Err(MultiSignatureError::VerificationKeyInfinity(Box::new(vkpop_infinity.vk))));
698+
}
699+
700+
#[test]
701+
fn test_keyreg_with_infinity_vk(num_sigs in 2..16usize, seed in any::<[u8;32]>()) {
702+
let mut rng = ChaCha20Rng::from_seed(seed);
703+
let mut kr = KeyReg::init();
704+
705+
let sk = SigningKey::gen(&mut rng);
706+
let pop = ProofOfPossession::from(&sk);
707+
let p2 = blst_p2::default();
708+
let vk_infinity = VerificationKey(p2_affine_to_vk(&p2));
709+
let vkpop_infinity = VerificationKeyPoP { vk: vk_infinity, pop };
710+
711+
for _ in 0..num_sigs {
712+
let sk = SigningKey::gen(&mut rng);
713+
let vkpop = VerificationKeyPoP::from(&sk);
714+
let _ = kr.register(1, vkpop);
715+
}
716+
717+
let result = kr.register(1, vkpop_infinity);
718+
assert_eq!(result, Err(RegisterError::VerificationKeyInfinity(Box::new(vkpop_infinity.vk))));
659719
}
660720

661721
#[test]
@@ -675,7 +735,8 @@ mod tests {
675735
mvks.push(vk);
676736
}
677737

678-
assert!(Signature::verify_aggregate(&msg, &mvks, &sigs).is_ok());
738+
let result = Signature::verify_aggregate(&msg, &mvks, &sigs);
739+
assert!(result.is_ok(), "Aggregate verification failed {result:?}");
679740
}
680741

681742
#[test]
@@ -764,7 +825,8 @@ mod tests {
764825
let fake_sig = sk.sign(&msg);
765826
batch_sig[0] = fake_sig;
766827

767-
assert!(Signature::batch_verify_aggregates(&batch_msgs, &batch_vk, &batch_sig).is_err());
828+
let batch_result = Signature::batch_verify_aggregates(&batch_msgs, &batch_vk, &batch_sig);
829+
assert_eq!(batch_result, Err(MultiSignatureError::BatchInvalid));
768830
}
769831
}
770832

0 commit comments

Comments
 (0)