-
Notifications
You must be signed in to change notification settings - Fork 481
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
Change short-circuiting logical ORs to bitwise ORs in Ristretto decoding. #243
Change short-circuiting logical ORs to bitwise ORs in Ristretto decoding. #243
Conversation
I'm not sure if this is a good change, because the decoding function doesn't operate on secret data, and can't be constant-time anyways because it returns an |
@@ -296,7 +296,7 @@ impl CompressedRistretto { | |||
// t == ((1+as²) sqrt(4s²/(ad(1+as²)² - (1-as²)²)))/(1-as²) | |||
let t = &x * &y; | |||
|
|||
if ok.unwrap_u8() == 0u8 || t.is_negative().unwrap_u8() == 1u8 || y.is_zero().unwrap_u8() == 1u8 { | |||
if (ok.unwrap_u8() == 0u8) | (t.is_negative().unwrap_u8() == 1u8) | (y.is_zero().unwrap_u8() == 1u8) { |
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.
Given that Choice
implements BitXor
and Not
, I think this could be written more simply as:
if (ok.unwrap_u8() == 0u8) | (t.is_negative().unwrap_u8() == 1u8) | (y.is_zero().unwrap_u8() == 1u8) { | |
if (!ok | t.is_negative() | y.is_zero()).unwrap_u8() == 1u8 { |
@@ -266,7 +266,7 @@ impl CompressedRistretto { | |||
&s_bytes_check[..].ct_eq(self.as_bytes()); | |||
let s_is_negative = s.is_negative(); | |||
|
|||
if s_encoding_is_canonical.unwrap_u8() == 0u8 || s_is_negative.unwrap_u8() == 1u8 { | |||
if (s_encoding_is_canonical.unwrap_u8() == 0u8) | (s_is_negative.unwrap_u8() == 1u8) { |
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.
Similarly:
if (s_encoding_is_canonical.unwrap_u8() == 0u8) | (s_is_negative.unwrap_u8() == 1u8) { | |
if (!s_encoding_is_canonical | s_is_negative).unwrap_u8() == 1u8 { |
If timing is a concern here, the API should probably also be altered to return a CtOption::new(s, s_encoding_is_canonical & !s_is_negative).and_then(|s| {
[...]
CtOption::new(
RistrettoPoint(EdwardsPoint{X: x, Y: y, Z: one, T: t}),
ok & !t.is_negative() & !y.is_zero(),
)
) |
Timing isn't a concern here, because point decompression does not operate on secret data. |
…key-docs-coverage Fix `SigningKey` from/to_bytes docs +coverage
This prevents a timing side channel which would allow us to determine which check failed. I can't think of a case where this would create problems in practice, but nonetheless I'd argue we should prevent the leak.
Related to dalek-cryptography/subtle#42