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

proposal: crypto/ecdsa: generate RFC 6979 signatures if rand is nil #64802

Open
FiloSottile opened this issue Dec 19, 2023 · 4 comments
Open
Labels
Proposal Proposal-Crypto Proposal related to crypto packages or other security issues
Milestone

Comments

@FiloSottile
Copy link
Contributor

FiloSottile commented Dec 19, 2023

crypto/ecdsa currently generates "hedged" signatures, by drawing the random nonce from an AES-CTR CSPRNG keyed by SHA2-512(priv.D || entropy || hash)[:32]. This is great, as it provides the best of both worlds: fault injection tolerance and RNG failure resistance.

However, sometimes you do need deterministic signatures, not because they are more secure (as hedged signatures are even better) but because you actually need the signature not to change over time. I propose that when the rand parameter is nil (which currently panics), we produce RFC 6979 deterministic signatures.

Morevoer, Section 3.6 of RFC 6979 specifies how to add additional data to the RNG input, so we can replace our AES-CTR construction with that. The advantage of this would be that although the RFC doesn't have test vectors for this variant, we can generate some and share them with other implementations.

o  Additional data may be added to the input of HMAC, concatenated
      after bits2octets(H(m)):

         K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')

      A use case may be a protocol that requires a non-deterministic
      signature algorithm on a system that does not have access to a
      high-quality random source.  It suffices that the additional data
      k' is non-repeating (e.g., a signature counter or a monotonic
      clock) to ensure "random-looking" signatures are
      indistinguishable, in a cryptographic way, from plain (EC)DSA
      signatures.  In [SP800-90A] terminology, k' is the "additional
      input" that can be set as a parameter when generating pseudorandom
      bits.  This variant can be thought of as a "strengthening" of the
      randomness of the source of the additional data k'.

(The CFRG has a forever-stalled draft on "deterministic with noise" ECDSA signatures, draft-irtf-cfrg-det-sigs-with-noise, but it's unclear to me why we'd want that instead of the existing RFC 6979 mechanism.)

The properties of signatures generated by current applications wouldn't change: they would still be hendged, randomized, and unpredictable (because we use MaybeReadByte, so we can change the internals, yay!).

/cc @golang/security

@FiloSottile FiloSottile added Proposal Proposal-Crypto Proposal related to crypto packages or other security issues labels Dec 19, 2023
@gopherbot gopherbot added this to the Proposal milestone Dec 19, 2023
@FiloSottile
Copy link
Contributor Author

Unfortunately, for RFC 6979 we need to instantiate HMAC with the hash that was used to hash the message. In Sign and SignASN1, we don't have this information, only in PrivateKey.Sign.

We could implement this only for PrivateKey.Sign, or take a pragmatic route and map hash lengths to SHA-256/SHA-512 in SignASN1. (We'd document that, and still do the right thing in PrivateKey.Sign.)

Another wrinkle is that opts is currently ignored in PrivateKey.Sign, so we need to be prepared for current applications setting it wrong.

@gopherbot
Copy link

Change https://go.dev/cl/552215 mentions this issue: crypto/ecdsa: implement RFC6979

@FiloSottile
Copy link
Contributor Author

Ok, since we can't do this properly in Sign and SignASN1, I propose

  1. when the rand parameter to (*PrivateKey).Sign) is nil we produce RFC 6979 deterministic signatures

  2. we add SignDeterministic(priv *PrivateKey, digest []byte, hash crypto.Hash) ([]byte, error)

@FiloSottile
Copy link
Contributor Author

Actually, the top level functions might be worth rethinking in a v2 anyway, especially if we adopt some standard hedged signature scheme such as draft-irtf-cfrg-det-sigs-with-noise, maybe while doing FIPS work.

What I'm proposing here then is just that when the rand parameter to (*PrivateKey).Sign is nil we produce RFC 6979 deterministic signatures. Currently, the function panics if rand is nil.

Deterministic signatures are enough of an uncommon use case that it's ok if they are not super easy to access.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Proposal Proposal-Crypto Proposal related to crypto packages or other security issues
Projects
Status: Incoming
Development

No branches or pull requests

2 participants