Skip to content
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

p384: scalar multiplication test vectors #570

Merged
merged 3 commits into from
May 27, 2022

Conversation

tarcieri
Copy link
Member

Tests scalar multiplication using vectors from:

http://point-at-infinity.org/ecc/nisttv

@tarcieri
Copy link
Member Author

Note: currently failing on the first vector, which is one of the repeated addition of the generator vectors.

I haven't investigated why yet

cc @jedisct1 @brycx

@tarcieri
Copy link
Member Author

It looks like the From<u64> impl for Scalar was bugged and setting the last limb rather than the first.

With that fixed it gets farther but still fails on one of the vectors.

@tarcieri
Copy link
Member Author

tarcieri commented May 27, 2022

Sidebar: it looks like <Scalar as PrimeField>::from_repr isn't properly checking for overflow.

Confirmed this: fiat_p384_scalar_from_bytes states the following precondition:

/// Preconditions:
///   0 ≤ bytes_eval arg1 < m

...so the input scalar needs to be checked to ensure it doesn't overflow the order

@jedisct1
Copy link
Contributor

Why do we need From<u64> at all? That seems like something dangerous to have in a public API. Even internally, there's no specialized code for multiplication with small scalars. The real-world use cases for that are very specific (ex: cofactor clearing, which is irrelevant here) and would be rather addressed by dedicated functions.

The semantics of from_repr() are not very clear. The endianness is documented as "implementation specific", so my interpretation is that it was only meant to be used internally. Looking at this being used in this PR's test vectors got me even more confused about what a "repr" is, if it's supposed to be used by applications and if it is guaranteed to be stable across versions.

@jedisct1
Copy link
Contributor

so the input scalar needs to be checked to ensure it doesn't overflow the order

This is done in from_le_bytes() and thus indirectly everywhere else besides from_repr().

from_repr() can be replaced by a simple call to from_be_bytes().

@tarcieri
Copy link
Member Author

Why do we need From at all? That seems like something dangerous to have in a public API. Even internally, there's no specialized code for multiplication with small scalars. The real-world use cases for that are very specific (ex: cofactor clearing, which is irrelevant here) and would be rather addressed by dedicated functions.

At least in this particular case, it's being exercised by the test suite which is checking the equivalence of repeated doublings of the generator and scalar multiplication by the generator.

I'm not aware of external-facing applications offhand, but regardless, it was easy to fix.

The semantics of from_repr() are not very clear. The endianness is documented as "implementation specific", so my interpretation is that it was only meant to be used internally. Looking at this being used in this PR's test vectors got me even more confused about what a "repr" is, if it's supposed to be used by applications and if it is guaranteed to be stable across versions.

There is some ongoing discussion about this from users of ff and group. See here for example:

zkcrypto/ff#16 (comment)

k256 and p256 use a big endian representation.

This is done in from_le_bytes() and thus indirectly everywhere else besides from_repr().

from_repr() can be replaced by a simple call to from_be_bytes().

This doesn't really uphold the contract of the function, which returns a CtOption.

It's addressed easily enough using e.g. U384 to check for overflow, which can return a Choice.

@tarcieri
Copy link
Member Author

tarcieri commented May 27, 2022

Here's my proposed fix, which makes Scalar consistent with the ScalarCore API in the elliptic-curve crate: #571

This allows Scalar::from_repr to call Scalar::from_be_bytes.

@tarcieri tarcieri force-pushed the p384/scalar-mult-test-vectors branch from 6c2b5e9 to 22ef9b4 Compare May 27, 2022 15:54
@tarcieri tarcieri marked this pull request as ready for review May 27, 2022 16:17
@tarcieri tarcieri changed the title [WIP] p384: scalar multiplication test vectors p384: scalar multiplication test vectors May 27, 2022
@tarcieri tarcieri merged commit 1f35666 into master May 27, 2022
@tarcieri tarcieri deleted the p384/scalar-mult-test-vectors branch May 27, 2022 16:19
@tarcieri
Copy link
Member Author

@jedisct1 the From<u64> bound is actually a requirement for the PrimeField trait:

https://docs.rs/ff/0.12.0/ff/trait.PrimeField.html

pub trait PrimeField: Field + From<u64> { ... }

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.

2 participants