* [WIP] ed25519-dalek: bump `ed25519` crate dependency to v3.0.0
This has two test failures:
serialisation::serialize_deserialize_signature_json
serialisation::serialize_signature_size
These are due to a last minute change to use `serdect` for implementing
`serde` support: RustCrypto/signatures#1324.
The signature size regression from `64` to `72` is a deliberate tradeoff
we've accepted in `serdect`. First note that this test is for now the
unmaintained `bincode` crate.
The core problem is that `serde` does not actually provide fixed-size
arrays as a type within its data model (serde-rs/serde#1937) and you're
instead left faking it using `SerializeTuple` and serializing it a
byte-at-a-time as a tuple. While this gives optimal-sized results on
`bincode`, it gives less-than-optimal results on e.g. `rmp-serde` where
the bytes each end up tagged with a type prefix.
`serde` does provide portable APIs for using optimal format-specific
byte encodings, but they carry an additional length prefix, which is
unnecessary and suboptimal for something fixed-width like an Ed25519
signature, but alas as noted earlier `serde` does not actually have
fixed-width arrays in its data model.
The second test failure occurs specifically because `serdect`
introspects the format and uses `base16ct` to perform hex serialization
for human readable formats. While this is a readability improvement for
these formats (and also makes them easier to implement in constant-time,
though it's not relevant here), the drawback is it currently requires
the `alloc` feature for such formats, which is a regression:
Error("serializer is human readable, which requires the `alloc` crate feature", line: 0, column: 0)
Note that regardless these are both breaking changes to how `serde`
serialization is handled.
See also:
- RustCrypto/formats#1111
- RustCrypto/formats#1112
- dalek-cryptography/ed25519-dalek#140
* Migrate bincode -> postcard
* Bump `serdect` to v0.4.3
Includes `no_alloc` hex serialization support
---------
Co-authored-by: Michael Rosenberg <mrosenberg@cloudflare.com>
Adds a table of low order points, adapted from
https://cr.yp.to/ecdh.html, which suggests that non-Diffie-Hellman
protocols that depend on "contributory" behavior should reject them.
They're also useful for testing, e.g. how a protocol implementation
handles them during a key exchange (noting that a well-implemented AKE
shouldn't need to explicitly reject them, as someone attempting to use
them for MitM should be spotted as a transcript mismatch).
Most of the changes in this PR are actually from the associated `rand`
crate updates which are happening in rust-random/rand#1697, notably
`OsRng` has been renamed to `SysRng` (and is now provided by the
`getrandom` crate).
We do use some `rand_core` APIs in a few places though, like the STROBE
implementation, where this migrates from `rand_core::le` to
`rand_core::utils`.
Prior to a final stable release of the @RustCrypto dependencies used by
the dalek crates, we are going to target `rand_core` v0.10.
This updates the `rand` and `rand_core` dependencies as well as the
aforementioned @RustCrypto dependencies to be compatible with
`rand_core` v0.10, which incurred a few API changes:
- `rand_core` no longer includes `OsRng`, so this replaces the `os_rng`
features with `getrandom` features (same thing we did for @RustCrypto)
which uses the `getrandom` crate directly
- For `dev-dependencies` it just migrates straight to `rand`, replacing
`rand_chacha` with the `chacha` feature of `rand` (which pulls in
`chacha20`), and sourcing `OsRng` from `rand`, its new home (for now)
This PR also switches to using the `rustcrypto-ff`/`rustcrypto-group` crates
(hopefully temporary) which are forks of `ff` and `group` which have crate
releases that have been updated to use `rand_core` v0.10.0 prereleases.
Enforced via the newly added `clippy::mod_module_files` lint.
Previously a mixture of 2015 (`mod.rs`) module files along with
the 2018 `foo.rs` and `foo/` approach.
All of the toplevel modules (`edwards`, `field`, `montgomery`, and
`scalar`) were using the 2018 convention, except for `backend`,
`ristretto`, and the recently added `lizard` were using the 2015
convention.
This renames the files so everything follows the 2018 convention, and
applies the afforementioned clippy lint which will error if anyone tries
to add new files using the 2015 convention.
* Vendor lizard hash to curve from Signal
* Add invalid Lizard encoding test
* Added lizard details to readme and changelog
* Upgrade ristretto.sage to Python3
* Add lizard test vector generation to ristretto.sage
* Added map_to_curve and its inverse
* Use CtOption instead of bitmasks; other cleanup
* Add README to lizard folder
* Split map_to_curve into map_to_curve and map_to_curve_restricted; make its inverse return 16 elements
* Consolidate Ristretto Elligator functions into its own file
* Rename hash_to_curve as encode_to_curve
* Implement the inline description of the standard.
* Generalise map_to_field to return an arbitrary number of field elements.
* Implement hash_to_curve as defined in the standard.
* Put elligator behind the "digest" feature.
* Add warning on non-uniformity of `encode_to_curve`.
* Remove the need of Vec for hash_to_field.
* Apply suggestions from code review
* Refactor expand_message_xmd out of hash_to_field
* Add hash-to-curve to benches
* Constraint COUNT to 1 or 2; add note on secure hash function usage
* Correct hash function usage in encode- and hash-to-curve
---------
Co-authored-by: Armando Faz <armfazh@users.noreply.github.com>
Co-authored-by: Michael Rosenberg <mrosenberg@cloudflare.com>
* [WIP] Scalar::div_by_2
* debug_assert that carry is 0
* revise tests
* Test multiply by half scalar, double and compress (#804)
* Test `div_by_2` with `proptest` (#806)
---------
Co-authored-by: daxpedda <daxpedda@gmail.com>
This represents the first breaking change in a new release series,
bumping all crates to the 2024 edition of Rust.
As such, the version numbers of all crates have been incremented to
represent a new prerelease series:
- `curve25519-dalek`: v5.0.0-pre
- `ed25519-dalek`: v3.0.0-pre
- `x25519-dalek`: v3.0.0-pre
Note that this commit isn't intended to cut associated crate releases of
these on crates.io, but is merely bumping the version numbers to denote
there are pending breaking changes.
This commit also includes rustfmt changes which were made as part of the
2024 edition.
Also includes clippy fixes.
* Implementation of `hash_to_field` as defined in the standard
* Implementation of `hash_to_curve` as defined in the standard, by changing the mechanism over which we chose the sign.
* For the point above, had to change the `elligator_encode` to return whether `eps` is a square or not (required for `hash_to_curve`).
* Included test vectors of the draft.
* Included `FieldElement::from_bytes_wide(bytes: &u8; 64])` to reduce integers encoded in 64 bytes.
* curve: extract `AffinePoint` type
Based on discussions about `elliptic-curve` trait impls in #746, and
observing a similar type in `ed448-goldilocks` which inspired this one
(not to mention in all of the @RustCrypto elliptic curve crates), adds
an `AffinePoint` type with `x` and `y` coordinates.
For now, the type is kept out of the public API, and used as an
implementation detail for point compression. However, it's been written
with the intent of eventually stabilizing and exposing it. It's been
marked `pub` so unused functionality doesn't automatically trigger dead
code lints.
Further work could include refactoring point decompression to first
produce an `AffinePoint` and then convert to extended twisted Edwards
coordinates (i.e. `EdwardsPoint`), which is more or less what the
existing `step_1` and `step_2` functions do (`step_1` technically
produces projective coordinates, but `Z` is always set to `ONE`).
* Update curve25519-dalek/src/edwards.rs
* curve: rename `FieldElement*::as_bytes` => `::to_bytes`
Methods named `as_*` should perform a zero-cost borrowing conversion:
https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv
Methods named `to_*` can perform an expensive owned conversion.
Since the `FieldElement*` types are technically part of the public API
(but feature gated), this also preserves the old names with a
deprecation. We can remove them in the next breaking release.
The same change was also made to the backend `Scalar*` types, however
these types are not a part of the public API.
* curve: add `EdwardsPoint::compress_batch` and `::random`
We've had various requests to implement batch point compression for
`EdwardsPoint`, e.g. #705.
We can leverage `FieldElement::batch_invert` to implement it, which
results in a fairly significant speedup.
The name `EdwardsPoint::compress_batch` has been chosen to match
`RistrettoPoint::double_and_compress_batch`.
For benchmarking, randomized `EdwardsPoint`s have been used. To obtain
these, an inherent `EdwardsPoint::random` has been extracted from the
existing `Group::random` implementation, which uses rejection sampling.
`Group::random` has been updated to call the inherent
`EdwardsPoint::random`. This avoids a `group` dependency just to run the
batch compression benchmarks.
The following benchmark results have been obtained:
edwards benches/EdwardsPoint compression
time: [3.5029 µs 3.5098 µs 3.5171 µs]
edwards benches/Batch EdwardsPoint compression/1
time: [3.6698 µs 3.6758 µs 3.6817 µs]
edwards benches/Batch EdwardsPoint compression/2
time: [3.8410 µs 3.8461 µs 3.8516 µs]
edwards benches/Batch EdwardsPoint compression/4
time: [4.1534 µs 4.1961 µs 4.2558 µs]
edwards benches/Batch EdwardsPoint compression/8
time: [4.8466 µs 4.8533 µs 4.8600 µs]
edwards benches/Batch EdwardsPoint compression/16
time: [6.1216 µs 6.1315 µs 6.1410 µs]
As you can see, it affords a fairly significant speedup, batch
compressing 16 points in less time than the standard point compression
algorithm would take to compress 2 in a row.
The build is currently broken because it's been stabilized:
error: the feature `avx512_target_feature` has been stable since 1.89.0-nightly and no longer requires an attribute to enable
* Make AVX512IFMA opt-in backend
* Updated README to have backend info
* Added entry to changelog
---------
Co-authored-by: Michael Rosenberg <michael@mrosenberg.pub>
Alternative to #659/#661 and #662 which leverages `subtle::Choice` and
`subtle::ConditionallySelectable` as the optimization barriers.
Really the previous masking was there to conditionally add the scalar
field modulus on underflow, so instead of that, we can conditionally
select zero or the modulus using a `Choice` constructed from the
underflow bit.
Replaces the security mitigation added in #659 and #661 for
masking-related timing variability which used an inline `black_box`
using the recently added `subtle::BlackBox` newtype (see
dalek-cryptography/subtle#123)
Internally `BlackBox` uses a volatile read by default (i.e. same
strategy which was used before) or when the `core_hint_black_box`
feature of `subtle` is enabled, it uses `core::hint::black_box`
(whose documentation was recently updated to reflect the nuances of
potential cryptographic use, see rust-lang/rust#126703)
This PR goes ahead and uses `BlackBox` for both `mask` and
`underflow_mask` where previously it was only used on `underflow_mask`.
The general pattern of bitwise masking inside a loop seems worrisome for
the optimizer potentially inserting branches in the future.
Below are godbolt inspections of the generated assembly, which are free
of the `jns` instructions originally spotted in #659/#661:
- 32-bit (read_volatile): https://godbolt.org/z/TKo9fqza4
- 32-bit (hint::black_box): https://godbolt.org/z/caoMxYbET
- 64-bit (read_volatile): https://godbolt.org/z/PM6zKjj1f
- 64-bit (hint::black_box): https://godbolt.org/z/nseaPvdWv
Similar security fix to #659, but for the 32-bit backend. See that PR
for more information about the problem. Relevant compiler outputs (thanks to @tarcieri):
Without fix
https://godbolt.org/z/zvaWxzvqv
Notice the `jns` ("jump if not sign") instruction on line 106.
With fix
https://godbolt.org/z/jc9j7eb8E