Make digest optional (#268)

digest isn't yet stable but we have use it in the public API.

This makes the digest API optional to use in opt-in basis by
feature gating this via an optional digest feature.

API items now feature-gated:

- `pub use ed25519_dalek::Digest`
- `SigningKey::sign_prehashed(D: prehashed_message, ..)`
- `SigningKey::verify_prehashed(D: prehahed_message, ..)`
- `VerifyingKey::verify_prehashed(D: prehashed_message, ..)`
- `VerifyingKey::verify_prehashed_strict(D: prehashed_message, ..)`

Also no longer re-exporting `sha2::Sha512`
This commit is contained in:
pinkforest(she/her) 2023-01-19 18:59:43 +11:00 committed by GitHub
parent e1d4ef313e
commit 431e69959d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 37 additions and 12 deletions

View file

@ -30,7 +30,7 @@ jobs:
- run: cargo test --target ${{ matrix.target }} --no-default-features --features alloc --lib
- run: cargo test --target ${{ matrix.target }}
- run: cargo test --target ${{ matrix.target }} --features batch
- run: cargo test --target ${{ matrix.target }} --features rand_core
- run: cargo test --target ${{ matrix.target }} --features "digest rand_core"
- run: cargo test --target ${{ matrix.target }} --features serde
- run: cargo test --target ${{ matrix.target }} --features pem

View file

@ -57,6 +57,7 @@ std = ["alloc", "ed25519/std", "serde?/std", "sha2/std"]
asm = ["sha2/asm"]
batch = ["alloc", "merlin", "rand_core"]
digest = []
# This features turns off stricter checking for scalar malleability in signatures
legacy_compatibility = []
pkcs8 = ["ed25519/pkcs8"]

View file

@ -48,6 +48,7 @@ pub(crate) enum InternalError {
length_c: usize,
},
/// An ed25519ph signature can only take up to 255 octets of context.
#[cfg(feature = "digest")]
PrehashedContextLength,
/// A mismatched (public, secret) key pair.
MismatchedKeypair,
@ -76,6 +77,7 @@ impl Display for InternalError {
{} has length {}, {} has length {}.",
na, la, nb, lb, nc, lc
),
#[cfg(feature = "digest")]
InternalError::PrehashedContextLength => write!(
f,
"An ed25519ph signature can only take up to 255 octets of context"

View file

@ -262,6 +262,7 @@ mod signature;
mod signing;
mod verifying;
#[cfg(feature = "digest")]
pub use curve25519_dalek::digest::Digest;
#[cfg(feature = "batch")]

View file

@ -24,6 +24,7 @@ use serde_bytes::{ByteBuf as SerdeByteBuf, Bytes as SerdeBytes};
use sha2::Sha512;
#[cfg(feature = "digest")]
use curve25519_dalek::digest::generic_array::typenum::U64;
use curve25519_dalek::digest::Digest;
use curve25519_dalek::edwards::CompressedEdwardsY;
@ -208,12 +209,15 @@ impl SigningKey {
///
/// # Examples
///
#[cfg_attr(feature = "rand_core", doc = "```")]
#[cfg_attr(not(feature = "rand_core"), doc = "```ignore")]
#[cfg_attr(all(feature = "rand_core", feature = "digest"), doc = "```")]
#[cfg_attr(
any(not(feature = "rand_core"), not(feature = "digest")),
doc = "```ignore"
)]
/// use ed25519_dalek::Digest;
/// use ed25519_dalek::SigningKey;
/// use ed25519_dalek::Sha512;
/// use ed25519_dalek::Signature;
/// use sha2::Sha512;
/// use rand::rngs::OsRng;
///
/// # #[cfg(feature = "std")]
@ -253,13 +257,16 @@ impl SigningKey {
/// Let's add a context for good measure (remember, you'll want to choose
/// your own!):
///
#[cfg_attr(feature = "rand_core", doc = "```")]
#[cfg_attr(not(feature = "rand_core"), doc = "```ignore")]
#[cfg_attr(all(feature = "rand_core", feature = "digest"), doc = "```")]
#[cfg_attr(
any(not(feature = "rand_core"), not(feature = "digest")),
doc = "```ignore"
)]
/// # use ed25519_dalek::Digest;
/// # use ed25519_dalek::SigningKey;
/// # use ed25519_dalek::Signature;
/// # use ed25519_dalek::SignatureError;
/// # use ed25519_dalek::Sha512;
/// # use sha2::Sha512;
/// # use rand::rngs::OsRng;
/// #
/// # fn do_test() -> Result<Signature, SignatureError> {
@ -286,6 +293,7 @@ impl SigningKey {
///
/// [rfc8032]: https://tools.ietf.org/html/rfc8032#section-5.1
/// [terrible_idea]: https://github.com/isislovecruft/scripts/blob/master/gpgkey2bc.py
#[cfg(feature = "digest")]
pub fn sign_prehashed<D>(
&self,
prehashed_message: D,
@ -327,13 +335,16 @@ impl SigningKey {
///
/// # Examples
///
#[cfg_attr(feature = "rand_core", doc = "```")]
#[cfg_attr(not(feature = "rand_core"), doc = "```ignore")]
#[cfg_attr(all(feature = "rand_core", feature = "digest"), doc = "```")]
#[cfg_attr(
any(not(feature = "rand_core"), not(feature = "digest")),
doc = "```ignore"
)]
/// use ed25519_dalek::Digest;
/// use ed25519_dalek::SigningKey;
/// use ed25519_dalek::Signature;
/// use ed25519_dalek::SignatureError;
/// use ed25519_dalek::Sha512;
/// use sha2::Sha512;
/// use rand::rngs::OsRng;
///
/// # fn do_test() -> Result<(), SignatureError> {
@ -369,6 +380,7 @@ impl SigningKey {
/// ```
///
/// [rfc8032]: https://tools.ietf.org/html/rfc8032#section-5.1
#[cfg(feature = "digest")]
pub fn verify_prehashed<D>(
&self,
prehashed_message: D,
@ -724,6 +736,7 @@ impl ExpandedSecretKey {
/// a `SignatureError`.
///
/// [rfc8032]: https://tools.ietf.org/html/rfc8032#section-5.1
#[cfg(feature = "digest")]
#[allow(non_snake_case)]
pub(crate) fn sign_prehashed<'a, D>(
&self,

View file

@ -13,6 +13,7 @@ use core::convert::TryFrom;
use core::fmt::Debug;
use core::hash::{Hash, Hasher};
#[cfg(feature = "digest")]
use curve25519_dalek::digest::generic_array::typenum::U64;
use curve25519_dalek::digest::Digest;
use curve25519_dalek::edwards::CompressedEdwardsY;
@ -21,7 +22,7 @@ use curve25519_dalek::scalar::Scalar;
use ed25519::signature::Verifier;
pub use sha2::Sha512;
use sha2::Sha512;
#[cfg(feature = "pkcs8")]
use ed25519::pkcs8::{self, DecodePublicKey};
@ -206,6 +207,7 @@ impl VerifyingKey {
///
/// Returns `true` if the `signature` was a valid signature created by this
/// `Keypair` on the `prehashed_message`.
#[cfg(feature = "digest")]
#[allow(non_snake_case)]
pub fn verify_prehashed<D>(
&self,
@ -350,6 +352,7 @@ impl VerifyingKey {
///
/// Returns `true` if the `signature` was a valid signature created by this
/// `Keypair` on the `prehashed_message`.
#[cfg(feature = "digest")]
#[allow(non_snake_case)]
pub fn verify_prehashed_strict<D>(
&self,

View file

@ -14,6 +14,7 @@ use curve25519_dalek;
use ed25519_dalek::*;
use hex::FromHex;
#[cfg(feature = "digest")]
use hex_literal::hex;
#[cfg(test)]
@ -96,8 +97,9 @@ mod vectors {
}
// From https://tools.ietf.org/html/rfc8032#section-7.3
#[cfg(feature = "digest")]
#[test]
fn ed25519ph_rf8032_test_vector() {
fn ed25519ph_rf8032_test_vector_prehash() {
let sec_bytes = hex!("833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42");
let pub_bytes = hex!("ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf");
let msg_bytes = hex!("616263");
@ -234,6 +236,7 @@ mod vectors {
// Identical to repudiation() above, but testing verify_prehashed against
// verify_prehashed_strict. See comments above for a description of what's happening.
#[cfg(feature = "digest")]
#[test]
fn repudiation_prehash() {
let message1 = Sha512::new().chain_update(b"Send 100 USD to Alice");
@ -282,6 +285,7 @@ mod vectors {
mod integrations {
use super::*;
use rand::rngs::OsRng;
#[cfg(feature = "digest")]
use sha2::Sha512;
use std::collections::HashMap;
@ -328,6 +332,7 @@ mod integrations {
);
}
#[cfg(feature = "digest")]
#[test]
fn ed25519ph_sign_verify() {
let signing_key: SigningKey;