{"record":{"id":"e78902e1f052c77b","repo":"router-for-me/CLIProxyAPI","slug":"private-key-invalid-pkcs8-w","errorCode":null,"errorMessage":"private_key invalid pkcs8: %w","messagePattern":"private_key invalid pkcs8: %w","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/auth/vertex/keyutil.go","lineNumber":101,"sourceCode":"\treturn string(pem.EncodeToMemory(rsaBlock)), nil\n}\n\nfunc ensureRSAPrivateKey(block *pem.Block) (*pem.Block, error) {\n\tif block == nil {\n\t\treturn nil, fmt.Errorf(\"pem block is nil\")\n\t}\n\n\tif block.Type == \"RSA PRIVATE KEY\" {\n\t\tif _, err := x509.ParsePKCS1PrivateKey(block.Bytes); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"private_key invalid rsa: %w\", err)\n\t\t}\n\t\treturn block, nil\n\t}\n\n\tif block.Type == \"PRIVATE KEY\" {\n\t\tkey, err := x509.ParsePKCS8PrivateKey(block.Bytes)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"private_key invalid pkcs8: %w\", err)\n\t\t}\n\t\trsaKey, ok := key.(*rsa.PrivateKey)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"private_key is not an RSA key\")\n\t\t}\n\t\tder := x509.MarshalPKCS1PrivateKey(rsaKey)\n\t\treturn &pem.Block{Type: \"RSA PRIVATE KEY\", Bytes: der}, nil\n\t}\n\n\t// Attempt auto-detection: try PKCS#1 first, then PKCS#8.\n\tif rsaKey, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil {\n\t\tder := x509.MarshalPKCS1PrivateKey(rsaKey)\n\t\treturn &pem.Block{Type: \"RSA PRIVATE KEY\", Bytes: der}, nil\n\t}\n\tif key, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil {\n\t\tif rsaKey, ok := key.(*rsa.PrivateKey); ok {\n\t\t\tder := x509.MarshalPKCS1PrivateKey(rsaKey)\n\t\t\treturn &pem.Block{Type: \"RSA PRIVATE KEY\", Bytes: der}, nil","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/auth/vertex/keyutil.go#L83-L119","documentation":"From ensureRSAPrivateKey when the PEM block is typed 'PRIVATE KEY' (PKCS#8 generic) but x509.ParsePKCS8PrivateKey fails on its DER bytes (keyutil.go:98-101). The wrapper is fine; the inner ASN.1 payload is not parseable as any PKCS#8 key.","triggerScenarios":"Corrupted or truncated PKCS#8 DER body; encrypted PKCS#8 (PBES2) keys whose DER begins with encryption parameters Go parses but rejects as an unparseable plain key; mismatched base64 padding introduced by hand edits.","commonSituations":"Downloading keys through tools that mangle base64 line lengths; using encrypted export formats from other clouds; byte-level truncation in CI secret variables.","solutions":["Validate independently: openssl pkcs8 -in key.pem -nocrypt -noout; if it fails, the key file itself is bad","Re-export an unencrypted PKCS#8 RSA key or, simplest, re-download the GCP service account JSON","If the key is PBES2-encrypted, decrypt it first (openssl pkcs8 -passin ...) and store the plaintext in the secret manager"],"exampleFix":"# before: encrypted PKCS#8 stored raw\n-----BEGIN ENCRYPTED PRIVATE KEY-----\n# after: decrypt then store\nopenssl pkcs8 -in enc.pem -passin file:pass.txt -nocrypt -out plain.pem","handlingStrategy":"validation","validationCode":"block, _ := pem.Decode([]byte(pk))\nif block != nil && block.Type == \"PRIVATE KEY\" {\n    if _, err := x509.ParsePKCS8PrivateKey(block.Bytes); err != nil {\n        return fmt.Errorf(\"PKCS#8 body unparseable; key corrupt or encrypted\")\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Decrypt PBES2 keys before storing them as the service account key","Validate with openssl pkcs8 -nocrypt during deployment","Avoid byte-level edits of key material"],"tags":["vertex","pkcs8","crypto","private-key"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}