crypto/ecdsa: verify signature after signing to prevent faults from leaking private key
What version of Go are you using (go version)?
$ go version go version go1.19 linux/amd64
Does this issue reproduce with the latest release?
Yes.
What did you do?
It has been well known for quite some time that a single signature fault (e.g. due to a bit-flip or truncation) can lead to leaking the private key producing that signature. The crypto/rsa package has contained a defense against just such circumstances since 2015.
However, it is also possible for signature faults to leak ECDSA private keys. In particular, it has been shown that ECDSA private keys can be leaked if the same message is signed twice and one of those two signatures suffers a fault. This attack was recently demonstrated (PDF link) to be practical.
What did you expect to see?
I expected that ECDSA signatures would be validated immediately after being produced, in order to prevent faulty signatures from being exposed to an outside attacker.
What did you see instead?
I do not see any signature verification happening in the ecdsa call stack.
Additional information
I believe that the golang stdlib ecdsa implementation is not actually vulnerable to the signature fault attack as described above. In particular, that attack relies on the fact that many ecdsa implementations skirted the issue of bad random nonce generators by adopting deterministic nonces. It appears that the ecdsa implementation here uses true randomness, and is therefore not vulnerable. However I do believe that the implementation today could silently produce faulty signatures, which we may want to avoid as both a correctness and a defense-in-depth measure.
cc @golang/security
Faults can always cause incorrect outputs, for example by happening after the signature is generated and verified. This is a major problem if the fault leaks the private key, but crypto/ecdsa's implementation doesn't since the nonce is derived from both randomness, secrets, and the message, as you point out. I don't see why adding the complexity and performance cost of verifying the signature would help us.
A better argument could be made for Ed25519, though, which is deterministic.
Yep, it appears that Ed25519 is vulnerable to single fault attacks, and I don't see a verification step in the Ed25519 signing implementation.
Would you like me to repurpose this bug to track that, or file a separate one?