go-jose icon indicating copy to clipboard operation
go-jose copied to clipboard

ES256/etc algs produce non-deterministic ECDSA signatures inconsistent with the IETF JWT BCP

Open leighmcculloch opened this issue 4 years ago • 2 comments

In go-jose the ES256/ES384/ES512 algorithms that use ECDSA have been implemented to produce non-deterministic signatures. This means that signing the same JWT payload repeatedly produces a different signature each time.

According to the IETF JSON Web Token Best Current Practices Section 3.2 (JWT BCP) it is best practice to produce deterministic ECDSA signatures as defined by RFC6979 because of the possibility of recovering the private key when non-deterministic ECDSA signatures are used.

The JWT BCP states that:

ECDSA signatures require a unique random value for every message that is signed. If even just a few bits of the random value are predictable across multiple messages then the security of the signature scheme may be compromised. In the worst case, the private key may be recoverable by an attacker.

The JWT BCP goes on to state:

To counter these attacks, JWT libraries SHOULD implement ECDSA using the deterministic approach defined in [RFC6979]. This approach is completely compatible with existing ECDSA verifiers and so can be implemented without new algorithm identifiers being required.

Digging into the code, it looks like go-jose uses the Go stdlib's "crypto/rand".Reader as the random input into "crypto/ecdsa".Sign to produce the non-deterministic signature. I think the relevant code is here:

https://github.com/square/go-jose/blob/c9ac459e06bc9a5ab7efd5d3b3f421d6de27401f/asymmetric.go#L525

According to the godocs for "crypto/ecdsa".Sign:

The security of the private key depends on the entropy of rand.

My interpretation of the above (don't rely on it, I am often wrong) is that this is fine as long as RandReader is unpredictable, but it'd be great if the library followed the JWT Best Current Practices and wasn't dependent on that assumption.

Thanks to @juli and @marcelosalloum for identifying the changing signatures and inconsistency with the JWT BCP.

People tell me this isn't a vulnerability and isn't sensitive, but I took the conservative approach of emailing [email protected] first. There is no security policy on this GitHub repo, and that's the only email I could find. After a couple weeks and multiple emails I didn't receive a response, so I'm posting here.

leighmcculloch avatar Jul 08 '21 18:07 leighmcculloch

Go's crypto/ecdsa is not deterministic, but it's also not resting the security of the private key on the quality of the randomness. We should update the docs. It uses SHA2-512(priv.D || entropy || hash)[:32] as the seed of the CSPRNG, so as long as the private key is safe, the nonce is unpredictable.

FiloSottile avatar Jul 08 '21 22:07 FiloSottile

I had seen https://github.com/golang/go/commit/a8049f5 but wasn't sure if that entirely addressed the issue given the remaining comment on the Sign function. Thanks @FiloSottile!

leighmcculloch avatar Jul 08 '21 23:07 leighmcculloch