hashicorp/packer · error

marshal public key: %w

Error message

marshal public key: %w

What it means

marshalPublicKeyPEM wraps a failure from x509.MarshalPKIXPublicKey, the step that converts a parsed key into SubjectPublicKeyInfo DER before PEM-encoding. This function is used to derive the public counterpart of a loaded signer or Fulcio certificate. MarshalPKIXPublicKey fails almost exclusively when the crypto.PublicKey is of a type the standard library cannot serialize into SPKI form (in practice: unsupported key algorithms; RSA, ECDSA and Ed25519 always succeed).

Source

Thrown at internal/attestation/sign_key.go:229

	}

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

	publicKey, _, err := loadPEMPublicKey(publicKeyPEM)
	if err != nil {
		return nil, nil, err
	}

	return publicKey, publicKeyPEM, nil
}

func marshalPublicKeyPEM(publicKey crypto.PublicKey) ([]byte, error) {
	encoded, err := x509.MarshalPKIXPublicKey(publicKey)
	if err != nil {
		return nil, fmt.Errorf("marshal public key: %w", err)
	}

	return pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: encoded}), nil
}

func sha256Hex(value []byte) string {
	digest := sha256.Sum256(value)
	return hex.EncodeToString(digest[:])
}

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Identify the key algorithm ('openssl pkey -in key.pem -text -noout'); if it is DSA, regenerate the key as RSA, ECDSA (P-256/384/521) or Ed25519.
  2. Convert the key to a supported algorithm: 'openssl genpkey -algorithm RSA ...' or 'openssl genpkey -algorithm ED25519', then update the configured signer.
  3. If the key is fine but the file is not, re-export it in PKCS#8 ('openssl pkcs8 -topk8 -nocrypt') so parsing yields a standard key type.
  4. If this happens with a certificate-derived key, check the certificate's Public Key Algorithm field ('openssl x509 -in cert.pem -noout -text'); use a certificate with an RSA/EC/Ed25519 key.
  5. Inspect the wrapped inner error from MarshalPKIXPublicKey — it names the specific marshal failure.

Example fix

// before: DSA key in PKCS#8 -> parses, but MarshalPKIXPublicKey fails
// signer.pem: DSA PRIVATE KEY
// after: generate a supported key and reconfigure
//   openssl genpkey -algorithm ED25519 -out signer.pem
// signer ref = signer.pem
Defensive patterns

Strategy: validation

Validate before calling

// pre-flight: round-trip the key's public part through SPKI marshal
func canMarshalPublicKey(path string) error {
	data, _ := os.ReadFile(path)
	block, _ := pem.Decode(data)
	if block == nil {
		return fmt.Errorf("no PEM block")
	}
	key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return err
	}
	signer, ok := key.(crypto.Signer)
	if !ok {
		return fmt.Errorf("not a crypto.Signer")
	}
	if _, err := x509.MarshalPKIXPublicKey(signer.Public()); err != nil {
		return fmt.Errorf("algorithm %T not SPKI-marshalable: %w", signer.Public(), err)
	}
	return nil
}

Type guard

func isSPKIMarshalable(pub crypto.PublicKey) bool {
	switch pub.(type) {
	case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey:
		return true
	default:
		return false // e.g. *dsa.PublicKey, custom key types
	}
}

Try / catch

signer, verifier, err := loadPEMSigner(keyPath)
if err != nil {
	if strings.Contains(err.Error(), "marshal public key") {
		return fmt.Errorf("signer %s: public key algorithm not supported by x509.MarshalPKIXPublicKey; regenerate as RSA/ECDSA/Ed25519: %w", keyPath, err)
	}
	return err
}

Prevention

When it happens

Trigger: Any caller — loadPEMSigner, loadPEMPrivateKeyAsPublic, or newSigstoreVerifierFromPublicKey — passes a crypto.PublicKey that x509.MarshalPKIXPublicKey cannot marshal, e.g. a DSA public key recovered from a PKCS#8 blob, or a custom/foreign key type implementing crypto.Signer with an exotic PublicKey().

Common situations: A DSA private key in PKCS#8 format parses fine via ParsePKCS8PrivateKey (implementing crypto.Signer) but its DSA public key cannot be marshalled to SPKI, producing this error. Also possible when a Fulcio certificate carries an unexpected public-key algorithm, or with exotic smartcard/HSM-backed signer types whose Public() returns a non-standard type.

Related errors


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