mirror of
https://github.com/saymrwulf/risc0-curve25519-dalek-source.git
synced 2026-09-04 20:03:40 +00:00
Adding verify_prehashed_strict() (#212)
Combines `verify_prehashed` and `verify_strict` to allow strict verification with prehashed values.
This commit is contained in:
parent
461a2d7e05
commit
4f218d8e67
2 changed files with 268 additions and 84 deletions
127
src/verifying.rs
127
src/verifying.rs
|
|
@ -141,6 +141,28 @@ impl VerifyingKey {
|
||||||
VerifyingKey(compressed, point)
|
VerifyingKey(compressed, point)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A helper function that computes H(R || A || M) as well as its prehashed version
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn compute_challenge(
|
||||||
|
context: Option<&[u8]>,
|
||||||
|
R: &CompressedEdwardsY,
|
||||||
|
A: &CompressedEdwardsY,
|
||||||
|
M: &[u8],
|
||||||
|
) -> Scalar {
|
||||||
|
let mut h = Sha512::new();
|
||||||
|
if let Some(c) = context {
|
||||||
|
h.update(b"SigEd25519 no Ed25519 collisions");
|
||||||
|
h.update([1]); // Ed25519ph
|
||||||
|
h.update([c.len() as u8]);
|
||||||
|
h.update(c);
|
||||||
|
}
|
||||||
|
h.update(R.as_bytes());
|
||||||
|
h.update(A.as_bytes());
|
||||||
|
h.update(M);
|
||||||
|
|
||||||
|
Scalar::from_hash(h)
|
||||||
|
}
|
||||||
|
|
||||||
/// Verify a `signature` on a `prehashed_message` using the Ed25519ph algorithm.
|
/// Verify a `signature` on a `prehashed_message` using the Ed25519ph algorithm.
|
||||||
///
|
///
|
||||||
/// # Inputs
|
/// # Inputs
|
||||||
|
|
@ -171,8 +193,6 @@ impl VerifyingKey {
|
||||||
{
|
{
|
||||||
let signature = InternalSignature::try_from(signature)?;
|
let signature = InternalSignature::try_from(signature)?;
|
||||||
|
|
||||||
let mut h: Sha512 = Sha512::default();
|
|
||||||
|
|
||||||
let ctx: &[u8] = context.unwrap_or(b"");
|
let ctx: &[u8] = context.unwrap_or(b"");
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
ctx.len() <= 255,
|
ctx.len() <= 255,
|
||||||
|
|
@ -180,16 +200,12 @@ impl VerifyingKey {
|
||||||
);
|
);
|
||||||
|
|
||||||
let minus_A: EdwardsPoint = -self.1;
|
let minus_A: EdwardsPoint = -self.1;
|
||||||
|
let k = Self::compute_challenge(
|
||||||
h.update(b"SigEd25519 no Ed25519 collisions");
|
Some(ctx),
|
||||||
h.update([1]); // Ed25519ph
|
&signature.R,
|
||||||
h.update([ctx.len() as u8]);
|
&self.0,
|
||||||
h.update(ctx);
|
prehashed_message.finalize().as_slice(),
|
||||||
h.update(signature.R.as_bytes());
|
);
|
||||||
h.update(self.as_bytes());
|
|
||||||
h.update(prehashed_message.finalize().as_slice());
|
|
||||||
|
|
||||||
let k = Scalar::from_hash(h);
|
|
||||||
let R: EdwardsPoint =
|
let R: EdwardsPoint =
|
||||||
EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
||||||
|
|
||||||
|
|
@ -270,24 +286,18 @@ impl VerifyingKey {
|
||||||
) -> Result<(), SignatureError> {
|
) -> Result<(), SignatureError> {
|
||||||
let signature = InternalSignature::try_from(signature)?;
|
let signature = InternalSignature::try_from(signature)?;
|
||||||
|
|
||||||
let mut h: Sha512 = Sha512::new();
|
let signature_R = signature
|
||||||
let minus_A: EdwardsPoint = -self.1;
|
.R
|
||||||
|
.decompress()
|
||||||
let signature_R: EdwardsPoint = match signature.R.decompress() {
|
.ok_or_else(|| SignatureError::from(InternalError::Verify))?;
|
||||||
None => return Err(InternalError::Verify.into()),
|
|
||||||
Some(x) => x,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Logical OR is fine here as we're not trying to be constant time.
|
// Logical OR is fine here as we're not trying to be constant time.
|
||||||
if signature_R.is_small_order() || self.1.is_small_order() {
|
if signature_R.is_small_order() || self.1.is_small_order() {
|
||||||
return Err(InternalError::Verify.into());
|
return Err(InternalError::Verify.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
h.update(signature.R.as_bytes());
|
let minus_A: EdwardsPoint = -self.1;
|
||||||
h.update(self.as_bytes());
|
let k = Self::compute_challenge(None, &signature.R, &self.0, message);
|
||||||
h.update(message);
|
|
||||||
|
|
||||||
let k = Scalar::from_hash(h);
|
|
||||||
let R: EdwardsPoint =
|
let R: EdwardsPoint =
|
||||||
EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
||||||
|
|
||||||
|
|
@ -297,6 +307,67 @@ impl VerifyingKey {
|
||||||
Err(InternalError::Verify.into())
|
Err(InternalError::Verify.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Verify a `signature` on a `prehashed_message` using the Ed25519ph algorithm,
|
||||||
|
/// using strict signture checking as defined by [`Self::verify_strict`].
|
||||||
|
///
|
||||||
|
/// # Inputs
|
||||||
|
///
|
||||||
|
/// * `prehashed_message` is an instantiated hash digest with 512-bits of
|
||||||
|
/// output which has had the message to be signed previously fed into its
|
||||||
|
/// state.
|
||||||
|
/// * `context` is an optional context string, up to 255 bytes inclusive,
|
||||||
|
/// which may be used to provide additional domain separation. If not
|
||||||
|
/// set, this will default to an empty string.
|
||||||
|
/// * `signature` is a purported Ed25519ph [`Signature`] on the `prehashed_message`.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// Returns `true` if the `signature` was a valid signature created by this
|
||||||
|
/// `Keypair` on the `prehashed_message`.
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn verify_prehashed_strict<D>(
|
||||||
|
&self,
|
||||||
|
prehashed_message: D,
|
||||||
|
context: Option<&[u8]>,
|
||||||
|
signature: &ed25519::Signature,
|
||||||
|
) -> Result<(), SignatureError>
|
||||||
|
where
|
||||||
|
D: Digest<OutputSize = U64>,
|
||||||
|
{
|
||||||
|
let signature = InternalSignature::try_from(signature)?;
|
||||||
|
|
||||||
|
let ctx: &[u8] = context.unwrap_or(b"");
|
||||||
|
debug_assert!(
|
||||||
|
ctx.len() <= 255,
|
||||||
|
"The context must not be longer than 255 octets."
|
||||||
|
);
|
||||||
|
|
||||||
|
let signature_R = signature
|
||||||
|
.R
|
||||||
|
.decompress()
|
||||||
|
.ok_or_else(|| SignatureError::from(InternalError::Verify))?;
|
||||||
|
|
||||||
|
// Logical OR is fine here as we're not trying to be constant time.
|
||||||
|
if signature_R.is_small_order() || self.1.is_small_order() {
|
||||||
|
return Err(InternalError::Verify.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let minus_A: EdwardsPoint = -self.1;
|
||||||
|
let k = Self::compute_challenge(
|
||||||
|
Some(ctx),
|
||||||
|
&signature.R,
|
||||||
|
&self.0,
|
||||||
|
prehashed_message.finalize().as_slice(),
|
||||||
|
);
|
||||||
|
let R = EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
||||||
|
|
||||||
|
if R == signature_R {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(InternalError::Verify.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Verifier<ed25519::Signature> for VerifyingKey {
|
impl Verifier<ed25519::Signature> for VerifyingKey {
|
||||||
|
|
@ -309,14 +380,8 @@ impl Verifier<ed25519::Signature> for VerifyingKey {
|
||||||
fn verify(&self, message: &[u8], signature: &ed25519::Signature) -> Result<(), SignatureError> {
|
fn verify(&self, message: &[u8], signature: &ed25519::Signature) -> Result<(), SignatureError> {
|
||||||
let signature = InternalSignature::try_from(signature)?;
|
let signature = InternalSignature::try_from(signature)?;
|
||||||
|
|
||||||
let mut h: Sha512 = Sha512::new();
|
|
||||||
let minus_A: EdwardsPoint = -self.1;
|
let minus_A: EdwardsPoint = -self.1;
|
||||||
|
let k = Self::compute_challenge(None, &signature.R, &self.0, message);
|
||||||
h.update(signature.R.as_bytes());
|
|
||||||
h.update(self.as_bytes());
|
|
||||||
h.update(message);
|
|
||||||
|
|
||||||
let k = Scalar::from_hash(h);
|
|
||||||
let R: EdwardsPoint =
|
let R: EdwardsPoint =
|
||||||
EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
||||||
|
|
||||||
|
|
|
||||||
225
tests/ed25519.rs
225
tests/ed25519.rs
|
|
@ -21,16 +21,23 @@ use sha2::Sha512;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod vectors {
|
mod vectors {
|
||||||
use curve25519_dalek::{edwards::EdwardsPoint, scalar::Scalar};
|
|
||||||
use sha2::{digest::Digest, Sha512};
|
|
||||||
use std::convert::TryFrom;
|
|
||||||
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::BufRead;
|
|
||||||
use std::io::BufReader;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
use curve25519_dalek::{
|
||||||
|
constants::ED25519_BASEPOINT_POINT,
|
||||||
|
edwards::{CompressedEdwardsY, EdwardsPoint},
|
||||||
|
scalar::Scalar,
|
||||||
|
traits::IsIdentity,
|
||||||
|
};
|
||||||
|
use sha2::{digest::Digest, Sha512};
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
convert::TryFrom,
|
||||||
|
fs::File,
|
||||||
|
io::{BufRead, BufReader},
|
||||||
|
ops::Neg,
|
||||||
|
};
|
||||||
|
|
||||||
// TESTVECTORS is taken from sign.input.gz in agl's ed25519 Golang
|
// TESTVECTORS is taken from sign.input.gz in agl's ed25519 Golang
|
||||||
// package. It is a selection of test cases from
|
// package. It is a selection of test cases from
|
||||||
// http://ed25519.cr.yp.to/python/sign.input
|
// http://ed25519.cr.yp.to/python/sign.input
|
||||||
|
|
@ -81,6 +88,13 @@ mod vectors {
|
||||||
"Signature verification failed on line {}",
|
"Signature verification failed on line {}",
|
||||||
lineno
|
lineno
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
expected_verifying_key
|
||||||
|
.verify_strict(&msg_bytes, &sig2)
|
||||||
|
.is_ok(),
|
||||||
|
"Signature strict verification failed on line {}",
|
||||||
|
lineno
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,81 +130,154 @@ mod vectors {
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
signing_key
|
signing_key
|
||||||
.verify_prehashed(prehash_for_verifying, None, &sig2)
|
.verify_prehashed(prehash_for_verifying.clone(), None, &sig2)
|
||||||
.is_ok(),
|
.is_ok(),
|
||||||
"Could not verify ed25519ph signature!"
|
"Could not verify ed25519ph signature!"
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
expected_verifying_key
|
||||||
|
.verify_prehashed_strict(prehash_for_verifying, None, &sig2)
|
||||||
|
.is_ok(),
|
||||||
|
"Could not strict-verify ed25519ph signature!"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// The remaining items in this mod are for the repudiation tests
|
||||||
|
//
|
||||||
|
|
||||||
// Taken from curve25519_dalek::constants::EIGHT_TORSION[4]
|
// Taken from curve25519_dalek::constants::EIGHT_TORSION[4]
|
||||||
const EIGHT_TORSION_4: [u8; 32] = [
|
const EIGHT_TORSION_4: [u8; 32] = [
|
||||||
236, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
236, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127,
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127,
|
||||||
];
|
];
|
||||||
|
|
||||||
fn compute_hram(message: &[u8], pub_key: &EdwardsPoint, signature_r: &EdwardsPoint) -> Scalar {
|
// Computes the prehashed or non-prehashed challenge, depending on whether context is given
|
||||||
let k_bytes = Sha512::default()
|
fn compute_challenge(
|
||||||
.chain_update(&signature_r.compress().as_bytes())
|
message: &[u8],
|
||||||
.chain_update(&pub_key.compress().as_bytes()[..])
|
pub_key: &EdwardsPoint,
|
||||||
.chain_update(&message);
|
signature_r: &EdwardsPoint,
|
||||||
let mut k_output = [0u8; 64];
|
context: Option<&[u8]>,
|
||||||
k_output.copy_from_slice(k_bytes.finalize().as_slice());
|
) -> Scalar {
|
||||||
Scalar::from_bytes_mod_order_wide(&k_output)
|
let mut h = Sha512::default();
|
||||||
|
if let Some(c) = context {
|
||||||
|
h.update(b"SigEd25519 no Ed25519 collisions");
|
||||||
|
h.update(&[1]);
|
||||||
|
h.update(&[c.len() as u8]);
|
||||||
|
h.update(c);
|
||||||
|
}
|
||||||
|
h.update(&signature_r.compress().as_bytes());
|
||||||
|
h.update(&pub_key.compress().as_bytes()[..]);
|
||||||
|
h.update(&message);
|
||||||
|
Scalar::from_hash(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_signature(r: &EdwardsPoint, s: &Scalar) -> Vec<u8> {
|
fn serialize_signature(r: &EdwardsPoint, s: &Scalar) -> Vec<u8> {
|
||||||
[&r.compress().as_bytes()[..], &s.as_bytes()[..]].concat()
|
[&r.compress().as_bytes()[..], &s.as_bytes()[..]].concat()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const WEAK_PUBKEY: CompressedEdwardsY = CompressedEdwardsY(EIGHT_TORSION_4);
|
||||||
|
|
||||||
|
// Pick a random Scalar
|
||||||
|
fn non_null_scalar() -> Scalar {
|
||||||
|
let mut rng = rand::rngs::OsRng;
|
||||||
|
let mut s_candidate = Scalar::random(&mut rng);
|
||||||
|
while s_candidate == Scalar::ZERO {
|
||||||
|
s_candidate = Scalar::random(&mut rng);
|
||||||
|
}
|
||||||
|
s_candidate
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pick_r(s: Scalar) -> EdwardsPoint {
|
||||||
|
let r0 = s * ED25519_BASEPOINT_POINT;
|
||||||
|
// Pick a torsion point of order 2
|
||||||
|
r0 + WEAK_PUBKEY.decompress().unwrap().neg()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that verify_strict() rejects small-order pubkeys. We test this by explicitly
|
||||||
|
// constructing a pubkey-signature pair that verifies with respect to two distinct messages.
|
||||||
|
// This should be accepted by verify(), but rejected by verify_strict().
|
||||||
#[test]
|
#[test]
|
||||||
fn repudiation() {
|
fn repudiation() {
|
||||||
use curve25519_dalek::traits::IsIdentity;
|
|
||||||
use std::ops::Neg;
|
|
||||||
|
|
||||||
let message1 = b"Send 100 USD to Alice";
|
let message1 = b"Send 100 USD to Alice";
|
||||||
let message2 = b"Send 100000 USD to Alice";
|
let message2 = b"Send 100000 USD to Alice";
|
||||||
|
|
||||||
// Pick a random Scalar
|
|
||||||
fn non_null_scalar() -> Scalar {
|
|
||||||
let mut rng = rand::rngs::OsRng;
|
|
||||||
let mut s_candidate = Scalar::random(&mut rng);
|
|
||||||
while s_candidate == Scalar::ZERO {
|
|
||||||
s_candidate = Scalar::random(&mut rng);
|
|
||||||
}
|
|
||||||
s_candidate
|
|
||||||
}
|
|
||||||
let mut s: Scalar = non_null_scalar();
|
let mut s: Scalar = non_null_scalar();
|
||||||
|
let pubkey = WEAK_PUBKEY.decompress().unwrap();
|
||||||
|
let mut r = pick_r(s);
|
||||||
|
|
||||||
fn pick_r_and_pubkey(s: Scalar) -> (EdwardsPoint, EdwardsPoint) {
|
// Find an R such that
|
||||||
let r0 = s * curve25519_dalek::constants::ED25519_BASEPOINT_POINT;
|
// H(R || A || M₁) · A == A == H(R || A || M₂) · A
|
||||||
// Pick a torsion point of order 2
|
// This happens with high probability when A is low order.
|
||||||
let pub_key = curve25519_dalek::edwards::CompressedEdwardsY(EIGHT_TORSION_4)
|
while !(pubkey.neg() + compute_challenge(message1, &pubkey, &r, None) * pubkey)
|
||||||
.decompress()
|
.is_identity()
|
||||||
.unwrap();
|
|| !(pubkey.neg() + compute_challenge(message2, &pubkey, &r, None) * pubkey)
|
||||||
let r = r0 + pub_key.neg();
|
.is_identity()
|
||||||
(r, pub_key)
|
{
|
||||||
|
// We pick an s and let R = sB - A where B is the basepoint
|
||||||
|
s = non_null_scalar();
|
||||||
|
r = pick_r(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (mut r, mut pub_key) = pick_r_and_pubkey(s);
|
// At this point, both verification equations hold:
|
||||||
|
// sB = R + H(R || A || M₁) · A
|
||||||
|
// = R + H(R || A || M₂) · A
|
||||||
|
// Check that this is true
|
||||||
|
let signature = serialize_signature(&r, &s);
|
||||||
|
let vk = VerifyingKey::from_bytes(&pubkey.compress().as_bytes()).unwrap();
|
||||||
|
let sig = Signature::try_from(&signature[..]).unwrap();
|
||||||
|
assert!(vk.verify(message1, &sig).is_ok());
|
||||||
|
assert!(vk.verify(message2, &sig).is_ok());
|
||||||
|
|
||||||
while !(pub_key.neg() + compute_hram(message1, &pub_key, &r) * pub_key).is_identity()
|
// Now check that the sigs fail under verify_strict. This is because verify_strict rejects
|
||||||
|| !(pub_key.neg() + compute_hram(message2, &pub_key, &r) * pub_key).is_identity()
|
// small order pubkeys.
|
||||||
|
assert!(vk.verify_strict(message1, &sig).is_err());
|
||||||
|
assert!(vk.verify_strict(message2, &sig).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identical to repudiation() above, but testing verify_prehashed against
|
||||||
|
// verify_prehashed_strict. See comments above for a description of what's happening.
|
||||||
|
#[test]
|
||||||
|
fn repudiation_prehash() {
|
||||||
|
let message1 = Sha512::new().chain_update(b"Send 100 USD to Alice");
|
||||||
|
let message2 = Sha512::new().chain_update(b"Send 100000 USD to Alice");
|
||||||
|
let message1_bytes = message1.clone().finalize();
|
||||||
|
let message2_bytes = message2.clone().finalize();
|
||||||
|
|
||||||
|
let mut s: Scalar = non_null_scalar();
|
||||||
|
let pubkey = WEAK_PUBKEY.decompress().unwrap();
|
||||||
|
let mut r = pick_r(s);
|
||||||
|
let context_str = Some(&b"edtest"[..]);
|
||||||
|
|
||||||
|
while !(pubkey.neg()
|
||||||
|
+ compute_challenge(&message1_bytes, &pubkey, &r, context_str) * pubkey)
|
||||||
|
.is_identity()
|
||||||
|
|| !(pubkey.neg()
|
||||||
|
+ compute_challenge(&message2_bytes, &pubkey, &r, context_str) * pubkey)
|
||||||
|
.is_identity()
|
||||||
{
|
{
|
||||||
s = non_null_scalar();
|
s = non_null_scalar();
|
||||||
let key = pick_r_and_pubkey(s);
|
r = pick_r(s);
|
||||||
r = key.0;
|
|
||||||
pub_key = key.1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that verify_prehashed succeeds on both sigs
|
||||||
let signature = serialize_signature(&r, &s);
|
let signature = serialize_signature(&r, &s);
|
||||||
let pk = VerifyingKey::from_bytes(&pub_key.compress().as_bytes()).unwrap();
|
let vk = VerifyingKey::from_bytes(&pubkey.compress().as_bytes()).unwrap();
|
||||||
let sig = Signature::try_from(&signature[..]).unwrap();
|
let sig = Signature::try_from(&signature[..]).unwrap();
|
||||||
// The same signature verifies for both messages
|
assert!(vk
|
||||||
assert!(pk.verify(message1, &sig).is_ok() && pk.verify(message2, &sig).is_ok());
|
.verify_prehashed(message1.clone(), context_str, &sig)
|
||||||
// But not with a strict signature: verify_strict refuses small order keys
|
.is_ok());
|
||||||
assert!(
|
assert!(vk
|
||||||
pk.verify_strict(message1, &sig).is_err() || pk.verify_strict(message2, &sig).is_err()
|
.verify_prehashed(message2.clone(), context_str, &sig)
|
||||||
);
|
.is_ok());
|
||||||
|
|
||||||
|
// Check that verify_prehashed_strict fails on both sigs
|
||||||
|
assert!(vk
|
||||||
|
.verify_prehashed_strict(message1.clone(), context_str, &sig)
|
||||||
|
.is_err());
|
||||||
|
assert!(vk
|
||||||
|
.verify_prehashed_strict(message2.clone(), context_str, &sig)
|
||||||
|
.is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,6 +299,7 @@ mod integrations {
|
||||||
let mut csprng = OsRng;
|
let mut csprng = OsRng;
|
||||||
|
|
||||||
signing_key = SigningKey::generate(&mut csprng);
|
signing_key = SigningKey::generate(&mut csprng);
|
||||||
|
let verifying_key = signing_key.verifying_key();
|
||||||
good_sig = signing_key.sign(&good);
|
good_sig = signing_key.sign(&good);
|
||||||
bad_sig = signing_key.sign(&bad);
|
bad_sig = signing_key.sign(&bad);
|
||||||
|
|
||||||
|
|
@ -219,14 +307,26 @@ mod integrations {
|
||||||
signing_key.verify(&good, &good_sig).is_ok(),
|
signing_key.verify(&good, &good_sig).is_ok(),
|
||||||
"Verification of a valid signature failed!"
|
"Verification of a valid signature failed!"
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
verifying_key.verify_strict(&good, &good_sig).is_ok(),
|
||||||
|
"Strict verification of a valid signature failed!"
|
||||||
|
);
|
||||||
assert!(
|
assert!(
|
||||||
signing_key.verify(&good, &bad_sig).is_err(),
|
signing_key.verify(&good, &bad_sig).is_err(),
|
||||||
"Verification of a signature on a different message passed!"
|
"Verification of a signature on a different message passed!"
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
verifying_key.verify_strict(&good, &bad_sig).is_err(),
|
||||||
|
"Strict verification of a signature on a different message passed!"
|
||||||
|
);
|
||||||
assert!(
|
assert!(
|
||||||
signing_key.verify(&bad, &good_sig).is_err(),
|
signing_key.verify(&bad, &good_sig).is_err(),
|
||||||
"Verification of a signature on a different message passed!"
|
"Verification of a signature on a different message passed!"
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
verifying_key.verify_strict(&bad, &good_sig).is_err(),
|
||||||
|
"Strict verification of a signature on a different message passed!"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -256,6 +356,7 @@ mod integrations {
|
||||||
let context: &[u8] = b"testing testing 1 2 3";
|
let context: &[u8] = b"testing testing 1 2 3";
|
||||||
|
|
||||||
signing_key = SigningKey::generate(&mut csprng);
|
signing_key = SigningKey::generate(&mut csprng);
|
||||||
|
let verifying_key = signing_key.verifying_key();
|
||||||
good_sig = signing_key
|
good_sig = signing_key
|
||||||
.sign_prehashed(prehashed_good1, Some(context))
|
.sign_prehashed(prehashed_good1, Some(context))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -265,22 +366,40 @@ mod integrations {
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
signing_key
|
signing_key
|
||||||
.verify_prehashed(prehashed_good2, Some(context), &good_sig)
|
.verify_prehashed(prehashed_good2.clone(), Some(context), &good_sig)
|
||||||
.is_ok(),
|
.is_ok(),
|
||||||
"Verification of a valid signature failed!"
|
"Verification of a valid signature failed!"
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
verifying_key
|
||||||
|
.verify_prehashed_strict(prehashed_good2, Some(context), &good_sig)
|
||||||
|
.is_ok(),
|
||||||
|
"Strict verification of a valid signature failed!"
|
||||||
|
);
|
||||||
assert!(
|
assert!(
|
||||||
signing_key
|
signing_key
|
||||||
.verify_prehashed(prehashed_good3, Some(context), &bad_sig)
|
.verify_prehashed(prehashed_good3.clone(), Some(context), &bad_sig)
|
||||||
.is_err(),
|
.is_err(),
|
||||||
"Verification of a signature on a different message passed!"
|
"Verification of a signature on a different message passed!"
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
verifying_key
|
||||||
|
.verify_prehashed_strict(prehashed_good3, Some(context), &bad_sig)
|
||||||
|
.is_err(),
|
||||||
|
"Strict verification of a signature on a different message passed!"
|
||||||
|
);
|
||||||
assert!(
|
assert!(
|
||||||
signing_key
|
signing_key
|
||||||
.verify_prehashed(prehashed_bad2, Some(context), &good_sig)
|
.verify_prehashed(prehashed_bad2.clone(), Some(context), &good_sig)
|
||||||
.is_err(),
|
.is_err(),
|
||||||
"Verification of a signature on a different message passed!"
|
"Verification of a signature on a different message passed!"
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
verifying_key
|
||||||
|
.verify_prehashed_strict(prehashed_bad2, Some(context), &good_sig)
|
||||||
|
.is_err(),
|
||||||
|
"Strict verification of a signature on a different message passed!"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "batch")]
|
#[cfg(feature = "batch")]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue