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
ecdsa: prehash must receive zero-pads on left #547
Conversation
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.
LGTM
Maybe we should add the test parameters from RFC 6979 (in a separate PR)? At least for one of the curves. Never mind, misread the source. But having a few tests against these test vectors and some parameters, signatures, etc. from other implementations would be beneficial regardless |
I was thinking to add a test to catch this but curious how to test this problem appropriately without help of other libs. A simple roundtrip test doesn’t help for this, so as the rfc makes the process determinable embedding the expected output vector and compare? |
So this issue you fixed should occur whenever you use the So a possible test would be to, for example, import RFC 6979 test vectors wouldn't detect this unfortunately since they expect the digest that was used to hash the message and the digest that is used to derive I'm not sure whether this is even the place for a test like this since the RFC 6979 tests aren't here either, instead they are implemented alongside the concrete curve implementations (here). CC @tarcieri |
Nice catch, thanks! Regarding testing: I'd strongly recommend against circular dependencies, particularly involving pre-1.0 crates. We already have some in this repo for the I'd suggest adding some unit tests in the https://github.com/RustCrypto/elliptic-curves/blob/f3ae7d5/p256/src/ecdsa.rs#L91-L113 |
`prehash_to_field_bytes` was zero-padding on the right of the byte sequence but this must be done on the left because the output is evaluated as a big integer. This behavior is defined on various documents including RFC6979 Section 2.3.2., SEC 1 Section 2.3.8., NIST FIPS 186-4 Appendix C.2.1. https://datatracker.ietf.org/doc/html/rfc6979#section-2.3.2 https://www.secg.org/sec1-v2.pdf https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.186-4.pdf
Indeed, having circular dependencies would be painful; Do you think that this PR needs a unit test? I think I can work on p256/p384 integration test... But writing a unit test would take a time for me because currently ecdsa crate has no unit test & I'm not confident enough to prepare curve structs and others for unit testing from scratch (with aligning to your intention and design decision), so I want to leave this for you. |
Integration tests would be a lot more valuable for assessing correctness. I can add a unit/regression test separately if you'd rather work on integration tests instead. |
ok, I'll try working on integration test in a separate PR (as p256/p384 crate reside in another repo) |
Add integration tests to verify the following scenarios: - P-256 ECDSA signing/verification with SHA-384 (longer than field size) - P-384 ECDSA signing/verification with SHA-256 (smaller than field size) Verification scenarios use a test vector adopted from FIPS 186-4. Signing scenarios use a key from RFC6979 test vector but the test signature is pre-calculated using ecdsa crate (with the following fix applied) and cross-verified using OpenSSL. Unfortunately there are no suitable test vector to test DigestPrimitive::prehash_to_field_bytes through PrehashSigner. The tests added in p384 currently fails and a fix has been submitted separately at RustCrypto/signatures#547
Submitted RustCrypto/elliptic-curves#666 |
Thank you! |
Released as |
Add integration tests to verify the following scenarios: - P-256 ECDSA signing/verification with SHA-384 (longer than field size) - P-384 ECDSA signing/verification with SHA-256 (smaller than field size) Verification scenarios use a test vector adopted from FIPS 186-4. Signing scenarios use a key from RFC6979 test vector but the test signature is pre-calculated using ecdsa crate (with the following fix applied) and cross-verified using OpenSSL. Unfortunately there are no suitable test vector to test DigestPrimitive::prehash_to_field_bytes through PrehashSigner. The tests added in p384 currently fails and a fix has been submitted separately at RustCrypto/signatures#547
This is a fix for the issue I mentioned at #534 (comment). I believe the present implementation of
prehash_to_field_bytes
can't interop with OpenSSL (at least but should be the same for other crypto libraries)...Description
prehash_to_field_bytes
was zero-padding on the right of the byte sequence but this must be done on the left because the output is evaluated as a integer encoded in big-endian, and its integer representation should be stable regardless of sequence length.This behavior is defined on various documents including RFC6979 Section 2.3.2., SEC 1 Section 2.3.8., NIST FIPS 186-4 Appendix C.2.1.
Verification
I used the following code to test signing with ecdsa crate and verify with OpenSSL:
this patch fixes the crate not to fail the above code.