hyperledger/fabric · error

found unknown private key type (%T) in PKCS#8 wrapping

Error message

found unknown private key type (%T) in PKCS#8 wrapping

What it means

parsePrivateKey first attempts x509.ParsePKCS8PrivateKey; PKCS#8 parsing succeeded but yielded a key type other than *ecdsa.PrivateKey or ed25519.PrivateKey (most commonly *rsa.PrivateKey), so this error names the unsupported type found inside the PKCS#8 structure.

Source

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

	key, err := parsePrivateKey(bl.Bytes)
	if err != nil {
		return nil, err
	}
	return key, nil
}

// 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
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Generate an ECDSA key: openssl ecparam -name prime256v1 -genkey -noout -out key.pem and re-enroll/re-register identity
  2. Convert nothing — RSA keys cannot be converted to ECDSA; obtain a new ECDSA key from the CA
  3. Verify key type: openssl pkey -in key.pem -noout -text (should show 'Private-Key: (256 bit)' with NIST CURVE)
  4. If your tooling must support RSA, extend parsePrivateKey's switch explicitly

Example fix

// before
openssl genrsa -out key.pem 2048
openssl pkcs8 -topk8 -nocrypt -in key.pem -out key.p8
// after
openssl ecparam -name prime256v1 -genkey -noout -out key.pem
Defensive patterns

Strategy: validation

Validate before calling

b, _ := os.ReadFile(keyPath)
blk, _ := pem.Decode(b)
key, err := x509.ParsePKCS8PrivateKey(blk.Bytes)
if err == nil {
    switch key.(type) {
    case *ecdsa.PrivateKey, ed25519.PrivateKey:
    default:
        return fmt.Errorf("unsupported PKCS#8 key type %T", key)
    }
}

Type guard

func isSupportedPKCS8(b []byte) bool {
    blk, _ := pem.Decode(b)
    if blk == nil { return false }
    k, err := x509.ParsePKCS8PrivateKey(blk.Bytes)
    if err != nil { return true /* may be SEC1, handled later */ }
    switch k.(type) {
    case *ecdsa.PrivateKey, ed25519.PrivateKey:
        return true
    }
    return false
}

Try / catch

s, err := signer.NewSigner(keyPath, idPath)
if err != nil {
    if strings.Contains(err.Error(), "PKCS#8 wrapping") {
        return fmt.Errorf("key %s is RSA; provision an ECDSA key", keyPath)
    }
    return err
}

Prevention

When it happens

Trigger: Loading a PKCS#8-wrapped RSA private key (e.g. '-----BEGIN PRIVATE KEY-----' containing an RSA key) via NewSigner -> loadPrivateKey -> parsePrivateKey and calling Sign.

Common situations: Keys generated with default openssl genrsa then converted to PKCS#8; cloud CAs issuing RSA keys by default; shared scripts generating keys without specifying EC curve.

Related errors


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