ipfs/kubo · error
expected PRIVATE KEY type in PEM block but got: %s
Error message
expected PRIVATE KEY type in PEM block but got: %s
What it means
`ipfs key import --format=pem-pkcs8-cleartext` requires the PEM file to contain a block of type "PRIVATE KEY" (PKCS8). The file decoded as PEM, but its block header was a different type (e.g. "ENCRYPTED PRIVATE KEY", "RSA PRIVATE KEY", "PUBLIC KEY"), so kubo refuses to parse it as an unencrypted PKCS8 key.
Source
Thrown at core/commands/keystore.go:495
}
defer file.Close()
data, err := io.ReadAll(file)
if err != nil {
return err
}
importFormat, _ := req.Options[keyFormatOptionName].(string)
var sk crypto.PrivKey
switch importFormat {
case keyFormatPemCleartextOption:
pemBlock, rest := pem.Decode(data)
if pemBlock == nil {
return fmt.Errorf("PEM block not found in input data:\n%s", rest)
}
if pemBlock.Type != "PRIVATE KEY" {
return fmt.Errorf("expected PRIVATE KEY type in PEM block but got: %s", pemBlock.Type)
}
stdKey, err := parsePKCS8PrivateKey(pemBlock.Bytes)
if err != nil {
return fmt.Errorf("parsing PKCS8 format: %w", err)
}
// In case ed25519.PrivateKey is returned we need the pointer for
// conversion to libp2p (see export command for more details).
if ed25519KeyPointer, ok := stdKey.(ed25519.PrivateKey); ok {
stdKey = &ed25519KeyPointer
}
sk, _, err = crypto.KeyPairFromStdKey(stdKey)
if err != nil {
return fmt.Errorf("converting std Go key to libp2p key: %w", err)
}
case keyFormatLibp2pCleartextOption:View on GitHub (pinned to 329838acdf)
Solutions
- Regenerate the key as unencrypted PKCS8: `openssl genpkey -algorithm ED25519 -out key.pem` or `openssl pkcs8 -topk8 -nocrypt -in old.pem -out key.pem`
- Check the PEM header in the file; it must read `-----BEGIN PRIVATE KEY-----`
- If the file is a PUBLIC KEY, locate and use the corresponding private key file
Example fix
// before (PKCS1, not PKCS8) $ openssl genrsa -traditional -out key.pem 2048 -----BEGIN RSA PRIVATE KEY----- // after (PKCS8) $ openssl pkcs8 -topk8 -nocrypt -in key.pem -out key8.pem -----BEGIN PRIVATE KEY-----
Defensive patterns
Strategy: validation
Validate before calling
data, _ := os.ReadFile("key.pem")
block, _ := pem.Decode(data)
if block == nil || block.Type != "PRIVATE KEY" {
return fmt.Errorf("key.pem must be an unencrypted PKCS8 'PRIVATE KEY' PEM block, got type %q", func() string { if block != nil { return block.Type }; return "" }())
} Type guard
func isPKCS8Pem(data []byte) bool {
b, _ := pem.Decode(data)
return b != nil && b.Type == "PRIVATE KEY"
} Prevention
- Generate keys with `openssl genpkey -algorithm ED25519` which emits PKCS8 by default
- Never use `-aes256`/encryption when exporting for ipfs key import
- Check the PEM header line begins with `-----BEGIN PRIVATE KEY-----` before importing
When it happens
Trigger: Running `ipfs key import name -f pem-pkcs8-cleartext key.pem` where key.pem is PEM but not a PKCS8 "PRIVATE KEY" block: an openssl legacy `RSA PRIVATE KEY` (PKCS1) file, an `ENCRYPTED PRIVATE KEY` produced without `-nocrypt`, or a `PUBLIC KEY` file instead of the private one.
Common situations: Developer generated a key with `openssl genpkey -algorithm RSA -aes256` (encrypted output), exported from a tool using PKCS1 (`openssl rsa -traditional`), or grabbed the wrong (public) key file.
Related errors
- parsing PKCS8 format: %w
- unexpected PEM block for format=%s: try again with format=%s
- encoding PEM block: %w
- PEM block not found in input data: %s
- converting std Go key to libp2p key: %w
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/0fb85d4a7f469f54.
Report an issue: GitHub.