ethereum/go-ethereum · critical
key generation: ecdsa.GenerateKey failed:
Error message
key generation: ecdsa.GenerateKey failed:
What it means
After successfully reading 64 random bytes, NewKeyForDirectICAP runs ecdsa.GenerateKey over secp256k1 seeded by those bytes. If key generation itself errors it panics with 'key generation: ecdsa.GenerateKey failed: ' plus the cause. With a full 64-byte random seed this virtually never fails; hitting it means the reader produced biased/insufficient entropy or the crypto backend is broken.
Source
Thrown at accounts/keystore/key.go:157
Address: crypto.PubkeyToAddress(privateKeyECDSA.PublicKey),
PrivateKey: privateKeyECDSA,
}
return key
}
// NewKeyForDirectICAP generates a key whose address fits into < 155 bits so it can fit
// into the Direct ICAP spec. for simplicity and easier compatibility with other libs, we
// retry until the first byte is 0.
func NewKeyForDirectICAP(rand io.Reader) *Key {
randBytes := make([]byte, 64)
_, err := rand.Read(randBytes)
if err != nil {
panic("key generation: could not read from random source: " + err.Error())
}
reader := bytes.NewReader(randBytes)
privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), reader)
if err != nil {
panic("key generation: ecdsa.GenerateKey failed: " + err.Error())
}
key := newKeyFromECDSA(privateKeyECDSA)
if !strings.HasPrefix(key.Address.Hex(), "0x00") {
return NewKeyForDirectICAP(rand)
}
return key
}
func newKey(rand io.Reader) (*Key, error) {
privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand)
if err != nil {
return nil, err
}
return newKeyFromECDSA(privateKeyECDSA), nil
}
func storeNewKey(ks keyStore, rand io.Reader, auth string) (*Key, accounts.Account, error) {
key, err := newKey(rand)View on GitHub (pinned to 6bb0588ad8)
Solutions
- Use crypto/rand.Reader for real key generation rather than stubbed/derived readers.
- Ensure your custom reader fully fills the 64-byte slice and returns high-quality randomness.
- Check the panic-appended error for read errors masquerading as GenerateKey failures (partial reads).
- Re-run with the OS entropy source; if it persists, suspect the build/toolchain.
Example fix
// before k := keystore.NewKeyForDirectICAP(zeroReader) // may panic in GenerateKey // after import "crypto/rand" k := keystore.NewKeyForDirectICAP(rand.Reader)
Defensive patterns
Strategy: validation
Validate before calling
func readFullSeed(r io.Reader) ([]byte, error) {
b := make([]byte, 64)
if _, err := io.ReadFull(r, b); err != nil {
return nil, fmt.Errorf("seed read: %w", err)
}
return b, nil
} Prevention
- Custom io.Reader implementations must fill the buffer fully and return real randomness.
- Prefer crypto/rand.Reader over derived or stubbed readers.
When it happens
Trigger: NewKeyForDirectICAP(rand) where rand.Read succeeded but returned low-entropy or repeated data (e.g. a reader always returning zeros from a stubbed source), causing GenerateKey's internal key validation to reject the result; or a corrupted/fuzzed crypto build.
Common situations: Tests stubbing the io.Reader with zeros or a short repeating pattern instead of real randomness; readers that return (n, nil) without filling the buffer; exotic architectures with a broken curve implementation.
Related errors
- Could not create random uuid: %v
- key generation: could not read from random source:
- reading from crypto/rand failed:
- nil chainID
- error decoding contract deployer hex %s: %v
AI-assisted analysis of ethereum/go-ethereum@6bb0588ad8 (2026-08-15).
Data as JSON: /api/errors/18dca7ca48e23946.
Report an issue: GitHub.