SonarSource/sonarqube · error · IllegalArgumentException

Error while loading PKCS8 private key, please check the form

Error message

Error while loading PKCS8 private key, please check the format

What it means

SamlPrivateKeyConverter.toPrivateKey() decodes a Base64 string as PKCS#8 DER and generates an RSA PrivateKey via KeyFactory. If KeyFactory.getInstance("RSA") or generatePrivate throws NoSuchAlgorithmException or InvalidKeySpecException, the key bytes are not a valid PKCS#8-encoded RSA private key and it throws IllegalArgumentException with this message.

Source

Thrown at server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlPrivateKeyConverter.java:42

import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import org.sonar.api.server.ServerSide;

@ServerSide
class SamlPrivateKeyConverter {

  PrivateKey toPrivateKey(String privateKeyString) {
    String cleanedPrivateKeyString = sanitizePrivateKeyString(privateKeyString);

    byte[] decoded = Base64.getDecoder().decode(cleanedPrivateKeyString);
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded);
    try {
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      return keyFactory.generatePrivate(keySpec);
    } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
      throw new IllegalArgumentException("Error while loading PKCS8 private key, please check the format", e);
    }
  }

  private static String sanitizePrivateKeyString(String privateKeyString) {
    return privateKeyString
      .replace("-----BEGIN PRIVATE KEY-----", "")
      .replace("-----END PRIVATE KEY-----", "")
      .replaceAll("\\s+", "");
  }
}

View on GitHub (pinned to 184c821202)

Solutions

  1. Convert the key to PKCS#8: openssl pkcs8 -topk8 -nocrypt -in key.pem -out key-pkcs8.pem, then paste only the Base64 body into sonar.auth.saml.privateKey
  2. If the key is PKCS#1, the header 'BEGIN RSA PRIVATE KEY' is the tell — re-export as 'BEGIN PRIVATE KEY' (PKCS#8)
  3. Confirm the header/footer lines are removed; the converter strips exactly '-----BEGIN PRIVATE KEY-----'/'-----END PRIVATE KEY-----'

Example fix

// before (PKCS#1 key, rejected)
// -----BEGIN RSA PRIVATE KEY-----
// MIIEpAIBAAKCAQEA...
// after: convert first
// $ openssl pkcs8 -topk8 -nocrypt -in key.pem -out key-pkcs8.pem
String pkcs8Key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC...";
Defensive patterns

Strategy: validation

Validate before calling

String cleaned = key.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replaceAll("\\s", "");
if (cleaned.contains("RSA PRIVATE")) throw new IllegalStateException("PKCS#1 key detected; convert with openssl pkcs8 -topk8 -nocrypt");
byte[] decoded = Base64.getDecoder().decode(cleaned);
new PKCS8EncodedKeySpec(decoded); // throws InvalidKeySpecException later at KeyFactory if wrong

Type guard

static boolean isPkcs8Header(String pem) {
  return pem != null && pem.contains("-----BEGIN PRIVATE KEY-----");
}

Try / catch

try {
  PrivateKey key = SamlPrivateKeyConverter.toPrivateKey(cfg.privateKey());
} catch (IllegalArgumentException e) {
  log.error("SAML private key must be PKCS#8, unencrypted", e);
  throw new ConfigurationException("Re-export key: openssl pkcs8 -topk8 -nocrypt -in key.pem");
}

Prevention

When it happens

Trigger: Calling toPrivateKey() (or configuring sonar.auth.saml.privateKey) with a key that is PKCS#1 ('BEGIN RSA PRIVATE KEY'), OpenSSL 'BEGIN PRIVATE KEY' with an EC/other algorithm, encrypted ('BEGIN ENCRYPTED PRIVATE KEY'), truncated, or otherwise not PKCS#8 RSA DER after the PEM header is stripped.

Common situations: Admins exporting keys with 'openssl genrsa' (PKCS#1) instead of 'openssl genpkey' (PKCS#8), pasting the IdP certificate instead of the SP key, or including header/footer lines that break Base64 decoding.

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 SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/a1b91140c8e52822. Report an issue: GitHub.