Both the C and Java backends of this crate implement "ref10" validation criteria, i.e. the ones used by the original implementation of Ed25519 extracted from SUPERCOP.
The README of this crate notes that Ed25519 is described in RFC8032, however the validation criteria in the RFC differ from "ref10" in that they require all encoded field elements (i.e. base and scalar field elements) are canonical, i.e. the coordinate of R is less than p and s is less than l.
The goal of this change was to prevent malleability, however the handling of torsion components is un(der)specified in that it says implementations can effectively pick their own rules. This means some implementations allow malleability in the form of torsion components and different RFC8032-conforming implementations can make different decisions about which signatures are valid, as criticized in the blog post "It's 255:19AM. Do you know what your validation criteria are?".
I'll further note the README of this crate doesn't actually claim it conforms to RFC8032, only where one can find a specification about it. We've had suggestions to change our validation criteria away from "ref10" to RFC8032 (#54), however this crate is nearly a decade old (longer if you count the previous red25519 crate it descended from which predates RFC8032) and changing the validation criteria at this point would change the set of accepted signatures and in that regard can be considered a breaking change.
So, the question is: should we actually change our validation criteria at this point? I think one of two things should happen:
- We should either keep "ref10" validation criteria and document where we diverge from the RFC
- We should adopt RFC8032 validation criteria and update the README to say we actually implement the RFC, in which case both the C and Java backends need to be updated accordingly
The "255:19AM" blog post makes the case for ZIP-215 validation criteria which goes effectively in the reverse direction from RFC8032: it accepts certain non-canonical point encodings and uses cofactored verification, thereby permitting signatures involving points with torsion components.
I'm somewhat loathe to change the existing validation criteria without a major version bump. We could instead potentially introduce verify_strict or verify_rfc8032 which adds the additional checks, which could be implemented in pure Ruby, and then calls into the native extension(s).
Edit: I should probably also note that while "signature malleability" sounds scary, its security impact is highly application-dependent. For many ordinary uses of digital signatures it has little practical consequence. The extent to which it is worth addressing highly depends on the intended use case, i.e. does the application hash signatures and try to use the hash as some sort of identifier, which is a somewhat questionable thing to do vs using key fingerprints and/or hashes of the signed content as identifiers instead.
Both the C and Java backends of this crate implement "ref10" validation criteria, i.e. the ones used by the original implementation of Ed25519 extracted from SUPERCOP.
The README of this crate notes that Ed25519 is described in RFC8032, however the validation criteria in the RFC differ from "ref10" in that they require all encoded field elements (i.e. base and scalar field elements) are canonical, i.e. the coordinate of
Ris less thanpandsis less thanl.The goal of this change was to prevent malleability, however the handling of torsion components is un(der)specified in that it says implementations can effectively pick their own rules. This means some implementations allow malleability in the form of torsion components and different RFC8032-conforming implementations can make different decisions about which signatures are valid, as criticized in the blog post "It's 255:19AM. Do you know what your validation criteria are?".
I'll further note the README of this crate doesn't actually claim it conforms to RFC8032, only where one can find a specification about it. We've had suggestions to change our validation criteria away from "ref10" to RFC8032 (#54), however this crate is nearly a decade old (longer if you count the previous
red25519crate it descended from which predates RFC8032) and changing the validation criteria at this point would change the set of accepted signatures and in that regard can be considered a breaking change.So, the question is: should we actually change our validation criteria at this point? I think one of two things should happen:
The "255:19AM" blog post makes the case for ZIP-215 validation criteria which goes effectively in the reverse direction from RFC8032: it accepts certain non-canonical point encodings and uses cofactored verification, thereby permitting signatures involving points with torsion components.
I'm somewhat loathe to change the existing validation criteria without a major version bump. We could instead potentially introduce
verify_strictorverify_rfc8032which adds the additional checks, which could be implemented in pure Ruby, and then calls into the native extension(s).Edit: I should probably also note that while "signature malleability" sounds scary, its security impact is highly application-dependent. For many ordinary uses of digital signatures it has little practical consequence. The extent to which it is worth addressing highly depends on the intended use case, i.e. does the application hash signatures and try to use the hash as some sort of identifier, which is a somewhat questionable thing to do vs using key fingerprints and/or hashes of the signed content as identifiers instead.