{"record":{"id":"6b4aa60f4c5efdd9","repo":"juicedata/juicefs","slug":"cannot-decode-encrypted-private-keys-v","errorCode":null,"errorMessage":"cannot decode encrypted private keys: %v","messagePattern":"cannot decode encrypted private keys: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/object/encrypt.go","lineNumber":99,"sourceCode":"\t\t}\n\t} else {\n\t\tvar err error\n\t\t// nolint:staticcheck\n\t\tbuf, err = x509.DecryptPEMBlock(block, passphrase)\n\t\tif err != nil {\n\t\t\tif err == x509.IncorrectPasswordError {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tkey, err := pkcs8.ParsePKCS8PrivateKey(block.Bytes, passphrase)\n\t\t\tif err == nil {\n\t\t\t\treturn key, nil\n\t\t\t}\n\t\t\tkey, err = pkcs8.ParsePKCS8PrivateKey(block.Bytes)\n\t\t\tif err == nil {\n\t\t\t\treturn key, nil\n\t\t\t}\n\t\t\tif !strings.Contains(err.Error(), \"ParsePKCS1PrivateKey\") {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot decode encrypted private keys: %v\", err)\n\t\t\t}\n\t\t\tbuf = block.Bytes\n\t\t}\n\t}\n\n\trsaKey, err := x509.ParsePKCS1PrivateKey(buf)\n\tif err == nil {\n\t\treturn rsaKey, nil\n\t}\n\tkey, err := pkcs8.ParsePKCS8PrivateKey(buf)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn key, nil\n}\n\nfunc ParseRsaPrivateKeyFromPath(path, passphrase string) (any, error) {\n\tb, err := os.ReadFile(path)","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/object/encrypt.go#L81-L117","documentation":"ParsePrivateKeyFromPem parses a PEM-encoded private key, optionally decrypting it with a passphrase. When a passphrase is supplied but the block cannot be decrypted as a legacy encrypted PEM or as a PKCS8 (encrypted or plain) key, and the failure is not the recoverable 'ParsePKCS1PrivateKey' fallback case, it gives up with 'cannot decode encrypted private keys'.","triggerScenarios":"Calling ParsePrivateKeyFromPem (or ParseRsaPrivateKeyFromPath, or format/mount with encrypt-keys and a passphrase) with a passphrase on a PEM key that is neither legacy x509 encrypted PEM nor PKCS8-formatted; the underlying pkcs8 parser rejects the DER bytes.","commonSituations":"Key file generated with an unsupported algorithm (e.g. Ed25519 via an old pkcs8 lib) or non-PKCS8 container (raw PKCS1 'RSA PRIVATE KEY' with a passphrase); wrong or corrupted key file; key re-encoded by another tool into an unsupported format.","solutions":["Convert the key to an unencrypted PKCS8 or PKCS1 PEM: openssl pkcs8 -topk8 -nocrypt -in key.pem -out key8.pem (or openssl rsa -in key.pem -out rsakey.pem)","Verify the passphrase is correct; if wrong you would instead get IncorrectPasswordError, so if you see this the format itself is unsupported","Regenerate the key with openssl genrsa and supply the new file via the encrypt keys option","Check that the key file was not truncated or modified (compare sha256 with the original)"],"exampleFix":"// before: feeding a passphrase-protected PKCS1 key\nkey, err := ParseRsaPrivateKeyFromPath(\"/keys/priv.pem\", \"secret\") // cannot decode encrypted private keys\n// after: strip legacy encryption first\n// openssl rsa -in /keys/priv.pem -passin pass:secret -out /keys/priv8.pem\n// openssl pkcs8 -topk8 -nocrypt -in /keys/priv8.pem -out /keys/final.pem\nkey, err := ParseRsaPrivateKeyFromPath(\"/keys/final.pem\", \"\")","handlingStrategy":"validation","validationCode":"func keyLooksSupported(pemBytes []byte) error {\n\tblock, _ := pem.Decode(pemBytes)\n\tif block == nil { return errors.New(\"not a PEM file\") }\n\tif strings.Contains(block.Type, \"ENCRYPTED\") || strings.Contains(block.Headers[\"Proc-Type\"], \"ENCRYPTED\") {\n\t\t// legacy encrypted PEM / PKCS8-encrypted; passphrase required\n\t\t_ = block\n\t}\n\tif _, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil { return nil }\n\tif _, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil { return nil }\n\treturn errors.New(\"key is not PKCS1/PKCS8; re-encode with openssl pkcs8 -topk8\")\n}","typeGuard":"func isPemBlock(b []byte) bool { block, _ := pem.Decode(b); return block != nil }","tryCatchPattern":"key, err := ParsePrivateKeyFromPem(pemBytes, pass)\nif errors.Is(err, ErrKeyNeedPasswd) { /* prompt for passphrase */ }\nelse if err != nil { /* re-encode the key with openssl and retry */ }","preventionTips":["Store keys as unencrypted PKCS8 or PKCS1 PEM; keep the passphrase protection at the file/vault level","Test-parse the key file at deploy time with openssl pkey -in key.pem -noout","Never hand-edit or re-save key files with editors that may alter line endings","Pin the key-generation command (openssl genrsa / pkcs8) in provisioning scripts"],"tags":["crypto","pem","pkcs8","key-parsing"],"backgroundTag":"invalid-argument-format","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}