-
Notifications
You must be signed in to change notification settings - Fork 78
Fix wrapping shifts and add unbounded shifts #1160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix wrapping shifts and add unbounded shifts #1160
Conversation
Codecov Report❌ Patch coverage is
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. 🚀 New features to boost your workflow:
|
07801ed to
66e9080
Compare
d8adb00 to
342f7f2
Compare
src/modular/bingcd/extension.rs
Outdated
| // #[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())); | ||
| // } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forget to uncomment this?
There was a problem hiding this comment.
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>
1208796 to
ab512c6
Compare
| /// 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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is performing division
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
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
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.
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.
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.
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.
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.
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.
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 newunbounded_shl/unbounded_shrmethods provide support for the old behavior. TheShlVartimeandShrVartimetraits also get a new method to support unbounded shifts.The performance of constant-time
shl/shrmethods is improved by only performing one sub-limb shift instead of multiple.Fixes #1151