Skip to content

Commit

Permalink
Use ed25519::Signature as the signature type; MSRV 1.60
Browse files Browse the repository at this point in the history
This allows using `ed25519-consensus` in conjunction with the
`signature::{Signer, Verifier}` traits.

These traits are generic around a signature type parameter which is used
to identify a particular signature algorithm, which in this case is
`ed25519::Signature`. This type has been used to replace the signature
type originally defined in this crate, which is necessary to make
`Signer`/`Verifier` work.

Uses namespaced features to activate both `dep:serde` and
`ed25519/serde`, which requires an MSRV of 1.60. Note this is also the
MSRV of `ed25519` v2.1+.
  • Loading branch information
tarcieri committed Jan 23, 2023
1 parent 94763f4 commit 2ec9dc2
Show file tree
Hide file tree
Showing 12 changed files with 38 additions and 82 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ curve25519-dalek = { package = "curve25519-dalek-ng", version = "4.1", default-f
serde = { version = "1", optional = true, features = ["derive"] }
zeroize = { version = "1.1", default-features = false }
thiserror = { version = "1", optional = true }
ed25519 = { version = "2", default-features = false }

[dev-dependencies]
rand = "0.8"
Expand All @@ -31,6 +32,7 @@ once_cell = "1.4"
[features]
std = ["thiserror"]
default = ["serde", "std"]
serde = ["dep:serde", "ed25519/serde"]

[[test]]
name = "rfc8032"
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@ let (vk_bytes, sig_bytes) = {
};
// Verify the signature
assert!(
VerificationKey::try_from(vk_bytes)
.and_then(|vk| vk.verify(&sig_bytes.into(), msg))
.and_then(|vk| vk.verify(msg, &sig_bytes.into()))
.is_ok()
);
```
Expand All @@ -79,4 +80,4 @@ assert!(
[RFC8032]: https://tools.ietf.org/html/rfc8032
[zebra]: https://github.com/ZcashFoundation/zebra
[ZIP215]: https://github.com/zcash/zips/blob/master/zip-0215.rst
[blog]: https://hdevalence.ca/blog/2020-10-04-its-25519am
[blog]: https://hdevalence.ca/blog/2020-10-04-its-25519am
2 changes: 1 addition & 1 deletion benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn bench_batch_verify(c: &mut Criterion) {
b.iter(|| {
for (vk_bytes, sig) in sigs.iter() {
let _ =
VerificationKey::try_from(*vk_bytes).and_then(|vk| vk.verify(sig, b""));
VerificationKey::try_from(*vk_bytes).and_then(|vk| vk.verify(b"", sig));
}
})
},
Expand Down
7 changes: 4 additions & 3 deletions src/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl<'msg, M: AsRef<[u8]> + ?Sized> From<(VerificationKeyBytes, Signature, &'msg
// Compute k now to avoid dependency on the msg lifetime.
let k = Scalar::from_hash(
Sha512::default()
.chain(&sig.R_bytes[..])
.chain(sig.r_bytes())
.chain(&vk_bytes.0[..])
.chain(msg),
);
Expand Down Expand Up @@ -187,10 +187,11 @@ impl Verifier {
let mut A_coeff = Scalar::zero();

for (k, sig) in sigs.iter() {
let R = CompressedEdwardsY(sig.R_bytes)
let R = CompressedEdwardsY(*sig.r_bytes())
.decompress()
.ok_or(Error::InvalidSignature)?;
let s = Scalar::from_canonical_bytes(sig.s_bytes).ok_or(Error::InvalidSignature)?;
let s =
Scalar::from_canonical_bytes(*sig.s_bytes()).ok_or(Error::InvalidSignature)?;
let z = Scalar::from(gen_u128(&mut rng));
B_coeff -= z * s;
Rs.push(R);
Expand Down
3 changes: 1 addition & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
#[cfg(feature = "std")]
pub mod batch;
mod error;
mod signature;
mod signing_key;
mod verification_key;

pub use ed25519::{signature, Signature};
pub use error::Error;
pub use signature::Signature;
pub use signing_key::SigningKey;
pub use verification_key::{VerificationKey, VerificationKeyBytes};
63 changes: 0 additions & 63 deletions src/signature.rs

This file was deleted.

11 changes: 9 additions & 2 deletions src/signing_key.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use core::convert::TryFrom;

use curve25519_dalek::{constants, scalar::Scalar};
use ed25519::signature::{self, Signer};
use rand_core::{CryptoRng, RngCore};
use sha2::{Digest, Sha512};

Expand Down Expand Up @@ -156,7 +157,6 @@ impl SigningKey {
}

/// Create a signature on `msg` using this key.
#[allow(non_snake_case)]
pub fn sign(&self, msg: &[u8]) -> Signature {
let r = Scalar::from_hash(Sha512::default().chain(&self.prefix[..]).chain(msg));

Expand All @@ -173,6 +173,13 @@ impl SigningKey {

let s_bytes = (r + k * self.s).to_bytes();

Signature { R_bytes, s_bytes }
Signature::from_components(R_bytes, s_bytes)
}
}

impl Signer<Signature> for SigningKey {
#[allow(non_snake_case)]
fn try_sign(&self, msg: &[u8]) -> signature::Result<Signature> {
Ok(self.sign(msg))
}
}
19 changes: 14 additions & 5 deletions src/verification_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use curve25519_dalek::{
scalar::Scalar,
traits::IsIdentity,
};
use ed25519::signature::{self, Verifier};
use sha2::{Digest, Sha512};

use crate::{Error, Signature};
Expand All @@ -27,7 +28,7 @@ use crate::{Error, Signature};
/// # let sig = sk.sign(msg);
/// # let vk_bytes = VerificationKeyBytes::from(&sk);
/// VerificationKey::try_from(vk_bytes)
/// .and_then(|vk| vk.verify(&sig, msg));
/// .and_then(|vk| vk.verify( msg,&sig));
/// ```
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
Expand Down Expand Up @@ -204,10 +205,10 @@ impl VerificationKey {
///
/// [ps]: https://zips.z.cash/protocol/protocol.pdf#concreteed25519
/// [ZIP215]: https://github.com/zcash/zips/blob/master/zip-0215.rst
pub fn verify(&self, signature: &Signature, msg: &[u8]) -> Result<(), Error> {
pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), Error> {
let k = Scalar::from_hash(
Sha512::default()
.chain(&signature.R_bytes[..])
.chain(signature.r_bytes())
.chain(&self.A_bytes.0[..])
.chain(msg),
);
Expand All @@ -219,9 +220,10 @@ impl VerificationKey {
#[allow(non_snake_case)]
pub(crate) fn verify_prehashed(&self, signature: &Signature, k: Scalar) -> Result<(), Error> {
// `s_bytes` MUST represent an integer less than the prime `l`.
let s = Scalar::from_canonical_bytes(signature.s_bytes).ok_or(Error::InvalidSignature)?;
let s =
Scalar::from_canonical_bytes(*signature.s_bytes()).ok_or(Error::InvalidSignature)?;
// `R_bytes` MUST be an encoding of a point on the twisted Edwards form of Curve25519.
let R = CompressedEdwardsY(signature.R_bytes)
let R = CompressedEdwardsY(*signature.r_bytes())
.decompress()
.ok_or(Error::InvalidSignature)?;
// We checked the encoding of A_bytes when constructing `self`.
Expand All @@ -239,3 +241,10 @@ impl VerificationKey {
}
}
}

impl Verifier<Signature> for VerificationKey {
fn verify(&self, msg: &[u8], signature: &Signature) -> signature::Result<()> {
self.verify(msg, signature)
.map_err(|_| signature::Error::new())
}
}
2 changes: 1 addition & 1 deletion tests/rfc8032.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn rfc8032_test_case(sk_bytes: Vec<u8>, pk_bytes: Vec<u8>, sig_bytes: Vec<u8>, m
let pk: VerificationKey = bincode::deserialize(&pk_bytes).expect("pk should deserialize");
let sig: Signature = bincode::deserialize(&sig_bytes).expect("sig should deserialize");

assert!(pk.verify(&sig, &msg).is_ok(), "verification failed");
assert!(pk.verify(&msg, &sig).is_ok(), "verification failed");

let pk_from_sk = VerificationKey::from(&sk);
assert_eq!(
Expand Down
2 changes: 1 addition & 1 deletion tests/small_order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ fn individual_matches_batch_verification() -> Result<(), Report> {
let sig = Signature::from(case.sig_bytes);
let vkb = VerificationKeyBytes::from(case.vk_bytes);
let individual_verification =
VerificationKey::try_from(vkb).and_then(|vk| vk.verify(&sig, msg));
VerificationKey::try_from(vkb).and_then(|vk| vk.verify(msg, &sig));
let mut bv = batch::Verifier::new();
bv.queue((vkb, sig, msg));
let batch_verification = bv.verify(rand::thread_rng());
Expand Down
2 changes: 1 addition & 1 deletion tests/unit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,5 @@ fn sign_and_verify() {

let sig = sk.sign(&msg[..]);

assert_eq!(pk.verify(&sig, &msg[..]), Ok(()))
assert_eq!(pk.verify(&msg[..], &sig), Ok(()))
}
2 changes: 1 addition & 1 deletion tests/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl TestCase {
fn check_zip215(&self) -> Result<(), Report> {
use ed25519_consensus::{Signature, VerificationKey};
let sig = Signature::from(self.sig_bytes);
VerificationKey::try_from(self.vk_bytes).and_then(|vk| vk.verify(&sig, b"Zcash"))?;
VerificationKey::try_from(self.vk_bytes).and_then(|vk| vk.verify(b"Zcash", &sig))?;
Ok(())
}
}
Expand Down

0 comments on commit 2ec9dc2

Please sign in to comment.