Conversation
The wNAF implementation assumes a little endian representation for scalars, but `PrimeField::to_repr` returns an opaque representation which may be big endian and is in the case of our implementations of the NIST P-curves. RustCrypto/ff#10 added a stopgap API: `PrimeField::to_le_repr`, which is guaranteed to return a little endian representation. This commit switches `(rustcrypto-)group` to use it, which should make it compatible with our curves which otherwise use a big endian SEC1 representation.
PrimeField::to_le_repr for scalarsPrimeField::to_le_repr for scalars
Member
Author
|
Confirmed this is working against cc @str4d |
tarcieri
added a commit
to RustCrypto/elliptic-curves
that referenced
this pull request
Apr 8, 2026
RustCrypto/group#12 included a workaround that allows curves with a big endian `PrimeField::Repr` to be used for wNAF, by defining a separate `PrimeField::to_le_repr` method which is always guaranteed to be little endian. This may not be the permanent solution to this problem which gets upstreamed, but it unblocks work for now. This commit adds the relevant impls of `to_le_repr`, along with initial `WnafGroup` impls to `ProjectivePoint` in `k256` and `primeorder` (currently hardcoded to a fixed constant of `4` for now to unblock additional work). This also adds a `ProjectivePoint::wnaf` static method to obtain a wNAF context for that particular curve group, feature-gated on `alloc`. Finally, it adds a smoke test to `p256` which checks it against our scalar multiplication test vectors, however it does not check any other curves yet and probably should.
tarcieri
added a commit
to RustCrypto/elliptic-curves
that referenced
this pull request
Apr 8, 2026
RustCrypto/group#12 included a workaround that allows curves with a big endian `PrimeField::Repr` to be used for wNAF, by defining a separate `PrimeField::to_le_repr` method which is always guaranteed to be little endian. This may not be the permanent solution to this problem which gets upstreamed, but it unblocks work for now. This commit adds the relevant impls of `to_le_repr`, along with initial `WnafGroup` impls to `ProjectivePoint` in `k256` and `primeorder` (currently hardcoded to a fixed constant of `4` for now to unblock additional work). This also adds a `ProjectivePoint::wnaf` static method to obtain a wNAF context for that particular curve group, feature-gated on `alloc`. Finally, it adds a smoke test to `p256` which checks it against our scalar multiplication test vectors, however it does not check any other curves yet and probably should.
tarcieri
added a commit
to RustCrypto/utils
that referenced
this pull request
May 15, 2026
Adds a crate providing a `&BitSlice`/`&mut BitSlice` type which is constructable from `&[u8]` but provides slicing at the granularity of individual bits. The name of the crate is a play on `bitvec`, which provides a similar type. However, the implementation in this crate is significantly simpler with a much smaller code surface and minimal use of `unsafe` code. The implementation is a generalization of RustCrypto/formats#2300 which sought to implement a similar data structure as a reference type for representing ASN.1 BIT STRINGs. However, using this approach was deferred because the implementation relies on a conversion which is sound under Tree Borrows (as verified by Miri) but unsound under Stacked Borrows as it loses provenance. See rust-lang/unsafe-code-guidelines#134 There are several places such a data structure is potentially useful for RustCrypto projects. Beyond the previously mentioned ASN.1 BIT STRING use case, being able to iterate over bits is useful in many numerical algorithms with applications in cryptography, notably in `crypto-bigint` and for elliptic curves. Elliptic curve scalar multiplication is generally implemented as a loop over the bits of a scalar. Having an iterator type for this purpose avoids problems relating to the endianness of how scalars are serialized when implementing generic scalar multiplication algorithms, e.g. wNAF (see RustCrypto/group#12). Given the current open soundness story, I'm not rushing to use this in `crypto-bigint` until that changes. Where we could use it today though is as an optional dependency to `der`, where it can act as an ASN.1 BIT STRING type, but implement `ToOwned` producing a `der::asn1::BitString` (which, to make `ToOwned` work, needs to impl `Borrow<BitSlice>`). This would make it optionally possible to use `Cow` for copy-on-write BIT STRINGs today with `BitSlice` as the borrowed form, but leaving the preferred default data structure for that purpose as `der::asn1::BitStringRef`, which is a lifetime-parameterized struct that avoids the open soundness questions around `BitSlice`. From there we can see what develops around the soundness story and SB/TB discrepancy, and beyond that new Rust features like custom DSTs which may make expressing structures like this less of a hack.
tarcieri
added a commit
to RustCrypto/utils
that referenced
this pull request
May 15, 2026
Adds a crate providing a `&BitSlice`/`&mut BitSlice` type which is constructable from `&[u8]` but provides slicing at the granularity of individual bits. The name of the crate is a play on `bitvec`, which provides a similar type. However, the implementation in this crate is significantly simpler with a much smaller code surface and minimal use of `unsafe` code. The implementation is a generalization of RustCrypto/formats#2300 which sought to implement a similar data structure as a reference type for representing ASN.1 BIT STRINGs. However, using this approach was deferred because the implementation relies on a conversion which is sound under Tree Borrows (as verified by Miri) but unsound under Stacked Borrows as it loses provenance. See rust-lang/unsafe-code-guidelines#134 There are several places such a data structure is potentially useful for RustCrypto projects. Beyond the previously mentioned ASN.1 BIT STRING use case, being able to iterate over bits is useful in many numerical algorithms with applications in cryptography, notably in `crypto-bigint` and for elliptic curves. Elliptic curve scalar multiplication is generally implemented as a loop over the bits of a scalar. Having an iterator type for this purpose avoids problems relating to the endianness of how scalars are serialized when implementing generic scalar multiplication algorithms, e.g. wNAF (see RustCrypto/group#12). Given the current open soundness story, I'm not rushing to use this in `crypto-bigint` until that changes. Where we could use it today though is as an optional dependency to `der`, where it can act as an ASN.1 BIT STRING type, but implement `ToOwned` producing a `der::asn1::BitString` (which, to make `ToOwned` work, needs to impl `Borrow<BitSlice>`). This would make it optionally possible to use `Cow` for copy-on-write BIT STRINGs today with `BitSlice` as the borrowed form, but leaving the preferred default data structure for that purpose as `der::asn1::BitStringRef`, which is a lifetime-parameterized struct that avoids the open soundness questions around `BitSlice`. From there we can see what develops around the soundness story and SB/TB discrepancy, and beyond that new Rust features like custom DSTs which may make expressing structures like this less of a hack.
tarcieri
added a commit
to RustCrypto/utils
that referenced
this pull request
May 15, 2026
Adds a crate providing a `&BitSlice`/`&mut BitSlice` type which is constructable from `&[u8]` but provides slicing at the granularity of individual bits. The name of the crate is a play on `bitvec`, which provides a similar type. However, the implementation in this crate is significantly simpler with a much smaller code surface and minimal use of `unsafe` code. The implementation is a generalization of RustCrypto/formats#2300 which sought to implement a similar data structure as a reference type for representing ASN.1 BIT STRINGs. However, using this approach was deferred because the implementation relies on a conversion which is sound under Tree Borrows (as verified by Miri) but unsound under Stacked Borrows as it loses provenance. See rust-lang/unsafe-code-guidelines#134 There are several places such a data structure is potentially useful for RustCrypto projects. Beyond the previously mentioned ASN.1 BIT STRING use case, being able to iterate over bits is useful in many numerical algorithms with applications in cryptography, notably in `crypto-bigint` and for elliptic curves. Elliptic curve scalar multiplication is generally implemented as a loop over the bits of a scalar. Having an iterator type for this purpose avoids problems relating to the endianness of how scalars are serialized when implementing generic scalar multiplication algorithms, e.g. wNAF (see RustCrypto/group#12). Given the current open soundness story, I'm not rushing to use this in `crypto-bigint` until that changes. Where we could use it today though is as an optional dependency to `der`, where it can act as an ASN.1 BIT STRING type, but implement `ToOwned` producing a `der::asn1::BitString` (which, to make `ToOwned` work, needs to impl `Borrow<BitSlice>`). This would make it optionally possible to use `Cow` for copy-on-write BIT STRINGs today with `BitSlice` as the borrowed form, but leaving the preferred default data structure for that purpose as `der::asn1::BitStringRef`, which is a lifetime-parameterized struct that avoids the open soundness questions around `BitSlice`. From there we can see what develops around the soundness story and SB/TB discrepancy, and beyond that new Rust features like custom DSTs which may make expressing structures like this less of a hack.
tarcieri
added a commit
to RustCrypto/utils
that referenced
this pull request
May 15, 2026
Adds a crate providing a `&BitSlice`/`&mut BitSlice` type which is constructable from `&[u8]` but provides slicing at the granularity of individual bits. The name of the crate is a play on `bitvec`, which provides a similar type. However, the implementation in this crate is significantly simpler with a much smaller code surface and minimal use of `unsafe` code. The implementation is a generalization of RustCrypto/formats#2300 which sought to implement a similar data structure as a reference type for representing ASN.1 BIT STRINGs. However, using this approach was deferred because the implementation relies on a conversion which is sound under Tree Borrows (as verified by Miri) but unsound under Stacked Borrows as it loses provenance. See rust-lang/unsafe-code-guidelines#134 There are several places such a data structure is potentially useful for RustCrypto projects. Beyond the previously mentioned ASN.1 BIT STRING use case, being able to iterate over bits is useful in many numerical algorithms with applications in cryptography, notably in `crypto-bigint` and for elliptic curves. Elliptic curve scalar multiplication is generally implemented as a loop over the bits of a scalar. Having an iterator type for this purpose avoids problems relating to the endianness of how scalars are serialized when implementing generic scalar multiplication algorithms, e.g. wNAF (see RustCrypto/group#12). Given the current open soundness story, I'm not rushing to use this in `crypto-bigint` until that changes. Where we could use it today though is as an optional dependency to `der`, where it can act as an ASN.1 BIT STRING type, but implement `ToOwned` producing a `der::asn1::BitString` (which, to make `ToOwned` work, needs to impl `Borrow<BitSlice>`). This would make it optionally possible to use `Cow` for copy-on-write BIT STRINGs today with `BitSlice` as the borrowed form, but leaving the preferred default data structure for that purpose as `der::asn1::BitStringRef`, which is a lifetime-parameterized struct that avoids the open soundness questions around `BitSlice`. From there we can see what develops around the soundness story and SB/TB discrepancy, and beyond that new Rust features like custom DSTs which may make expressing structures like this less of a hack.
tarcieri
added a commit
to RustCrypto/utils
that referenced
this pull request
May 15, 2026
Adds a crate providing a `&BitSlice`/`&mut BitSlice` type which is constructable from `&[u8]` but provides slicing at the granularity of individual bits. The name of the crate is a play on `bitvec`, which provides a similar type. However, the implementation in this crate is significantly simpler with a much smaller code surface and minimal use of `unsafe` code. The implementation is a generalization of RustCrypto/formats#2300 which sought to implement a similar data structure as a reference type for representing ASN.1 BIT STRINGs. However, using this approach was deferred because the implementation relies on a conversion which is sound under Tree Borrows (as verified by Miri) but unsound under Stacked Borrows as it loses provenance. See rust-lang/unsafe-code-guidelines#134 There are several places such a data structure is potentially useful for RustCrypto projects. Beyond the previously mentioned ASN.1 BIT STRING use case, being able to iterate over bits is useful in many numerical algorithms with applications in cryptography, notably in `crypto-bigint` and for elliptic curves. Elliptic curve scalar multiplication is generally implemented as a loop over the bits of a scalar. Having an iterator type for this purpose avoids problems relating to the endianness of how scalars are serialized when implementing generic scalar multiplication algorithms, e.g. wNAF (see RustCrypto/group#12). Given the current open soundness story, I'm not rushing to use this in `crypto-bigint` until that changes. Where we could use it today though is as an optional dependency to `der`, where it can act as an ASN.1 BIT STRING type, but implement `ToOwned` producing a `der::asn1::BitString` (which, to make `ToOwned` work, needs to impl `Borrow<BitSlice>`). This would make it optionally possible to use `Cow` for copy-on-write BIT STRINGs today with `BitSlice` as the borrowed form, but leaving the preferred default data structure for that purpose as `der::asn1::BitStringRef`, which is a lifetime-parameterized struct that avoids the open soundness questions around `BitSlice`. From there we can see what develops around the soundness story and SB/TB discrepancy, and beyond that new Rust features like custom DSTs which may make expressing structures like this less of a hack.
tarcieri
added a commit
to RustCrypto/utils
that referenced
this pull request
May 15, 2026
Adds a crate providing a `&BitSlice`/`&mut BitSlice` type which is constructable from `&[u8]` but provides slicing at the granularity of individual bits. The name of the crate is a play on `bitvec`, which provides a similar type. However, the implementation in this crate is significantly simpler with a much smaller code surface and minimal use of `unsafe` code. The implementation is a generalization of RustCrypto/formats#2300 which sought to implement a similar data structure as a reference type for representing ASN.1 BIT STRINGs. However, using this approach was deferred because the implementation relies on a conversion which is sound under Tree Borrows (as verified by Miri) but unsound under Stacked Borrows as it loses provenance. See rust-lang/unsafe-code-guidelines#134 There are several places such a data structure is potentially useful for RustCrypto projects. Beyond the previously mentioned ASN.1 BIT STRING use case, being able to iterate over bits is useful in many numerical algorithms with applications in cryptography, notably in `crypto-bigint` and for elliptic curves. Elliptic curve scalar multiplication is generally implemented as a loop over the bits of a scalar. Having an iterator type for this purpose avoids problems relating to the endianness of how scalars are serialized when implementing generic scalar multiplication algorithms, e.g. wNAF (see RustCrypto/group#12). Given the current open soundness story, I'm not rushing to use this in `crypto-bigint` until that changes. Where we could use it today though is as an optional dependency to `der`, where it can act as an ASN.1 BIT STRING type, but implement `ToOwned` producing a `der::asn1::BitString` (which, to make `ToOwned` work, needs to impl `Borrow<BitSlice>`). This would make it optionally possible to use `Cow` for copy-on-write BIT STRINGs today with `BitSlice` as the borrowed form, but leaving the preferred default data structure for that purpose as `der::asn1::BitStringRef`, which is a lifetime-parameterized struct that avoids the open soundness questions around `BitSlice`. From there we can see what develops around the soundness story and SB/TB discrepancy, and beyond that new Rust features like custom DSTs which may make expressing structures like this less of a hack.
tarcieri
added a commit
to RustCrypto/utils
that referenced
this pull request
May 15, 2026
Adds a crate providing a `&BitSlice`/`&mut BitSlice` type which is constructable from `&[u8]` but provides slicing at the granularity of individual bits. The name of the crate is a play on `bitvec`, which provides a similar type. However, the implementation in this crate is significantly simpler with a much smaller code surface and minimal use of `unsafe` code. The implementation is a generalization of RustCrypto/formats#2300 which sought to implement a similar data structure as a reference type for representing ASN.1 BIT STRINGs. However, using this approach was deferred because the implementation relies on a conversion which is sound under Tree Borrows (as verified by Miri) but unsound under Stacked Borrows as it loses provenance. See rust-lang/unsafe-code-guidelines#134 There are several places such a data structure is potentially useful for RustCrypto projects. Beyond the previously mentioned ASN.1 BIT STRING use case, being able to iterate over bits is useful in many numerical algorithms with applications in cryptography, notably in `crypto-bigint` and for elliptic curves. Elliptic curve scalar multiplication is generally implemented as a loop over the bits of a scalar. Having an iterator type for this purpose avoids problems relating to the endianness of how scalars are serialized when implementing generic scalar multiplication algorithms, e.g. wNAF (see RustCrypto/group#12). Given the current open soundness story, I'm not rushing to use this in `crypto-bigint` until that changes. Where we could use it today though is as an optional dependency to `der`, where it can act as an ASN.1 BIT STRING type, but implement `ToOwned` producing a `der::asn1::BitString` (which, to make `ToOwned` work, needs to impl `Borrow<BitSlice>`). This would make it optionally possible to use `Cow` for copy-on-write BIT STRINGs today with `BitSlice` as the borrowed form, but leaving the preferred default data structure for that purpose as `der::asn1::BitStringRef`, which is a lifetime-parameterized struct that avoids the open soundness questions around `BitSlice`. From there we can see what develops around the soundness story and SB/TB discrepancy, and beyond that new Rust features like custom DSTs which may make expressing structures like this less of a hack.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The wNAF implementation assumes a little endian representation for scalars, but
PrimeField::to_reprreturns an opaque representation which may be big endian and is in the case of our implementations of the NIST P-curves.RustCrypto/ff#10 added a stopgap API:
PrimeField::to_le_repr, which is guaranteed to return a little endian representation. This commit switches(rustcrypto-)groupto use it, which should make it compatible with our curves which otherwise use a big endian SEC1 representation.Thanks to @tob-scott-a for sleuthing this out in #10.