{"record":{"id":"0dcd477b8b30f387","repo":"hashicorp/packer","slug":"signer-q-does-not-implement-crypto-signer","errorCode":null,"errorMessage":"signer %q does not implement crypto.Signer","messagePattern":"signer %q does not implement crypto\\.Signer","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/attestation/sign_key.go","lineNumber":150,"sourceCode":"}\n\nfunc loadPEMSigner(path string) (crypto.Signer, *pemVerifier, error) {\n\tcontents, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"read signer %q: %w\", path, err)\n\t}\n\n\tblock, _ := pem.Decode(contents)\n\tif block == nil {\n\t\treturn nil, nil, fmt.Errorf(\"decode signer %q: no PEM block found\", path)\n\t}\n\n\tvar signer crypto.Signer\n\tif key, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil {\n\t\tvar ok bool\n\t\tsigner, ok = key.(crypto.Signer)\n\t\tif !ok {\n\t\t\treturn nil, nil, fmt.Errorf(\"signer %q does not implement crypto.Signer\", path)\n\t\t}\n\t} else if key, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil {\n\t\tsigner = key\n\t} else if key, err := x509.ParseECPrivateKey(block.Bytes); err == nil {\n\t\tsigner = key\n\t} else {\n\t\treturn nil, nil, fmt.Errorf(\"unsupported private key in signer %q\", path)\n\t}\n\n\tpublicKeyPEM, err := marshalPublicKeyPEM(signer.Public())\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tverifier, err := LoadPEMVerifierBytes(publicKeyPEM)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/internal/attestation/sign_key.go#L132-L168","documentation":"The PEM block parsed successfully as a PKCS#8 private key, but the resulting Go value does not implement crypto.Signer, so it cannot be used to sign attestations. loadPEMSigner rejects it rather than returning a signer that cannot Sign(). This typically means the PKCS#8 payload wraps a key type the signer path cannot use.","triggerScenarios":"Calling newPEMSigner(path) where the file holds a PKCS#8 structure whose parsed key is not a crypto.Signer (e.g. certain PKCS#8-wrapped key agreement/key encapsulation payloads, or unusual key types like ed25519ph containers depending on the Go version).","commonSituations":"Key exported from an HSM or PKCS#12 bundle with an unusual algorithm identifier; a key generated for encryption-only use; mismatch between the declared OID in the PKCS#8 blob and an actual signing key.","solutions":["Regenerate a standard signing key: 'openssl genpkey -algorithm ED25519' or '-algorithm RSA' / 'EC', then export as PKCS#8 PEM.","Re-export the key so the PKCS#8 payload contains a normal RSA/EC/Ed25519 private key.","Confirm what Go parsed by running x509.ParsePKCS8PrivateKey on the block bytes in a small test and printing the concrete type.","If the key lives in an HSM, use a crypto.Signer handle (PKCS#11) rather than a PEM file, or export a software signing key."],"exampleFix":"// before\n$ openssl genpkey -algorithm <non-signing KEM> -out signer.pem\nsigner, _, err := attestation.NewSigner(\"signer.pem\") // does not implement crypto.Signer\n// after\n$ openssl genpkey -algorithm ED25519 -out signer.pem\nsigner, _, err := attestation.NewSigner(\"signer.pem\") // ok","handlingStrategy":"validation","validationCode":"raw, _ := os.ReadFile(keyPath)\nblock, _ := pem.Decode(raw)\nif block == nil {\n\treturn fmt.Errorf(\"%s: no PEM block\", keyPath)\n}\nkey, err := x509.ParsePKCS8PrivateKey(block.Bytes)\nif err != nil {\n\treturn err // falls through to PKCS1/EC handling in the library\n}\nif _, ok := key.(crypto.Signer); !ok {\n\treturn fmt.Errorf(\"%s: PKCS#8 key type %T cannot sign; regenerate with RSA/EC/Ed25519\", keyPath, key)\n}","typeGuard":"func isCryptoSigner(key any) bool {\n\t_, ok := key.(crypto.Signer)\n\treturn ok\n}","tryCatchPattern":"signer, verifier, err := attestation.NewSigner(keyPath)\nif err != nil && strings.Contains(err.Error(), \"does not implement crypto.Signer\") {\n\treturn fmt.Errorf(\"%s holds a non-signing key; regenerate: openssl genpkey -algorithm ED25519 -out %s\", keyPath, keyPath)\n}","preventionTips":["Generate signing keys only with standard algorithms: RSA, ECDSA, or Ed25519.","Avoid keys exported from HSMs/PKCS#12 with non-signing algorithm identifiers; use a real crypto.Signer integration instead.","Pre-check parsed key types in a smoke test before production signing.","Keep tool-generated key material and its intended use documented to prevent mismatches."],"tags":["go","crypto","pkcs8","signing"],"backgroundTag":"key-not-crypto-signer","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}