ed25519: implement MultipartSigner/Verifier (#764)

This commit is contained in:
daxpedda 2025-07-14 16:41:20 +02:00 committed by GitHub
parent fc8a8a5276
commit c3f91f7620
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 38 additions and 12 deletions

View file

@ -142,7 +142,7 @@ pub fn raw_sign<CtxDigest>(
where
CtxDigest: Digest<OutputSize = U64>,
{
esk.raw_sign::<CtxDigest>(message, verifying_key)
esk.raw_sign::<CtxDigest>(&[message], verifying_key)
}
/// Compute a signature over the given prehashed message, the Ed25519ph algorithm defined in
@ -230,7 +230,7 @@ pub fn raw_verify<CtxDigest>(
where
CtxDigest: Digest<OutputSize = U64>,
{
vk.raw_verify::<CtxDigest>(message, signature)
vk.raw_verify::<CtxDigest>(&[message], signature)
}
/// The batched Ed25519 verification check, rejecting non-canonical R values. `MsgDigest` is the

View file

@ -29,7 +29,7 @@ use curve25519_dalek::{
scalar::Scalar,
};
use ed25519::signature::{KeypairRef, Signer, Verifier};
use ed25519::signature::{KeypairRef, MultipartSigner, MultipartVerifier, Signer, Verifier};
#[cfg(feature = "digest")]
use crate::context::Context;
@ -568,6 +568,12 @@ impl KeypairRef for SigningKey {
impl Signer<Signature> for SigningKey {
/// Sign a message with this signing key's secret key.
fn try_sign(&self, message: &[u8]) -> Result<Signature, SignatureError> {
self.try_multipart_sign(&[message])
}
}
impl MultipartSigner<Signature> for SigningKey {
fn try_multipart_sign(&self, message: &[&[u8]]) -> Result<Signature, SignatureError> {
let expanded: ExpandedSecretKey = (&self.secret_key).into();
Ok(expanded.raw_sign::<Sha512>(message, &self.verifying_key))
}
@ -615,6 +621,16 @@ impl Verifier<Signature> for SigningKey {
}
}
impl MultipartVerifier<Signature> for SigningKey {
fn multipart_verify(
&self,
message: &[&[u8]],
signature: &Signature,
) -> Result<(), SignatureError> {
self.verifying_key.multipart_verify(message, signature)
}
}
impl From<SecretKey> for SigningKey {
#[inline]
fn from(secret: SecretKey) -> Self {
@ -829,7 +845,7 @@ impl ExpandedSecretKey {
#[inline(always)]
pub(crate) fn raw_sign<CtxDigest>(
&self,
message: &[u8],
message: &[&[u8]],
verifying_key: &VerifyingKey,
) -> Signature
where
@ -838,7 +854,7 @@ impl ExpandedSecretKey {
// OK unwrap, update can't fail.
self.raw_sign_byupdate(
|h: &mut CtxDigest| {
h.update(message);
message.iter().for_each(|slice| h.update(slice));
Ok(())
},
verifying_key,

View file

@ -19,7 +19,7 @@ use curve25519_dalek::{
scalar::Scalar,
};
use ed25519::signature::Verifier;
use ed25519::signature::{MultipartVerifier, Verifier};
use sha2::Sha512;
@ -200,7 +200,7 @@ impl VerifyingKey {
#[allow(non_snake_case)]
pub(crate) fn raw_verify<CtxDigest>(
&self,
message: &[u8],
message: &[&[u8]],
signature: &ed25519::Signature,
) -> Result<(), SignatureError>
where
@ -245,7 +245,7 @@ impl VerifyingKey {
let message = prehashed_message.finalize();
let expected_R = RCompute::<CtxDigest>::compute(self, signature, Some(ctx), &message);
let expected_R = RCompute::<CtxDigest>::compute(self, signature, Some(ctx), &[&message]);
if expected_R == signature.R {
Ok(())
@ -371,7 +371,7 @@ impl VerifyingKey {
return Err(InternalError::Verify.into());
}
let expected_R = RCompute::<Sha512>::compute(self, signature, None, message);
let expected_R = RCompute::<Sha512>::compute(self, signature, None, &[message]);
if expected_R == signature.R {
Ok(())
} else {
@ -447,7 +447,7 @@ impl VerifyingKey {
}
let message = prehashed_message.finalize();
let expected_R = RCompute::<Sha512>::compute(self, signature, Some(ctx), &message);
let expected_R = RCompute::<Sha512>::compute(self, signature, Some(ctx), &[&message]);
if expected_R == signature.R {
Ok(())
@ -508,10 +508,10 @@ where
key: &VerifyingKey,
signature: InternalSignature,
prehash_ctx: Option<&[u8]>,
message: &[u8],
message: &[&[u8]],
) -> CompressedEdwardsY {
let mut c = Self::new(key, signature, prehash_ctx);
c.update(message);
message.iter().for_each(|slice| c.update(slice));
c.finish()
}
@ -561,6 +561,16 @@ impl Verifier<ed25519::Signature> for VerifyingKey {
///
/// Returns `Ok(())` if the signature is valid, and `Err` otherwise.
fn verify(&self, message: &[u8], signature: &ed25519::Signature) -> Result<(), SignatureError> {
self.multipart_verify(&[message], signature)
}
}
impl MultipartVerifier<ed25519::Signature> for VerifyingKey {
fn multipart_verify(
&self,
message: &[&[u8]],
signature: &ed25519::Signature,
) -> Result<(), SignatureError> {
self.raw_verify::<Sha512>(message, signature)
}
}