{"record":{"id":"18dca7ca48e23946","repo":"ethereum/go-ethereum","slug":"key-generation-ecdsa-generatekey-failed","errorCode":null,"errorMessage":"key generation: ecdsa.GenerateKey failed: ","messagePattern":"key generation: ecdsa\\.GenerateKey failed: ","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"accounts/keystore/key.go","lineNumber":157,"sourceCode":"\t\tAddress:    crypto.PubkeyToAddress(privateKeyECDSA.PublicKey),\n\t\tPrivateKey: privateKeyECDSA,\n\t}\n\treturn key\n}\n\n// NewKeyForDirectICAP generates a key whose address fits into < 155 bits so it can fit\n// into the Direct ICAP spec. for simplicity and easier compatibility with other libs, we\n// retry until the first byte is 0.\nfunc NewKeyForDirectICAP(rand io.Reader) *Key {\n\trandBytes := make([]byte, 64)\n\t_, err := rand.Read(randBytes)\n\tif err != nil {\n\t\tpanic(\"key generation: could not read from random source: \" + err.Error())\n\t}\n\treader := bytes.NewReader(randBytes)\n\tprivateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), reader)\n\tif err != nil {\n\t\tpanic(\"key generation: ecdsa.GenerateKey failed: \" + err.Error())\n\t}\n\tkey := newKeyFromECDSA(privateKeyECDSA)\n\tif !strings.HasPrefix(key.Address.Hex(), \"0x00\") {\n\t\treturn NewKeyForDirectICAP(rand)\n\t}\n\treturn key\n}\n\nfunc newKey(rand io.Reader) (*Key, error) {\n\tprivateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn newKeyFromECDSA(privateKeyECDSA), nil\n}\n\nfunc storeNewKey(ks keyStore, rand io.Reader, auth string) (*Key, accounts.Account, error) {\n\tkey, err := newKey(rand)","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/ethereum/go-ethereum/blob/6bb0588ad8e7f922e4ad5580f51265a4097af08f/accounts/keystore/key.go#L139-L175","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nk := keystore.NewKeyForDirectICAP(zeroReader) // may panic in GenerateKey\n\n// after\nimport \"crypto/rand\"\nk := keystore.NewKeyForDirectICAP(rand.Reader)","handlingStrategy":"validation","validationCode":"func readFullSeed(r io.Reader) ([]byte, error) {\n\tb := make([]byte, 64)\n\tif _, err := io.ReadFull(r, b); err != nil {\n\t\treturn nil, fmt.Errorf(\"seed read: %w\", err)\n\t}\n\treturn b, nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Custom io.Reader implementations must fill the buffer fully and return real randomness.","Prefer crypto/rand.Reader over derived or stubbed readers."],"tags":["go-ethereum","keystore","ecdsa","entropy","panic"],"backgroundTag":null,"analyzedSha":"6bb0588ad8e7f922e4ad5580f51265a4097af08f","analyzedAt":"2026-08-15T10:06:53.996Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}