{"record":{"id":"03418a2500cbc05f","repo":"router-for-me/CLIProxyAPI","slug":"private-key-invalid-rsa-w","errorCode":null,"errorMessage":"private_key invalid rsa: %w","messagePattern":"private_key invalid rsa: %w","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/auth/vertex/keyutil.go","lineNumber":93,"sourceCode":"\tif block == nil {\n\t\treturn \"\", fmt.Errorf(\"private_key pem decode failed\")\n\t}\n\n\trsaBlock, err := ensureRSAPrivateKey(block)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\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.","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/auth/vertex/keyutil.go#L75-L111","documentation":"From ensureRSAPrivateKey when the PEM block is typed 'RSA PRIVATE KEY' (PKCS#1) but x509.ParsePKCS1PrivateKey rejects its DER bytes (keyutil.go:90-93). The PEM wrapper is well-formed, yet the underlying ASN.1 payload is not a valid PKCS#1 RSA private key.","triggerScenarios":"A PKCS#8 or EC key mislabeled with the 'RSA PRIVATE KEY' PEM type; DER bytes corrupted or truncated; a key produced by an exotic tool emitting non-standard PKCS#1 encoding.","commonSituations":"Users manually retagging PEM headers to 'fix' parser complaints; secrets-manager round trips that corrupt bytes; converting EC keys while keeping the RSA label.","solutions":["Identify the true key format: openssl pkey -in key.pem -noout && openssl rsa -in key.pem -noout -check","If it is actually PKCS#8, relabel the header to '-----BEGIN PRIVATE KEY-----' (or re-export from GCP, which always yields a parseable file)","Regenerate the service account key in GCP as the guaranteed-clean fix"],"exampleFix":"# before (PKCS#8 bytes under an RSA PKCS#1 label)\n-----BEGIN RSA PRIVATE KEY-----\nMIIEvQ...pkcs8-bytes...\n-----END RSA PRIVATE KEY-----\n# after\n-----BEGIN PRIVATE KEY-----\nMIIEvQ...pkcs8-bytes...\n-----END PRIVATE KEY-----","handlingStrategy":"validation","validationCode":"block, _ := pem.Decode([]byte(pk))\nif block != nil && block.Type == \"RSA PRIVATE KEY\" {\n    if _, err := x509.ParsePKCS1PrivateKey(block.Bytes); err != nil {\n        return fmt.Errorf(\"PKCS#1-labeled key fails to parse; likely mislabeled PKCS#8\")\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not retag PEM headers to silence parser errors","Let GCP-generated files remain untouched","Use openssl to convert formats properly instead of editing text"],"tags":["vertex","rsa","pkcs1","crypto"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}