-
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
Supporting Signed Integer Arithmetic #624
Comments
As I don't happen to work on cryptographic algorithms that require signed arithmetic (instead we use modular arithmetic where negative values wrap around a modulus, e.g. DSA, RSA, and elliptic curves) I can't answer these questions for you. What cryptographic algorithm are you implementing and how does it leverage signed arithmetic? |
I'm working on cryptography involving class groups. In these groups, each element can be represented as a tuple The most prevalent operations on these tuples are normalization, reduction, and composition. These operations use a combination of addition, subtraction, multiplication, and (floored)division on the tuple's elements. Currently, I'm investigating whether it is "best" to make my 'math fit the code' or make the 'code fit the math'. Here, "best" is a trade-off between the code's development cost, understandability/modifiability, and execution time. It is quite a complex process ;-) |
Just curious, do any class group protocols involve secrets or otherwise benefit from constant time arithmetic for other reasons? VDFs need pure speed, but afaik do not benefit from being constant time, but those are likely broken anyways. An accumulator or such does probably. |
The Additive Homomorphic Encryption (AHE) scheme I'm building on top of Class Groups involves operations that I think should be constant time. Two examples:
Perhaps there are other techniques to achieve this. If that is the case, I'd love to hear about them :) |
This brings me back to my initial question: what are the requirements for a (partial) implementation of signed integer arithmetic to be accepted into this crate? If I get around to implementing (part of) it, I'd prefer to make something that has a high probability of being accepted :) |
I noticed that there is a
I noticed that this crate's implementation of Bernstein-Yang's GCD (a function I'd like to use) is not marked as "variable time". Though, I noticed that it contains an |
Using a built-in public signed number implementation rather than the private vendored implementation used for Bernstein-Yang is a good observation for a potential improvement, but signedness is half the story. The other is the 62-bit unsaturated limb representation, where we'd need It's all potentially doable right now though, even on stable Rust.
That's definitely also another good observation, and it seems like it was probably a case of something more like PoC-quality code being committed due to lack of proper review (mea culpa), in the haste of trying to build out all the functionality that was needed for The conditional negation is easy enough to fix. I believe the I'll make a separate tracking issue for that. Thanks. Edit: opened #627 |
Sounds like this is going to be a complex project. I'm in! Sounds like quite some planning/investigation will have to take place to do this right. I'm just getting the hang of Rust, so we'll have to collab to properly integrate this nicely into the crate. Do you have a preferred way of working in this regard? |
@erik-3milabs I'd suggest starting by adding signed integer support. Rather than my previous suggestion of trying to make |
@tarcieri just mentioning that I'm working with Erik and will be helping, it is valuable for us to have constant-time signed integers. |
@tarcieri IIUC, you're essentially proposing to investigate whether it is possible to replace pub(super) struct UnsatInt<const LIMBS: usize>(pub [u64; LIMBS]); with pub(super) struct UnsatInt<const LIMBS: usize>(pub Int<LIMBS>); where The first step - moving from Idealistic perspectiveMaking This suggests that
Extrapolating this would yield the following dependency tree: i.e., from an idealistic perspective, one should first split on saturation level, and only then on signedness. Realistic perspectiveOk, let's come back down to earth. I don't think there is demand for a Instead, I think we should stick with the structure we have right now: and provide proper support to switch from
the library could be made generic to include those as follows: TL;DR:From a structural perspective, I think it is best to leave I'd love to hear your take on this. |
As for implementing an
|
Sure, that sounds fine
One complication is that So if you really want to support Also, as it were, the implementation the current B-Y |
Even for RSA you might want to have signed integers. Imagine the "scalar"/"exponent" of the elements of multiplicative group modulo N, which you don't know the factorization of (exactly like RSA public key). Then you cannot negate this scalar by doing negation mod phi(N), because you don't know the order of the group (unless you have secret key of RSA). |
@tarcieri development has commenced! I decided to start with the checked and wrapping functionality for the Given your experience, have you, perchance, stumbled across a reference guide on implementing (fast) signed integer arithmetic (but never gotten around to implementing it yourself)? That could save me the arduous search for one. |
Waiting on @tarcieri response, I'll let myself to add my $0.02 here as I have some experience implementing big ints.
I don't know which approach would be better here, provided it has to be constant time and crypto safe. |
@lleoha thanks for your input! Three quick questions:
|
This is exactly two's complement, the MSB is sign but the remaining bits are not interpreted as absolute value of unsigned int (e.g. -1 being all bits set to 1, sign included), with that addition, subtraction etc. work the same for signed and unsigned integers or mix thereof. With sign magnitude the sign bit is usually stored seperately, so you can compute sign seperately and work on absolute values stored in limbs.
Well, it kind of depends on the implementation, but the naive method would require to sign extend when casting to bigger domain, probably not a problem with fixed length integers, but this is something that is not needed in "sign magnitude" approach, where extension is just filling with zeros. If I were to make a choice I would give it a go with twos complement for fixed sized int (as in this project). |
A few quick points: This library supports both fixed-width and variable-width big integers, and ideally we could share algorithmic implementations between the two forms (see #667). Generally I’d say the stack allocated form is the more important priority. If one of the goals is to replace the bespoke signed integer implementation in the Bernstein-Yang / safegcd implementation, then note that algorithm is specified using two’s complement. |
If you do end up going with a sign bit, it should probably be represented as a Sidechannels involving sign bits have been a source of key recovery attacks: https://eprint.iacr.org/2015/1141.pdf |
@erik-3milabs left a bunch of comments, but general one I would still prefer to use U2 and not sign + abs (at least for fixed sized Int). |
Superseeded by feature tracking ticket #700 |
I'm interested in performing cryptographic arithmetic involving negative (signed) integers. As is made evident in #1, this crate does not yet provide support for this.
I'm exploring what writing the necessary code to support this would take. To progress my exploration, I'd like to learn what additions would be valued/accepted to this library. In particular, what would be considered a "minimal useful addition"? What functionality must be included? Adding support for all operations (right off the bat) might be beyond my current capacity.
Looking forward to your input!
Edit:
This discussion was superseded by #700
The text was updated successfully, but these errors were encountered: