hashicorp/packer · error

unsupported private key in signer %q

Error message

unsupported private key in signer %q

What it means

loadPEMSigner could not parse the PEM block bytes with any supported private-key format: x509.ParsePKCS8PrivateKey, ParsePKCS1PrivateKey, and ParseECPrivateKey all failed. The file contains a PEM block, but its DER payload is not a private key this library understands (or it is corrupted).

Source

Thrown at internal/attestation/sign_key.go:157

	block, _ := pem.Decode(contents)
	if block == nil {
		return nil, nil, fmt.Errorf("decode signer %q: no PEM block found", path)
	}

	var signer crypto.Signer
	if key, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil {
		var ok bool
		signer, ok = key.(crypto.Signer)
		if !ok {
			return nil, nil, fmt.Errorf("signer %q does not implement crypto.Signer", path)
		}
	} else if key, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil {
		signer = key
	} else if key, err := x509.ParseECPrivateKey(block.Bytes); err == nil {
		signer = key
	} else {
		return nil, nil, fmt.Errorf("unsupported private key in signer %q", path)
	}

	publicKeyPEM, err := marshalPublicKeyPEM(signer.Public())
	if err != nil {
		return nil, nil, err
	}

	verifier, err := LoadPEMVerifierBytes(publicKeyPEM)
	if err != nil {
		return nil, nil, err
	}

	return signer, verifier, nil
}

func loadPEMPublicKey(contents []byte) (crypto.PublicKey, []byte, error) {
	block, _ := pem.Decode(contents)
	if block == nil {

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Make sure the file is the PRIVATE key (header '-----BEGIN PRIVATE KEY-----', 'RSA PRIVATE KEY', or 'EC PRIVATE KEY'), not the public key or certificate.
  2. Decrypt encrypted PKCS#8 first: 'openssl pkcs8 -in encrypted.pem -out decrypted.pem' (supply the passphrase).
  3. Validate with 'openssl pkey -in key.pem -noout' to confirm OpenSSL can parse it, then re-export unencrypted.
  4. If the DER is corrupted, regenerate or re-transfer the key file.

Example fix

// before
signer, _, err := attestation.NewSigner("verifier-public.pem") // BEGIN PUBLIC KEY -> unsupported private key
// after
signer, _, err := attestation.NewSigner("signing-key.pem") // BEGIN PRIVATE KEY
Defensive patterns

Strategy: validation

Validate before calling

raw, _ := os.ReadFile(keyPath)
block, _ := pem.Decode(raw)
if block == nil {
	return fmt.Errorf("%s: no PEM block", keyPath)
}
switch block.Type {
case "PRIVATE KEY", "RSA PRIVATE KEY", "EC PRIVATE KEY":
	// supported unencrypted private-key types
default:
	return fmt.Errorf("%s: PEM type %q is not an unencrypted private key (got public key/cert/CSR/encrypted key?)", keyPath, block.Type)
}

Type guard

func isPrivate_KeyPEM(b []byte) bool {
	block, _ := pem.Decode(b)
	if block == nil {
		return false
	}
	switch block.Type {
	case "PRIVATE KEY", "RSA PRIVATE KEY", "EC PRIVATE KEY":
		return true
	}
	return false
}

Try / catch

signer, verifier, err := attestation.NewSigner(keyPath)
if err != nil && strings.Contains(err.Error(), "unsupported private key") {
	return fmt.Errorf("%s is not a PKCS#1/PKCS#8/EC private key; re-export with: openssl pkcs8 -topk8 -nocrypt -in key.pem -out key.pem.new", keyPath)
}

Prevention

When it happens

Trigger: Calling newPEMSigner(path) where the PEM block is a PUBLIC KEY, CERTIFICATE, CSR, ENCRYPTED PRIVATE KEY (legacy encrypted PEM), or otherwise not an unencrypted PKCS#1/PKCS#8/EC private key.

Common situations: Pointing the signer at the public verifier file by mistake; using an 'ENCRYPTED PRIVATE KEY' PKCS#8 blob that requires decryption first; a PEM block of an unrecognized type (e.g. NEW CERTIFICATE REQUEST); a truncated/corrupted DER body.

Related errors


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/2070e692dc260aad. Report an issue: GitHub.