juicedata/juicefs · error
cannot decode encrypted private keys: %v
Error message
cannot decode encrypted private keys: %v
What it means
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'.
Source
Thrown at pkg/object/encrypt.go:99
}
} else {
var err error
// nolint:staticcheck
buf, err = x509.DecryptPEMBlock(block, passphrase)
if err != nil {
if err == x509.IncorrectPasswordError {
return nil, err
}
key, err := pkcs8.ParsePKCS8PrivateKey(block.Bytes, passphrase)
if err == nil {
return key, nil
}
key, err = pkcs8.ParsePKCS8PrivateKey(block.Bytes)
if err == nil {
return key, nil
}
if !strings.Contains(err.Error(), "ParsePKCS1PrivateKey") {
return nil, fmt.Errorf("cannot decode encrypted private keys: %v", err)
}
buf = block.Bytes
}
}
rsaKey, err := x509.ParsePKCS1PrivateKey(buf)
if err == nil {
return rsaKey, nil
}
key, err := pkcs8.ParsePKCS8PrivateKey(buf)
if err != nil {
return nil, err
}
return key, nil
}
func ParseRsaPrivateKeyFromPath(path, passphrase string) (any, error) {
b, err := os.ReadFile(path)View on GitHub (pinned to c9a67b23e8)
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)
Example fix
// before: feeding a passphrase-protected PKCS1 key
key, err := ParseRsaPrivateKeyFromPath("/keys/priv.pem", "secret") // cannot decode encrypted private keys
// after: strip legacy encryption first
// openssl rsa -in /keys/priv.pem -passin pass:secret -out /keys/priv8.pem
// openssl pkcs8 -topk8 -nocrypt -in /keys/priv8.pem -out /keys/final.pem
key, err := ParseRsaPrivateKeyFromPath("/keys/final.pem", "") Defensive patterns
Strategy: validation
Validate before calling
func keyLooksSupported(pemBytes []byte) error {
block, _ := pem.Decode(pemBytes)
if block == nil { return errors.New("not a PEM file") }
if strings.Contains(block.Type, "ENCRYPTED") || strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED") {
// legacy encrypted PEM / PKCS8-encrypted; passphrase required
_ = block
}
if _, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil { return nil }
if _, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil { return nil }
return errors.New("key is not PKCS1/PKCS8; re-encode with openssl pkcs8 -topk8")
} Type guard
func isPemBlock(b []byte) bool { block, _ := pem.Decode(b); return block != nil } Try / catch
key, err := ParsePrivateKeyFromPem(pemBytes, pass)
if errors.Is(err, ErrKeyNeedPasswd) { /* prompt for passphrase */ }
else if err != nil { /* re-encode the key with openssl and retry */ } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- failed to parse PEM block containing the key
- parse private key: %s
- new sm4 GCM: %s
- new cipher: %s
- new GCM: %s
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/6b4aa60f4c5efdd9.
Report an issue: GitHub.