Files
serai/crypto/dleq/src/tests/mod.rs

153 lines
4.6 KiB
Rust
Raw Normal View History

use core::ops::Deref;
use hex_literal::hex;
use rand_core::OsRng;
use zeroize::Zeroizing;
use ff::Field;
use group::GroupEncoding;
use k256::{Scalar, ProjectivePoint};
use transcript::{Transcript, RecommendedTranscript};
use crate::{DLEqProof, MultiDLEqProof};
#[cfg(feature = "experimental")]
mod cross_group;
fn generators() -> [k256::ProjectivePoint; 5] {
[
ProjectivePoint::GENERATOR,
ProjectivePoint::from_bytes(
2022-07-15 01:26:07 -04:00
&(hex!("0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0").into()),
)
.unwrap(),
// Just an increment of the last byte from the previous, where the previous two are valid
ProjectivePoint::from_bytes(
2022-07-15 01:26:07 -04:00
&(hex!("0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac4").into()),
)
.unwrap(),
ProjectivePoint::from_bytes(
2022-07-15 01:26:07 -04:00
&(hex!("0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803aca").into()),
)
.unwrap(),
ProjectivePoint::from_bytes(
2022-07-15 01:26:07 -04:00
&(hex!("0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803acb").into()),
)
.unwrap(),
]
}
#[test]
fn test_dleq() {
let generators = generators();
let transcript = || RecommendedTranscript::new(b"DLEq Proof Test");
for i in 0 .. 5 {
let key = Zeroizing::new(Scalar::random(&mut OsRng));
let proof = DLEqProof::prove(&mut OsRng, &mut transcript(), &generators[.. i], &key);
let mut keys = [ProjectivePoint::GENERATOR; 5];
for k in 0 .. 5 {
keys[k] = generators[k] * key.deref();
}
proof.verify(&mut transcript(), &generators[.. i], &keys[.. i]).unwrap();
// Different challenge
assert!(proof
.verify(
&mut RecommendedTranscript::new(b"different challenge"),
&generators[.. i],
&keys[.. i]
)
.is_err());
// All of these following tests should effectively be a different challenge and accordingly
// pointless. They're still nice to have though
// We could edit these tests to always test with at least two generators
// Then we don't test proofs with zero/one generator(s)
// While those are stupid, and pointless, and potentially point to a failure in the caller,
// it could also be part of a dynamic system which deals with variable amounts of generators
// Not panicking in such use cases, even if they're inefficient, provides seamless behavior
if i >= 2 {
// Different generators
assert!(proof
.verify(
&mut transcript(),
generators[.. i].iter().cloned().rev().collect::<Vec<_>>().as_ref(),
&keys[.. i]
)
.is_err());
// Different keys
assert!(proof
.verify(
&mut transcript(),
&generators[.. i],
keys[.. i].iter().cloned().rev().collect::<Vec<_>>().as_ref()
)
.is_err());
}
#[cfg(feature = "serialize")]
{
let mut buf = vec![];
DKG Blame (#196) * Standardize the DLEq serialization function naming They mismatched from the rest of the project. This commit is technically incomplete as it doesn't update the dkg crate. * Rewrite DKG encryption to enable per-message decryption without side effects This isn't technically true as I already know a break in this which I'll correct for shortly. Does update documentation to explain the new scheme. Required for blame. * Add a verifiable system for blame during the FROST DKG Previously, if sent an invalid key share, the participant would realize that and could accuse the sender. Without further evidence, either the accuser or the accused could be guilty. Now, the accuser has a proof the accused is in the wrong. Reworks KeyMachine to return BlameMachine. This explicitly acknowledges how locally complete keys still need group acknowledgement before the protocol can be complete and provides a way for others to verify blame, even after a locally successful run. If any blame is cast, the protocol is no longer considered complete-able (instead aborting). Further accusations of blame can still be handled however. Updates documentation on network behavior. Also starts to remove "OnDrop". We now use Zeroizing for anything which should be zeroized on drop. This is a lot more piece-meal and reduces clones. * Tweak Zeroizing and Debug impls Expands Zeroizing to be more comprehensive. Also updates Zeroizing<CachedPreprocess([u8; 32])> to CachedPreprocess(Zeroizing<[u8; 32]>) so zeroizing is the first thing done and last step before exposing the copy-able [u8; 32]. Removes private keys from Debug. * Fix a bug where adversaries could claim to be using another user's encryption keys to learn their messages Mentioned a few commits ago, now fixed. This wouldn't have affected Serai, which aborts on failure, nor any DKG currently supported. It's just about ensuring the DKG encryption is robust and proper. * Finish moving dleq from ser/deser to write/read * Add tests for dkg blame * Add a FROST test for invalid signature shares * Batch verify encrypted messages' ephemeral keys' PoP
2023-01-01 01:54:18 -05:00
proof.write(&mut buf).unwrap();
let deserialized = DLEqProof::<ProjectivePoint>::read::<&[u8]>(&mut buf.as_ref()).unwrap();
assert_eq!(proof, deserialized);
}
}
}
#[test]
fn test_multi_dleq() {
let generators = generators();
let transcript = || RecommendedTranscript::new(b"MultiDLEq Proof Test");
// Test up to 3 keys
for k in 0 ..= 3 {
let mut keys = vec![];
let mut these_generators = vec![];
let mut pub_keys = vec![];
for i in 0 .. k {
let key = Zeroizing::new(Scalar::random(&mut OsRng));
// For each key, test a variable set of generators
// 0: 0
// 1: 1, 2
// 2: 2, 3, 4
let key_generators = generators[i .. (i + i + 1)].to_vec();
let mut these_pub_keys = vec![];
for generator in &key_generators {
these_pub_keys.push(generator * key.deref());
}
keys.push(key);
these_generators.push(key_generators);
pub_keys.push(these_pub_keys);
}
let proof = MultiDLEqProof::prove(&mut OsRng, &mut transcript(), &these_generators, &keys);
proof.verify(&mut transcript(), &these_generators, &pub_keys).unwrap();
// Different challenge
assert!(proof
.verify(&mut RecommendedTranscript::new(b"different challenge"), &these_generators, &pub_keys)
.is_err());
// Test verifying for a different amount of keys fail
if k > 0 {
assert!(proof.verify(&mut transcript(), &these_generators, &pub_keys[.. k - 1]).is_err());
}
#[cfg(feature = "serialize")]
{
let mut buf = vec![];
proof.write(&mut buf).unwrap();
let deserialized =
MultiDLEqProof::<ProjectivePoint>::read::<&[u8]>(&mut buf.as_ref(), k).unwrap();
assert_eq!(proof, deserialized);
}
}
}