mirror of
https://github.com/RustCrypto/signatures
synced 2026-06-21 13:45:42 +00:00
Implement Hash on non-secret Signature and VerifyingKey types (#1309)
Per #1229: Signature and public-key types lack `Hash`, which prevents use in `HashMap` / `HashSet` keys and similar collections. - ecdsa: Signature, DER Signature, SignatureWithOid - ed25519: Signature, pkcs8::PublicKeyBytes - ed448: Signature, pkcs8::PublicKeyBytes - ml-dsa: Signature, VerifyingKey - slh-dsa: Signature, VerifyingKey Where a trivial derive works (ed25519, ed448), uses derive. Where generic bounds or upstream gaps require it, uses a manual impl over the canonical serialized bytes (`to_bytes` / `encode` / `as_bytes`), which is the natural Hash domain for these types anyway. Closes #1229
This commit is contained in:
@@ -151,6 +151,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> core::hash::Hash for Signature<C>
|
||||
where
|
||||
C: EcdsaCurve,
|
||||
MaxSize<C>: ArraySize,
|
||||
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArraySize,
|
||||
{
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
self.as_bytes().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> AsRef<[u8]> for Signature<C>
|
||||
where
|
||||
C: EcdsaCurve,
|
||||
|
||||
@@ -398,6 +398,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> core::hash::Hash for Signature<C>
|
||||
where
|
||||
C: EcdsaCurve,
|
||||
SignatureSize<C>: ArraySize,
|
||||
{
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
self.to_bytes().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> fmt::LowerHex for Signature<C>
|
||||
where
|
||||
C: EcdsaCurve,
|
||||
@@ -667,6 +677,18 @@ where
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(feature = "digest")]
|
||||
impl<C> core::hash::Hash for SignatureWithOid<C>
|
||||
where
|
||||
C: EcdsaCurve,
|
||||
SignatureSize<C>: ArraySize,
|
||||
{
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
self.signature.hash(state);
|
||||
self.oid.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "digest")]
|
||||
impl<C> From<SignatureWithOid<C>> for Signature<C>
|
||||
where
|
||||
|
||||
+1
-1
@@ -316,7 +316,7 @@ pub type SignatureBytes = [u8; Signature::BYTE_SIZE];
|
||||
///
|
||||
/// Signature verification libraries are expected to reject invalid field
|
||||
/// elements at the time a signature is verified.
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Eq, Hash, PartialEq)]
|
||||
#[cfg_attr(
|
||||
feature = "zerocopy",
|
||||
derive(FromBytes, IntoBytes, Immutable, KnownLayout, Unaligned)
|
||||
|
||||
@@ -229,7 +229,7 @@ impl str::FromStr for KeypairBytes {
|
||||
///
|
||||
/// Note that this type operates on raw bytes and performs no validation that
|
||||
/// public keys represent valid compressed Ed25519 y-coordinates.
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||
#[cfg_attr(
|
||||
feature = "zerocopy",
|
||||
derive(IntoBytes, FromBytes, Unaligned, KnownLayout, Immutable,)
|
||||
|
||||
+1
-1
@@ -115,7 +115,7 @@ pub type SignatureBytes = [u8; Signature::BYTE_SIZE];
|
||||
///
|
||||
/// Signature verification libraries are expected to reject invalid field
|
||||
/// elements at the time a signature is verified.
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Eq, Hash, PartialEq)]
|
||||
#[repr(C)]
|
||||
pub struct Signature {
|
||||
R: ComponentBytes,
|
||||
|
||||
+1
-1
@@ -205,7 +205,7 @@ impl fmt::Debug for KeypairBytes {
|
||||
///
|
||||
/// Note that this type operates on raw bytes and performs no validation that
|
||||
/// public keys represent valid compressed Ed448 y-coordinates.
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||
pub struct PublicKeyBytes(pub [u8; Self::BYTE_SIZE]);
|
||||
|
||||
impl PublicKeyBytes {
|
||||
|
||||
@@ -151,6 +151,12 @@ impl<P: MlDsaParams> signature::SignatureEncoding for Signature<P> {
|
||||
type Repr = EncodedSignature<P>;
|
||||
}
|
||||
|
||||
impl<P: MlDsaParams> core::hash::Hash for Signature<P> {
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
self.encode().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
struct MuBuilder(H);
|
||||
|
||||
impl MuBuilder {
|
||||
@@ -834,6 +840,12 @@ impl<P: MlDsaParams> VerifyingKey<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: MlDsaParams> core::hash::Hash for VerifyingKey<P> {
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
self.encode().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: MlDsaParams> signature::Verifier<Signature<P>> for VerifyingKey<P> {
|
||||
fn verify(&self, msg: &[u8], signature: &Signature<P>) -> Result<(), Error> {
|
||||
self.multipart_verify(&[msg], signature)
|
||||
|
||||
@@ -71,6 +71,12 @@ impl<P: ParameterSet> Signature<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: ParameterSet> core::hash::Hash for Signature<P> {
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
self.to_bytes().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: ParameterSet> TryFrom<&[u8]> for Signature<P> {
|
||||
type Error = Error;
|
||||
|
||||
|
||||
@@ -136,6 +136,12 @@ impl<P: ParameterSet + VerifyingKeyLen> VerifyingKey<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: ParameterSet> core::hash::Hash for VerifyingKey<P> {
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
self.to_bytes().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: ParameterSet> Clone for VerifyingKey<P> {
|
||||
fn clone(&self) -> Self {
|
||||
VerifyingKey {
|
||||
|
||||
Reference in New Issue
Block a user