Skip to content

Conversation

@andrewwhitehead
Copy link
Contributor

@andrewwhitehead andrewwhitehead commented Jan 27, 2026

This PR makes a couple breaking changes: wrapping shift methods are updated to behave accordingly with core, so the shift value itself is wrapped at the capacity of the integer instead of the integer becoming zero when the shift exceeds the capacity. The new unbounded_shl/unbounded_shr methods provide support for the old behavior. The ShlVartime and ShrVartime traits also get a new method to support unbounded shifts.

The performance of constant-time shl/shr methods is improved by only performing one sub-limb shift instead of multiple.

Fixes #1151

@codecov
Copy link

codecov bot commented Jan 27, 2026

Codecov Report

❌ Patch coverage is 98.22560% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.85%. Comparing base (77bdacd) to head (ab512c6).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
src/uint/ref_type/shl.rs 93.24% 5 Missing ⚠️
src/uint/ref_type/shr.rs 93.50% 5 Missing ⚠️
src/uint/boxed/shr.rs 95.89% 3 Missing ⚠️
src/uint/mul/karatsuba.rs 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1160      +/-   ##
==========================================
+ Coverage   84.49%   84.85%   +0.36%     
==========================================
  Files         181      181              
  Lines       19674    19892     +218     
==========================================
+ Hits        16624    16880     +256     
+ Misses       3050     3012      -38     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@andrewwhitehead andrewwhitehead marked this pull request as draft January 27, 2026 23:30
@andrewwhitehead andrewwhitehead marked this pull request as ready for review January 28, 2026 22:10
@andrewwhitehead andrewwhitehead force-pushed the upd/wrapping-shifts branch 2 times, most recently from d8adb00 to 342f7f2 Compare January 29, 2026 23:01
Comment on lines 240 to 248
// #[test]
// fn bounded_overflowing_shr() {
// let res = U64::MAX.bounded_overflowing_shr::<32>(20);
// assert!(bool::from(res.is_some()));
// assert_eq!(res.unwrap(), U64::MAX.overflowing_shr(20).unwrap());

let res = U64::MAX.bounded_overflowing_shr::<32>(32);
assert!(bool::from(res.is_none()));
}
// let res = U64::MAX.bounded_overflowing_shr::<32>(32);
// assert!(bool::from(res.is_none()));
// }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forget to uncomment this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, updated the test.

Signed-off-by: Andrew Whitehead <cywolf@gmail.com>
… UintRef

Signed-off-by: Andrew Whitehead <cywolf@gmail.com>
Signed-off-by: Andrew Whitehead <cywolf@gmail.com>
Signed-off-by: Andrew Whitehead <cywolf@gmail.com>
Signed-off-by: Andrew Whitehead <cywolf@gmail.com>
Signed-off-by: Andrew Whitehead <cywolf@gmail.com>
Signed-off-by: Andrew Whitehead <cywolf@gmail.com>
Signed-off-by: Andrew Whitehead <cywolf@gmail.com>
@tarcieri tarcieri merged commit 1128ede into RustCrypto:master Feb 1, 2026
31 checks passed
Comment on lines +89 to +96
/// Remainder calculation, constant time for a given divisor `d`.
/// Based on "Faster Remainder by Direct Computation: Applications to Compilers and Software Libraries"
/// by Daniel Lemire, Owen Kaser, and Nathan Kurz., Fig. 1.
#[inline(never)]
#[allow(clippy::cast_possible_truncation)]
pub(crate) const fn u32_rem(n: u32, d: u32) -> u32 {
assert!(d > 0, "divisor must be nonzero");
let c = u64::MAX / (d as u64) + 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is performing division

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, only between a constant and the divisor though which should be constant time for a given numerator.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did check the assembly and it looked reasonable, the numerator only gets multiplied. The inline(never) is to help avoid optimizations.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On several architectures, division is variable-time with respect to both dividend and divisor

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah but that shouldn't be a problem, it only promises to be constant time for a given divisor (the number of bits in an integer, so far). This could be renamed as _vartime I suppose.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think it'd be fine if it were named _vartime and noted as being variable-time with respect to d.

It probably wouldn't be too hard to implement a fully constant-time version, FWIW.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we already have a constant-time version in div_limb.rs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 32-bit implementation in div_limb is conditional on the platform right now but that could be adjusted, or this could use the word-sized implementation. This version is much simpler though.

tarcieri added a commit to RustCrypto/elliptic-curves that referenced this pull request Feb 2, 2026
Release notes:

https://github.com/rust-random/rand_core/releases/tag/v0.10.0

Also bumps the following:
- `chacha20` v0.10.0-rc.10
- `crypto-bigint` v0.7.0-rc.24
- `crypto-common` v0.2.0-rc.14
- `digest` v0.11.0-rc.10
- `ecdsa` v0.17.0-rc.15
- `elliptic-curve` v0.14.0-rc.27
- `signature` v3.0.0-rc.10

This includes `wrapping_sh*` => `unbounded_sh*` changes that preserve
the original behavior of our implementation after this change:

RustCrypto/crypto-bigint#1160
tarcieri added a commit to RustCrypto/elliptic-curves that referenced this pull request Feb 2, 2026
Release notes:

https://github.com/rust-random/rand_core/releases/tag/v0.10.0

Also bumps the following:
- `chacha20` v0.10.0-rc.10
- `crypto-bigint` v0.7.0-rc.24
- `crypto-common` v0.2.0-rc.14
- `digest` v0.11.0-rc.10
- `ecdsa` v0.17.0-rc.15
- `elliptic-curve` v0.14.0-rc.27
- `signature` v3.0.0-rc.10

This includes `wrapping_sh*` => `unbounded_sh*` changes that preserve
the original behavior of our implementation after this change:

RustCrypto/crypto-bigint#1160

This also unfortunately includes the migration to `cpubits!` as it's
part of this `crypto-bigint` release.
tarcieri added a commit to RustCrypto/elliptic-curves that referenced this pull request Feb 2, 2026
Release notes:

https://github.com/rust-random/rand_core/releases/tag/v0.10.0

Also bumps the following:
- `chacha20` v0.10.0-rc.10
- `crypto-bigint` v0.7.0-rc.24
- `crypto-common` v0.2.0-rc.14
- `digest` v0.11.0-rc.10
- `ecdsa` v0.17.0-rc.15
- `elliptic-curve` v0.14.0-rc.27
- `signature` v3.0.0-rc.10

This includes `wrapping_sh*` => `unbounded_sh*` changes that preserve
the original behavior of our implementation after this change:

RustCrypto/crypto-bigint#1160

This also unfortunately includes the migration to `cpubits!` as it's
part of this `crypto-bigint` release.
tarcieri added a commit to RustCrypto/elliptic-curves that referenced this pull request Feb 2, 2026
Release notes:

https://github.com/rust-random/rand_core/releases/tag/v0.10.0

Also bumps the following:
- `chacha20` v0.10.0-rc.10
- `crypto-bigint` v0.7.0-rc.24
- `crypto-common` v0.2.0-rc.14
- `digest` v0.11.0-rc.10
- `ecdsa` v0.17.0-rc.15
- `elliptic-curve` v0.14.0-rc.27
- `signature` v3.0.0-rc.10

This includes `wrapping_sh*` => `unbounded_sh*` changes that preserve
the original behavior of our implementation after this change:

RustCrypto/crypto-bigint#1160

This also unfortunately includes the migration to `cpubits!` as it's
part of this `crypto-bigint` release.
tarcieri added a commit to RustCrypto/elliptic-curves that referenced this pull request Feb 2, 2026
Release notes:

https://github.com/rust-random/rand_core/releases/tag/v0.10.0

Also bumps the following:
- `chacha20` v0.10.0-rc.10
- `crypto-bigint` v0.7.0-rc.24
- `crypto-common` v0.2.0-rc.14
- `digest` v0.11.0-rc.10
- `ecdsa` v0.17.0-rc.15
- `elliptic-curve` v0.14.0-rc.27
- `signature` v3.0.0-rc.10

This includes `wrapping_sh*` => `unbounded_sh*` changes that preserve
the original behavior of our implementation after this change:

RustCrypto/crypto-bigint#1160

This also unfortunately includes the migration to `cpubits!` as it's
part of this `crypto-bigint` release.
tarcieri added a commit to RustCrypto/elliptic-curves that referenced this pull request Feb 2, 2026
Release notes:

https://github.com/rust-random/rand_core/releases/tag/v0.10.0

Also bumps the following:
- `chacha20` v0.10.0-rc.10
- `crypto-bigint` v0.7.0-rc.24
- `crypto-common` v0.2.0-rc.14
- `digest` v0.11.0-rc.10
- `ecdsa` v0.17.0-rc.15
- `elliptic-curve` v0.14.0-rc.27
- `signature` v3.0.0-rc.10

This includes `wrapping_sh*` => `unbounded_sh*` changes that preserve
the original behavior of our implementation after this change:

RustCrypto/crypto-bigint#1160

This also unfortunately includes the migration to `cpubits!` as it's
part of this `crypto-bigint` release.
tarcieri added a commit to RustCrypto/elliptic-curves that referenced this pull request Feb 2, 2026
Release notes:

https://github.com/rust-random/rand_core/releases/tag/v0.10.0

Also bumps the following:
- `chacha20` v0.10.0-rc.10
- `crypto-bigint` v0.7.0-rc.24
- `crypto-common` v0.2.0-rc.14
- `digest` v0.11.0-rc.10
- `ecdsa` v0.17.0-rc.15
- `elliptic-curve` v0.14.0-rc.27
- `signature` v3.0.0-rc.10

This includes `wrapping_sh*` => `unbounded_sh*` changes that preserve
the original behavior of our implementation after this change:

RustCrypto/crypto-bigint#1160

This also unfortunately includes the migration to `cpubits!` as it's
part of this `crypto-bigint` release.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wrapping shift confusion

3 participants