hyperledger/fabric · error

failed to parse private key: %v

Error message

failed to parse private key: %v

What it means

If the DER bytes are not PKCS#8 (or fail to parse), parsePrivateKey falls back to x509.ParseECPrivateKey to handle SEC1 EC keys generated by 'openssl ecparam'. When that also fails, this error wraps the underlying parse failure, meaning the key is neither valid PKCS#8 nor a SEC1 EC private key.

Source

Thrown at cmd/common/signer/signer.go:143

// Based on crypto/tls/tls.go but modified for Fabric:
func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
	// OpenSSL 1.0.0 generates PKCS#8 keys.
	if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
		switch key := key.(type) {
		// Fabric only supports ECDSA at the moment.
		case *ecdsa.PrivateKey:
			return key, nil
		case ed25519.PrivateKey:
			return key, nil
		default:
			return nil, errors.Errorf("found unknown private key type (%T) in PKCS#8 wrapping", key)
		}
	}

	// OpenSSL ecparam generates SEC1 EC private keys for ECDSA.
	key, err := x509.ParseECPrivateKey(der)
	if err != nil {
		return nil, errors.Errorf("failed to parse private key: %v", err)
	}

	return key, nil
}

func signECDSA(k *ecdsa.PrivateKey, digest []byte) (signature []byte, err error) {
	r, s, err := ecdsa.Sign(rand.Reader, k, digest)
	if err != nil {
		return nil, err
	}

	s, err = utils.ToLowS(&k.PublicKey, s)
	if err != nil {
		return nil, err
	}

	return marshalECDSASignature(r, s)
}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Decrypt the key first: openssl pkey -in key.pem -passin pass:... -out key_nocrypt.pem
  2. Convert to supported format: openssl ecparam/openssl pkey to produce an unencrypted EC PEM key
  3. Check the PEM header — 'ENCRYPTED PRIVATE KEY' or 'RSA PRIVATE KEY' indicates the unsupported case
  4. Re-export the key from the MSP/cert-authority source and confirm with openssl pkey -noout -text

Example fix

// before: encrypted key
-----BEGIN ENCRYPTED PRIVATE KEY-----
// after
openssl pkcs8 -topk8 -nocrypt -in key.pem -out key_nocrypt.pem
# or: openssl pkey -in enc.pem -passin pass:secret -out key.pem
Defensive patterns

Strategy: validation

Validate before calling

b, _ := os.ReadFile(keyPath)
blk, _ := pem.Decode(b)
if strings.Contains(blk.Headers["Proc-Type"], "ENCRYPTED") || blk.Type == "ENCRYPTED PRIVATE KEY" {
    return fmt.Errorf("%s is encrypted; decrypt before use", keyPath)
}
if _, err := x509.ParseECPrivateKey(blk.Bytes); err != nil {
    if _, err8 := x509.ParsePKCS8PrivateKey(blk.Bytes); err8 != nil {
        return fmt.Errorf("%s is neither PKCS#8 nor SEC1 EC key", keyPath)
    }
}

Try / catch

s, err := signer.NewSigner(keyPath, idPath)
if err != nil {
    if strings.Contains(err.Error(), "failed to parse private key") {
        return fmt.Errorf("key %s unparseable; decrypt/convert with openssl pkey", keyPath)
    }
    return err
}

Prevention

When it happens

Trigger: Key file contains an encrypted PEM block (passphrase-protected, pem.Decode yields the block but DER is encrypted), an RSA/PKCS#1 key that failed PKCS#8 parse, corrupted DER, or a public key instead of a private key.

Common situations: Passphrase-protected key with no decryption step; PKCS#1 RSA key ('BEGIN RSA PRIVATE KEY') rejected by both parsers; truncated or edited key file; copied key missing lines.

Understand the failure class

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/216fe8e4490eb711. Report an issue: GitHub.