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

  1. Use crypto/rand.Reader for real key generation rather than stubbed/derived readers.
  2. Ensure your custom reader fully fills the 64-byte slice and returns high-quality randomness.
  3. Check the panic-appended error for read errors masquerading as GenerateKey failures (partial reads).
  4. 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

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


AI-assisted analysis of ethereum/go-ethereum@6bb0588ad8 (2026-08-15). Data as JSON: /api/errors/18dca7ca48e23946. Report an issue: GitHub.