Hello,
The attached patch adds support for the deterministic DSA and ECDSA, as defined in RFC 6979, which enables us to use the signing function without randomness.
The original code has been hosted in GnuTLS for a while, implemented as a custom random function which can be used in combination with dsa_sign and ecdsa_sign. While this approach works in general, it requires pre/post processing: e.g., access to ECC q[1] and cancelling out the Nettle's tweak in dsa_sign adding 1[2] to the random value. Therefore, I would rather like this to be included in Nettle itself. Note also that this implementation should be identical to the latest code in GnuTLS, which addresses the Minerva attack[3].
The same patch is also available at GitLab: https://git.lysator.liu.se/nettle/nettle/-/merge_requests/64
Footnotes: [1] https://gitlab.com/gnutls/gnutls/-/blob/c1428c07d406f18cca94f94e2b7ca1f866df...
[2] https://gitlab.com/gnutls/gnutls/-/blob/c1428c07d406f18cca94f94e2b7ca1f866df...
[3] https://nvd.nist.gov/vuln/detail/CVE-2024-28834
Regards,
Daiki Ueno ueno@gnu.org writes:
The attached patch adds support for the deterministic DSA and ECDSA, as defined in RFC 6979, which enables us to use the signing function without randomness.
Thanks, I've had a first read, and added some comments on your MR (https://git.lysator.liu.se/nettle/nettle/-/merge_requests/64).
Regards, /Niels
Niels Möller nisse@lysator.liu.se writes:
Daiki Ueno ueno@gnu.org writes:
The attached patch adds support for the deterministic DSA and ECDSA, as defined in RFC 6979, which enables us to use the signing function without randomness.
Thanks, I've had a first read, and added some comments on your MR (https://git.lysator.liu.se/nettle/nettle/-/merge_requests/64).
Thank you; I updated the MR to address those comments.
I have a slight feeling that the current API is not easy to use, as the caller needs to instantiate both hash and HMAC contexts, as there are no correlations between the two:
struct sha256_ctx sha256; sha256_init (&sha256); sha256_update (&sha256, length, message); sha256_digest (&sha256, SHA256_DIGEST_SIZE, digest);
struct hmac_sha256_ctx hmac_sha256; ecdsa_sign_deterministic (&key, &hmac_sha256, &nettle_hmac_sha256, digest, &sig);
What would you say to introducing a specialized API, something like the following?
void ecdsa_sha256_sign_deterministic (const struct ecc_scalar *key, size_t length, const uint8_t *message, struct dsa_signature *signature);
Regards,
Daiki Ueno ueno@gnu.org writes:
I have a slight feeling that the current API is not easy to use, as the caller needs to instantiate both hash and HMAC contexts, as there are no correlations between the two:
On a more abstract level, are there any reasonable usecases for having one hash function for processing the message, and a different underlying hash function for the hmac used to produce the deterministic nonce?
What would you say to introducing a specialized API, something like the following?
void ecdsa_sha256_sign_deterministic (const struct ecc_scalar *key, size_t length, const uint8_t *message, struct dsa_signature *signature);
I think that could sense, but we also need an advertised api function that takes the digest as input, for applications that want to process the message using multiple _update calls.
Regards, /Niels
Niels Möller nisse@lysator.liu.se writes:
Daiki Ueno ueno@gnu.org writes:
I have a slight feeling that the current API is not easy to use, as the caller needs to instantiate both hash and HMAC contexts, as there are no correlations between the two:
On a more abstract level, are there any reasonable usecases for having one hash function for processing the message, and a different underlying hash function for the hmac used to produce the deterministic nonce?
Not that I know of. The RFC mandates the same hash function to be used in both for processing the message and generating a nonce.
What would you say to introducing a specialized API, something like the following?
void ecdsa_sha256_sign_deterministic (const struct ecc_scalar *key, size_t length, const uint8_t *message, struct dsa_signature *signature);
I think that could sense, but we also need an advertised api function that takes the digest as input, for applications that want to process the message using multiple _update calls.
I agree, that's a valid use-case. Perhaps this might suffice:
/* Sign DIGEST with KEY using deterministic nonce generation. * * DIGEST must be of the same length of SHA-256 output, that is 32 * octets long. */ void ecdsa_sha256_sign_deterministic (const struct ecc_scalar *key, const uint8_t *digest, struct dsa_signature *signature);
Regards,
Daiki Ueno ueno@gnu.org writes:
I agree, that's a valid use-case. Perhaps this might suffice:
/* Sign DIGEST with KEY using deterministic nonce generation.
- DIGEST must be of the same length of SHA-256 output, that is 32
- octets long. */
void ecdsa_sha256_sign_deterministic (const struct ecc_scalar *key, const uint8_t *digest, struct dsa_signature *signature);
Looks good to me. Underlying more general helper functions (however they are organized) can be internal only.
Regards, /Niels
Niels Möller nisse@lysator.liu.se writes:
Daiki Ueno ueno@gnu.org writes:
I agree, that's a valid use-case. Perhaps this might suffice:
/* Sign DIGEST with KEY using deterministic nonce generation.
- DIGEST must be of the same length of SHA-256 output, that is 32
- octets long. */
void ecdsa_sha256_sign_deterministic (const struct ecc_scalar *key, const uint8_t *digest, struct dsa_signature *signature);
Looks good to me. Underlying more general helper functions (however they are organized) can be internal only.
I've updated the MR along these lines.
Regards,
nettle-bugs@lists.lysator.liu.se