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

  1. 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)
  2. Verify the passphrase is correct; if wrong you would instead get IncorrectPasswordError, so if you see this the format itself is unsupported
  3. Regenerate the key with openssl genrsa and supply the new file via the encrypt keys option
  4. 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

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


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/6b4aa60f4c5efdd9. Report an issue: GitHub.