Skip to content

Conversation

@tarcieri
Copy link
Member

@tarcieri tarcieri commented Jul 16, 2020

This method is intended for use when implementing ECDSA, namely for computing a Scalar from the hash of the message:

https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Signature_generation_algorithm

Let 𝐳 be the 𝐋𝑛 leftmost bits of 𝑒, where 𝐋𝑛 is the bit length of the group order 𝑛

See related discussion here: https://github.com/RustCrypto/elliptic-curves/pull/56/files#diff-c8893dd2f9cf0dff9549c297fc437664R160-R176

cc @fjarri @nickray

@codecov-commenter
Copy link

codecov-commenter commented Jul 16, 2020

Codecov Report

Merging #76 into master will decrease coverage by 0.42%.
The diff coverage is 0.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #76      +/-   ##
==========================================
- Coverage   55.91%   55.49%   -0.43%     
==========================================
  Files          15       15              
  Lines        2897     2919      +22     
==========================================
  Hits         1620     1620              
- Misses       1277     1299      +22     
Impacted Files Coverage Δ
k256/src/arithmetic/scalar.rs 81.18% <0.00%> (-0.89%) ⬇️
k256/src/arithmetic/scalar/scalar_4x64.rs 90.55% <0.00%> (-3.22%) ⬇️
k256/src/arithmetic/scalar/scalar_8x32.rs 0.00% <0.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 37125d0...cac82e2. Read the comment docs.

This method is intended for use when implementing ECDSA, namely for
computing a `Scalar` from the hash of the message:

https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Signature_generation_algorithm

> Let 𝐳 be the 𝐋𝑛 leftmost bits of 𝑒, where 𝐋𝑛 is the bit length of the
> group order 𝑛
@tarcieri tarcieri force-pushed the k256/from-bytes-reduced branch from 69a618b to cac82e2 Compare July 16, 2020 14:53
Comment on lines +215 to +223
let w7 = u32::from_be_bytes(bytes[0..4].try_into().unwrap());
let w6 = u32::from_be_bytes(bytes[4..8].try_into().unwrap());
let w5 = u32::from_be_bytes(bytes[8..12].try_into().unwrap());
let w4 = u32::from_be_bytes(bytes[12..16].try_into().unwrap());
let w3 = u32::from_be_bytes(bytes[16..20].try_into().unwrap());
let w2 = u32::from_be_bytes(bytes[20..24].try_into().unwrap());
let w1 = u32::from_be_bytes(bytes[24..28].try_into().unwrap());
let w0 = u32::from_be_bytes(bytes[28..32].try_into().unwrap());
let w = [w0, w1, w2, w3, w4, w5, w6, w7];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit off-topic, but what is the motivation for this level of explicitness vs. loops or iterator approaches in cryptographic code? When I try this kind of thing, I tend to always get at least one index wrong :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually copypasta from both the from_bytes method as well as the from_overflow method.

I'd agree it could be simplified and potentially composed in terms of from_overflow too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps some time after rust-lang/rust#74060 is merged this could be:

let w: [u32; 8] = bytes.chunks(4).map(|chunk| u32::from_be_bytes(chunk).try_into().unwrap()).collect();

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AIUI, in some cases the p256 arithmetic uses "many variables" to allow functions to be const, not in this case though. I was wondering if the use for this was motivated by consistency and subjective preference, or some kind of cryptographic reason, would you know?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's any specific reason for it, but perhaps @str4d or @fjarri could chime in

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a minor performance benefit as compared to loops, but that can be negated by using an unrolling macro (there are several packages available for that). I have plans to do that, but just didn't get to it yet.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, loop unrolling. Thanks!

Copy link
Member Author

@tarcieri tarcieri Jul 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as macros for loop unrolling go, I've seen unroll, but that said so far in my usage of godbolt to optimize cryptographic code I still haven't seen a case where unrolling a loop by hand generates more efficient assembly.

(not saying they don't exist, especially in this kind of code, but I've generally seen LLVM's optimizer do a good job of unrolling loops on its own)

@tarcieri
Copy link
Member Author

I'm going to go with #78 instead

@tarcieri tarcieri closed this Jul 16, 2020
@tarcieri tarcieri deleted the k256/from-bytes-reduced branch July 16, 2020 18:26
@tarcieri
Copy link
Member Author

Haha, and now poking at implementing ECDSA this seems nice, especially in conjunction with the ecdsa::hazmat::SignPrimitive I defined, so I guess I'll be reviving it in the PR where I'm trying to implement ECDSA for secp256k1 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants