wevm / viem

TypeScript Interface for Ethereum
https://viem.sh
Other
2.56k stars 852 forks source link

Improve security of signature generation #3028

Closed paulmillr closed 21 hours ago

paulmillr commented 1 day ago

Problem

Transaction signatures use "nonce" / "k" during their construction. The nonce should never be equal between two different messages. Reusing them would allow attacker to recover private key.

Many years ago, nonce was generated using system randomness. On some systems with bad quality of randomness, that lead to breakages.

Today, the nonce is generated from private key and message hash using RFC 6979. Basically hash(private_key, message). However, if some issue would be found in serialization / parsing of those, and during generation of nonce, it would still be possible to recover private keys. The technique is described here: https://github.com/pcaversaccio/ecdsa-nonce-reuse-attack.

Impact

Private key leakage, hackers stealing money from users.

This is not some theoretical issue. This happened in the past. Soon there would be announcement of a new hack related to this.

Solution

Use RFC6979 3.6: additional k' extraData to mix-in 32 byte of random data on every signature. It is standard way of doing this. It has been extensively used by Bitcoin for non-taproot transactions, to decrease signature size.

https://github.com/wevm/viem/blob/0c98d991b5ec6990251486d860349718f8e7ea04/src/accounts/utils/sign.ts#L36-L41

secp256k1.sign(msgHash, privateKey) becomes secp256k1.sign(msgHash, privateKey, { extraData: true })

Disadvantages

There is no risk for security. If passed-through random is bad, the signature security would be just like today, not worse

paulmillr commented 14 hours ago

@jxom you can pass uint8array with specific extraData to ensure determinism in tests