{"record":{"id":"d88664efcaa44fa4","repo":"grafana/k6","slug":"encrypted-pkcs8-formatted-key-is-not-supported","errorCode":null,"errorMessage":"encrypted pkcs8 formatted key is not supported","messagePattern":"encrypted pkcs8 formatted key is not supported","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/grpc/client.go","lineNumber":133,"sourceCode":"\n\tfdset := &descriptorpb.FileDescriptorSet{}\n\tif err = proto.Unmarshal(fdsetBytes, fdset); err != nil {\n\t\treturn nil, fmt.Errorf(\"couldn't unmarshal protoset file %s: %w\", protosetPath, err)\n\t}\n\n\treturn c.convertToMethodInfo(fdset)\n}\n\n// Note: this function was lifted from `lib/options.go`\nfunc decryptPrivateKey(key, password []byte) ([]byte, error) {\n\tblock, _ := pem.Decode(key)\n\tif block == nil {\n\t\treturn nil, errors.New(\"failed to decode PEM key\")\n\t}\n\n\tblockType := block.Type\n\tif blockType == \"ENCRYPTED PRIVATE KEY\" {\n\t\treturn nil, errors.New(\"encrypted pkcs8 formatted key is not supported\")\n\t}\n\t/*\n\t   Even though `DecryptPEMBlock` has been deprecated since 1.16.x it is still\n\t   being used here because it is deprecated due to it not supporting *good* cryptography\n\t   ultimately though we want to support something so we will be using it for now.\n\t*/\n\tdecryptedKey, err := x509.DecryptPEMBlock(block, password) //nolint:staticcheck\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tkey = pem.EncodeToMemory(&pem.Block{\n\t\tType:  blockType,\n\t\tBytes: decryptedKey,\n\t})\n\treturn key, nil\n}\n\nfunc buildTLSConfig(parentConfig *tls.Config, certificate, key []byte, caCertificates [][]byte) (*tls.Config, error) {","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/grpc/client.go#L115-L151","documentation":"k6's encrypted-key decryption uses the legacy x509.DecryptPEMBlock API, which only understands traditional OpenSSL PEM encryption. Keys with block type 'ENCRYPTED PRIVATE KEY' (PKCS#8, e.g. PBES2 output of openssl pkcs8 -topk8 / genpkey with a passphrase) are explicitly rejected before decryption is attempted.","triggerScenarios":"client.connect(addr, { tls: { certs: [[cert, key, password]] } }) where key is an encrypted PKCS#8 file (header -----BEGIN ENCRYPTED PRIVATE KEY-----).","commonSituations":"Keys provisioned by modern openssl defaults (genpkey + pkcs8 -topk8), cloud KMS exports, or company PKI tooling that standardizes on PKCS#8 encryption.","solutions":["Decrypt to an unencrypted key: openssl pkcs8 -in key.enc.pem -nodes -out key.pem","Or convert to traditional RSA PEM encryption: openssl rsa -in key.enc.pem -aes256 -out key.trad.pem (then pass the new password)","Long-term: track the upstream k6 issue for PKCS#8 support instead of working around per script"],"exampleFix":"# before: key has '-----BEGIN ENCRYPTED PRIVATE KEY-----'\n# after: produce a supported format\nopenssl pkcs8 -in key.enc.pem -nodes -out key.pem\n# then connect without a password for that cert pair:\nclient.connect(addr, { tls: { certs: [[certPem, keyPem]] } });","handlingStrategy":"validation","validationCode":"function isEncryptedPkcs8(pem) {\n  return pem.trim().startsWith('-----BEGIN ENCRYPTED PRIVATE KEY-----');\n}\n\nif (isEncryptedPkcs8(keyPem)) {\n  throw new Error('k6 does not support encrypted PKCS#8 keys; convert with: openssl pkcs8 -in key.pem -nodes -out key-decrypted.pem');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Standardize team keys on unencrypted PEM or traditional RSA PEM encryption","Inspect the BEGIN header of any key generated by openssl genpkey/pkcs8 -topk8","Decrypt copies used for load testing and keep the encrypted originals in the secret store"],"tags":["grpc","tls","pkcs8","cryptography","certificates"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}