-
Notifications
You must be signed in to change notification settings - Fork 56
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
Implement modular arithmetic #130
Conversation
I now see issues #70 and #28. I think |
@jellevos the workaround that @haslersn suggested which uses a ZST + trait with an associated constant seems OK as a workaround until pub trait ResidueParameters<const L: usize>: PartialEq + Debug {
const MODULUS: Option<UInt<L>>;
}
#[derive(PartialEq)]
pub struct Residue<P, const L: usize>
where
P: ResidueParameters<L>,
{
repr: UInt<L>,
phantom: PhantomData<P>,
} It could be wrapped up in a macro which defines a ZST and impls the trait for it like so to reduce the boilerplate: impl_modulus!(Modulus, U256, "ffffffff00000001..."); |
Also thanks for submitting this! I'll try to review it in depth when I have some time. |
This is a really good idea! One thing that is not immediately clear to me is how ergonomic this will be for non-hardcoded moduli, but I will investigate.
Feel free to wait a bit until I have incorporated the changes above. :) If you like, I can ping you when they are ready. |
The philosophy of this crate is to largely focus on compile-time optimizations, and perhaps do a secondary pass for things that are dependent on runtime values (e.g. #58). Having a It would enable checking special properties of the modulus, and using those properties to select particular implementations in a way this could all be known at compile time. This would allow the compiler to optimize away the branches, so you could provide several implementations of e.g. modular sqrt, picking the best one for a particular modulus at compile time. |
@tarcieri The implementation is mostly finished, but I am running into a seemingly fundamental issue. Specifically, I get the following error when running the tests in
In other words, we are hitting the compiler's
What do you think? Do you have any clever ideas on how to get around this? Apart from this, I only need to add a few docstrings before the PR should be ready for review. |
I suppose we could also shrink the modulus in those tests, which would make the tests and library work on stable but would force dependencies that use somewhat large moduli to be nightly. |
@tarcieri The initial attempt at this was very cumbersome, because one has to drag the pub trait ResidueParameters: PartialEq + Debug + Send + 'static {
type UInt: GenericUInt;
const MODULUS: Option<Self::UInt>;
}
#[derive(PartialEq)]
pub struct Residue<P>
where
P: ResidueParameters,
{
repr: P::UInt,
phantom: PhantomData<P>,
} |
@jellevos wow, that is really unfortunate. I was unaware I see there's a tracking issue for the low limit precluding other real-world usages: rust-lang/rust#93481 (The main tracking issue for Tough to say what to do about this. It would be good to determine that the caller can change this limit, or otherwise if |
@haslersn FWIW the existing |
@tarcieri yes, but the |
@haslersn you can add those bounds to the existing |
@tarcieri yes, when adding the functionality directly in crypto-bigint, that would be the way to go. |
I think the best solution in the mean time would be to make sure the tests in this library pass on stable and then leave the problem with the user (i.e. a user must switch to nightly if the const computations exceed the current limit). I can finish these changes tomorrow, then I would say this is ready for review. I will add a clear statement in the docs that one may need to up |
@jellevos sounds good! FWIW I left a comment here: rust-lang/rust#93481 (comment) |
Currently, I use a second macro |
@tarcieri Ready for review! The efficient squaring method is in #133. Edit: I have an almost ready version of the runtime-selected moduli, and to make the code much nicer, this PR also requires some refactoring. This does mean that things get shuffled around a bit. I will still keep this PR only for constant moduli. I'll push this code in an hour or so and also create a draft PR for the runtime moduli. |
Summary of new changes:
I want to raise an issue about the multiplicative inverses as they are currently very unsafe to use. Currently, I only check that an inverse exists using @tarcieri Do you have any clever ideas on how to handle this? One idea is to return a |
I'd personally prefer (and it would be more consistent with the other RustCrypto projects) if it were the reverse of that, with |
I agree, I reverted it. 😄 I am still thinking about how to best handle the problem with multiplicative inverses:
|
@jellevos yeah, that's a tricky and annoying tradeoff. You could have a |
It should be ready! @tarcieri |
Cool, will take another look this weekend |
Extends #130 by adding residues for moduli decided at run-time.
When using this much appreciated feature in my project, I needed to do some changes to the API surface around I'd like to PR these changes, discuss them, and reach a consensus. However, I'll only get to that after the paper deadline, which is in about a week. So it would be nice if you could wait a bit with the next release. |
No worries there, it's going to be at least a few months before we're ready to cut another release |
Breaking changes were introduced in #130, so this bumps the crate's version to a prerelease to denote that. It will be bumped to `pre.0` for an actual crate release. Also removes all deprecated APIs.
Breaking changes were introduced in #130, so this bumps the crate's version to a prerelease to denote that. It will be bumped to `pre.0` for an actual crate release. Also removes all deprecated APIs.
Hi @tarcieri and the other contributors! For the
scicrypt
crate I was working on constant-time big integers by wrapping GMP, but the interface was extremely clumsy. I decided to switch to this crate (which looks awesome!) and added the necessary methods for modular arithmetic.I implemented the following functionality:
Choice
Neg
forWrapping<Uint<LIMBS>>
In my opinion, there are at least two large issues right now that I would like to hear your opinion on.
Modular
interface is not satisfying to me because it copies theMontgomeryParameters
and does not assert that twoModular
integers indeed share the same modulus.const fn
.Still, I thought it was good to already make a PR to bring this to your attention. I am happy to put in the effort to bring this to a point where it is mergeable! :)
Edit:
The modulus is now a constant and the struct is called
Residue
rather thanModular
.