Previously, we were checking that the highest 3 bits were unset, which still
leaves 2^253 - 2^252 + 27742317777372353535851937790883648493 potential scalars
for the `s` component of a signature which are not strictly mod \ell.
This change fixes that.
Note: This change makes ed25519-dalek incompatible with ed25519-donna in that
some signatures produced by donna will be verifiable by donna but NOT VERIFIABLE
by dalek. On the other hand, libsodium exports a -DED25519_COMPAT feature,
which when enabled, means it is compatible with dalek with the
`legacy_compatibility` feature disabled. Otherwise, libsodium's behaviour is
identical to the behaviour enabled by default in this patch.
* ADD new "batch" feature for feature-gating ed25519 batch verification; off by
default. The "batch" feature is the only thing which depends on all of the
`rand` crate, since it requires the functionality of `rand::thread_rng()`.
Without batch verification, the rest of ed25519-dalek only depends on
`rand_os` and `rand_core`.
This implements https://github.com/dalek-cryptography/ed25519-dalek/issues/64
You can still choose the "prehash" algorithm, as long as it has 64 bytes of
output. Otherwise, everything is hardcoded to use sha2::Sha512. To use a
different implementation you'll need a [patch.crates-io] section in cargo
config.
This caches the public key internally so that we effectively get a free
speedup on key reuse in regular signature verification, similar to that in
batch verification. (However, this also "speeds up"¹ batch verifications.)
¹ Less of a speed up than moving the computation elsewhere, but the speed up
on reuse still also applies to key reuse for batch verification.
Unfortunately the serialised size is likely never going to be the same
as the type's size in memory, as most serialisation formats define
additional headers for parsing safety reasons, such as buffer lengths
and type information.
generic_array v0.12 no longer serializes GenericArray as a Vec,
which reduces the serialized size of PublicKey, Signature, and
SecretKey by 8 bytes. Now that generic_array has been upgraded,
these tests simply ensure the serialization size doesn't change
in the future.
The API for this isn't the greatest and I apologise for that. Suggestions for
improvement welcome. One thing which @hdevalence and I considered was to
change the function signature to:
pub fn verify_batch<D, C, M, S, K>(messages: M,
signatures: S,
public_keys: K,
csprng: &mut C) -> Result<(), SignatureError>
where D: Digest<OutputSize = U64> + Default,
C: Rng + CryptoRng,
M: IntoIterator<Item = &[u8]>,
S: IntoIterator,
S::Item: Borrow<Signature>,
K: IntoIterator,
K::Item: Borrow<Signature>,
The other improvement which could be made is to implement 128-bit scalars for
the randomnesses.
* CLOSES#27
This also simplifies the verification logic. Because the verification check
happens in variable time, we don't need to do a constant-time eq check at the
end, so we can drop the `subtle` dependency entirely.
The `DecodingError` type becomes `SignatureError` and is also used to
signal failing verifications.
This code was significantly based off without boats' error types in
commit 6c1acaca7c, and also upon
conversation with them. Please target them with praise, and blame me
for whatever mistakes I might have made.
Advantages of a custom error type:
- It can be more easily integrated into other error types by clients;
they can implement From<FromBytesError> for their error types, or
they can use a library like failure.
- It is a zero-sized type, which can enable some representational
optimizations.
- It can be easier and more stable to test for.