-
Notifications
You must be signed in to change notification settings - Fork 55
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
[WIP] Int
- sign-and-magnitude
#694
Conversation
@erik-3milabs crypto-bigint has their own |
My impression was that in discussion it was suggested to rather use U2 not sign + absolute value. Constant operations would be easier in that representation and IMHO it's more suitable for fixed sized integers. |
|
||
impl<const LIMBS: usize> Int<LIMBS> { | ||
/// Add two [`Int`]s, checking for overflow. | ||
fn checked_adc(&self, rhs: &Self) -> CtOption<Self> { |
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 unnecessary complex.
it's much easier to do it that way:
- positive and negative never overflows
- two positives (or two negatives) overflow if MSB of the result is different that MSB of operands (the result and operands of magnitude I mean)
no need for min/max, sub etc.
use crate::int::Int; | ||
use crate::{CheckedDiv, Uint}; | ||
|
||
impl<const LIMBS: usize> CheckedDiv for Int<LIMBS> { |
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 zero has two representation, I think we should handle this as well, i.e "-0"/whatever should be "-0" not "+0".
|
||
impl<const LIMBS: usize, const RHS_LIMBS: usize> CheckedMul<Int<RHS_LIMBS>> for Int<LIMBS> { | ||
#[inline] | ||
fn checked_mul(&self, rhs: &Int<RHS_LIMBS>) -> CtOption<Self> { |
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.
same as for div, since there are two zero representation the sign should be preserved.
i.e.
- -0 * -0 = +0
- +0 * +0 = +0
- -0 * +0 = -0
- +0 * -0 = -0
use crate::int::Int; | ||
use crate::WrappingNeg; | ||
|
||
impl<const LIMBS: usize> Int<LIMBS> { |
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.
same here, there are two representation of zero so sign should behave correctly i.e.:
-(-0) = +0
-(+0) = -0
// TODO(erik): replace with Choice once I've figured how to const-construct those. | ||
is_negative: bool, |
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.
bool
anywhere in constant-time code is worrisome because it's an invitation for e.g. LLVM's optimizer to insert branches based on the value, even in cases where the original code deliberately avoids them
I am strongly against that for the following reasons. Currently zero has two representations (-0 and +0) adding is_zero will make it from 2 to ~2^(limbs * limb_bits). |
|
||
#[derive(Copy, Clone, Hash, Debug, PartialEq)] | ||
pub struct Int<const LIMBS: usize> { | ||
// TODO(erik): replace with Choice once I've figured how to const-construct those. |
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.
no problem here, worst case scenario, just use u8, CtChoice is more or less that.
I'd like to reiterate my previous comments that the heap-allocated The Pretty much all other algorithms use a very small, fixed number of key sizes. |
|
||
#[cfg(target_pointer_width = "64")] | ||
#[allow(dead_code)] | ||
type I128 = Int<2>; |
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 where it's tricky, if we want to relate this to builtin i128 type, this is actually closer to I129 because of using sign and magnitude instead of two's complements.
@tarcieri @lleoha thank you for your feedback! It became clear that sign-and-magnitude is not as great a solution as I thought it to be. To investigate whether two's complement might be a better approach, I took some time to whip up a quick implementation; you can find it as an open PR at #695. I would greatly appreciate your feedback! |
U2 looks much better than sign magnitude and is more consistent. |
|
Closing for now, due to "overwhelming" support for U2 #695. |
What is this?
This PR provides basic signed integer support into
crypto_bigint
. This is a not-yet-implemented feature (see #1).This basic implementation involves the following operations:
checked_add
,checked_sub
,checked_mul
, andchecked_div
Related
Discussion started in #624.
About
This PR puts the first code on the board. The decision was made to implement
Int
as sign-and-magnitude (over, say, two's complement) since it is easier to scale to flexible-size implementations and, in my opinion, less error-prone. Moreover, multiplications yield hardly any overhead compared to operating onUint
s; most of the overhead is incurred in the addition operation.Open question:
It was mentioned in #624 to use
Choice
to represent the sign. Sadly, this struct does not seem to have aconst
constructor. If this is indeed the case, we will be unable to make the constantsInt::ZERO
,::MINUS_ONE
,::ONE
,::MIN
and::MAX
unless we resolve this.Area for improvement:
The current addition/subtraction operations involve
Uint
-addition,Uint
-subtraction,CtOption::ct_selects
,Uint::eq
call, andUint::ct_gt
call.As such, this operation is ~7x more expensive than a
Uint
addition/subtraction. There is at least one clear area for improvement here: add anis_zero
flag to thestruct
. Doing so will get allow us to get rid of thect_eq
call.In my understanding, converting to and from two's complement will not be an option; the overhead in doing most likely exceeds the 6x performance penalty.
Any feedback is greatly appreciated!