router-for-me/CLIProxyAPI · error
private_key is not an RSA key
Error message
private_key is not an RSA key
What it means
From ensureRSAPrivateKey when a 'PRIVATE KEY' (PKCS#8) block parses successfully but the resulting key is not an *rsa.PrivateKey (keyutil.go:102-106). Vertex signing requires RSA; an ECDSA or Ed25519 key inside a PKCS#8 wrapper triggers this error.
Source
Thrown at internal/auth/vertex/keyutil.go:105
if block == nil {
return nil, fmt.Errorf("pem block is nil")
}
if block.Type == "RSA PRIVATE KEY" {
if _, err := x509.ParsePKCS1PrivateKey(block.Bytes); err != nil {
return nil, fmt.Errorf("private_key invalid rsa: %w", err)
}
return block, nil
}
if block.Type == "PRIVATE KEY" {
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("private_key invalid pkcs8: %w", err)
}
rsaKey, ok := key.(*rsa.PrivateKey)
if !ok {
return nil, fmt.Errorf("private_key is not an RSA key")
}
der := x509.MarshalPKCS1PrivateKey(rsaKey)
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: der}, nil
}
// Attempt auto-detection: try PKCS#1 first, then PKCS#8.
if rsaKey, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil {
der := x509.MarshalPKCS1PrivateKey(rsaKey)
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: der}, nil
}
if key, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil {
if rsaKey, ok := key.(*rsa.PrivateKey); ok {
der := x509.MarshalPKCS1PrivateKey(rsaKey)
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: der}, nil
}
}
return nil, fmt.Errorf("private_key uses unsupported format")
}View on GitHub (pinned to 78f0c4079e)
Solutions
- Regenerate the key as RSA of at least 2048 bits: openssl genrsa -out key.pem 2048, then rebuild the service account JSON
- Or use an official GCP-issued service account key, which is always RSA
- Verify the algorithm: openssl pkey -in key.pem -noout -text | head -1 (should say RSA)
Example fix
# before openssl ecparam -name prime256v1 -genkey -out key.pem # after openssl genrsa -out key.pem 2048
Defensive patterns
Strategy: type-guard
Validate before calling
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err == nil && !isRSA(key) {
return fmt.Errorf("key algorithm is %T; RSA required", key)
} Type guard
func isRSAKey(any) bool
// Go:
func isRSAKey(k any) bool {
_, ok := k.(*rsa.PrivateKey)
return ok
} Prevention
- Generate signing keys with openssl genrsa (>=2048 bits)
- Prefer GCP-issued service account keys, which are always RSA
- Assert algorithm early in key onboarding pipelines
When it happens
Trigger: User configures an EC (prime256v1) or Ed25519 service-account-style key as the Vertex credential; key generated with openssl ecparam or genkey -algorithm ed25519 instead of RSA; GCP always issues RSA, so this usually means a custom/homemade key.
Common situations: Organizations minting their own keys for private Vertex-compatible endpoints; converting existing EC TLS keys for signing experiments; misunderstanding that the field must be RSA.
Related errors
- private_key invalid rsa: %w
- private_key invalid pkcs8: %w
- failed to generate code verifier: %w
- failed to generate random bytes: %w
- failed to generate code verifier: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/bc996cdac2996665.
Report an issue: GitHub.