kgretzky/evilginx2 · critical

private key generation failed

Error message

private key generation failed

What it means

generateCertificates (called from NewCertDb) throws this when crypto/rand rsa.GenerateKey(2048) fails during regeneration of the CA private key. The previous key was already determined to be missing or corrupted, so this is a last-resort failure. It deliberately discards the underlying error detail and returns a fixed message.

Source

Thrown at core/certdb.go:94

	}
	return email
}

func (o *CertDb) generateCertificates() error {
	var key *rsa.PrivateKey

	pkey, err := ioutil.ReadFile(filepath.Join(o.cache_dir, "private.key"))
	if err != nil {
		pkey, err = ioutil.ReadFile(filepath.Join(o.cache_dir, "ca.key"))
	}

	if err != nil {
		// private key corrupted or not found, recreate and delete all public certificates
		os.RemoveAll(filepath.Join(o.cache_dir, "*"))

		key, err = rsa.GenerateKey(rand.Reader, 2048)
		if err != nil {
			return fmt.Errorf("private key generation failed")
		}
		pkey = pem.EncodeToMemory(&pem.Block{
			Type:  "RSA PRIVATE KEY",
			Bytes: x509.MarshalPKCS1PrivateKey(key),
		})
		err = ioutil.WriteFile(filepath.Join(o.cache_dir, "ca.key"), pkey, 0600)
		if err != nil {
			return err
		}
	} else {
		block, _ := pem.Decode(pkey)
		if block == nil {
			return fmt.Errorf("private key is corrupted")
		}

		key, err = x509.ParsePKCS1PrivateKey(block.Bytes)
		if err != nil {
			return err

View on GitHub (pinned to 4c0988a1d9)

Solutions

  1. Verify /dev/urandom is available and getrandom(2) is not blocked by the container/seccomp profile, then restart
  2. Clear the cache_dir so a fresh, valid key can be written and re-run
  3. Check disk permissions/space for writing ca.key (0600) in cache_dir
  4. Update Go / the library if running on a platform with known crypto/rand issues

Example fix

// before
os.RemoveAll(filepath.Join(o.cache_dir, "*")) // glob does not expand; cache may persist
// after
os.RemoveAll(o.cache_dir)
os.MkdirAll(o.cache_dir, 0700)
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check the environment before NewCertDb
f, err := os.Open("/dev/urandom")
if err != nil { log.Fatal("no entropy source available") }
f.Close()
if st, err := os.Stat(cacheDir); err != nil || !st.IsDir() { os.MkdirAll(cacheDir, 0700) }

Try / catch

db, err := NewCertDb(cacheDir, "")
if err != nil {
    if err.Error() == "private key generation failed" {
        // entropy/RNG issue: check /dev/urandom, seccomp, then retry
        log.Fatal("cannot generate RSA key: check entropy source and container policy")
    }
    log.Fatal(err)
}

Prevention

When it happens

Trigger: NewCertDb cannot read the cached ca.key, deletes the cache (os.RemoveAll of the cache dir), and then rsa.GenerateKey fails — practically only when the system CSPRNG (rand.Reader) fails or is unavailable (e.g. broken /dev/urandom in a stripped container).

Common situations: Containers/seccomp sandboxes blocking getrandom(); extremely constrained environments; corrupted cache_dir contents triggering the recreate path where a latent RNG problem then surfaces.

Related errors


AI-assisted analysis of kgretzky/evilginx2@4c0988a1d9 (2026-09-05). Data as JSON: /api/errors/476fba71f18363df. Report an issue: GitHub.