spring-projects/spring-boot · error · IllegalArgumentException

Error decrypting private key

Error message

Error decrypting private key

What it means

Pkcs8PrivateKeyDecryptor.decrypt handles BEGIN ENCRYPTED PRIVATE KEY blocks. It builds EncryptedPrivateKeyInfo from the bytes, derives a PBE SecretKey from the supplied password, obtains a Cipher, and returns keyInfo.getKeySpec(cipher). The catch (IOException | GeneralSecurityException) wraps any failure as IllegalArgumentException. The most common cause is a wrong password; it can also be an unsupported encryption algorithm.

Solutions

  1. Supply the correct password (the parse(text, password) overload).
  2. Verify the password decrypts the key out of band: `openssl pkey -in key.enc -passin pass:<pw>`.
  3. Re-encrypt with a standard algorithm: `openssl pkcs8 -topk8 -in key.pem -out key.enc`.
  4. On JDK 8u160 or older, install the JCE Unlimited Strength policy files; current JDKs ship with it by default.
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm the password decrypts the key out of band
Process p = new ProcessBuilder("openssl", "pkey", "-in", keyPath.toString(),
        "-passin", "pass:" + password, "-noout").redirectErrorStream(true).start();
if (p.waitFor() != 0) {
    throw new IllegalArgumentException("Wrong password or unsupported encryption for " + keyPath);
}

Try / catch

try {
    PemPrivateKeyParser.parse(text, password);
} catch (IllegalStateException ex) {
    Throwable c = ex.getCause();
    if (c instanceof IllegalArgumentException
            && "Error decrypting private key".equals(c.getMessage())) {
        // prompt the user for the correct password and retry once
    }
    throw ex;
}

Prevention

When it happens

Trigger: createKeySpecForPkcs8Encrypted calls Pkcs8PrivateKeyDecryptor.decrypt(bytes, password). Failure occurs when: the password is wrong (Cipher.init or getKeySpec fails); the PBES2 algorithm in the key is not offered by the configured JCE provider; the encrypted key bytes are malformed; or password is null on an encrypted key (Assert.state at line 452 throws IllegalArgumentException before the try, with a different message).

Common situations: Wrong passphrase supplied at build time; key encrypted with an algorithm (e.g. PBES2 with AES-256-GCM) the JVM cannot service on a very old JDK without unlimited-crypto policy; corrupted encrypted key; password not propagated through the buildpack configuration.

Related errors


AI-assisted analysis of spring-projects/spring-boot@270dfe353f (2026-08-11). Data as JSON: /api/errors/9cf446862fbde168. Report an issue: GitHub.

Appendix: source

Thrown at buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/PemPrivateKeyParser.java:464

	 */
	static class Pkcs8PrivateKeyDecryptor {

		public static final String PBES2_ALGORITHM = "PBES2";

		static PKCS8EncodedKeySpec decrypt(byte[] bytes, @Nullable String password) {
			Assert.state(password != null, "Password is required for an encrypted private key");
			try {
				EncryptedPrivateKeyInfo keyInfo = new EncryptedPrivateKeyInfo(bytes);
				AlgorithmParameters algorithmParameters = keyInfo.getAlgParameters();
				String encryptionAlgorithm = getEncryptionAlgorithm(algorithmParameters, keyInfo.getAlgName());
				SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(encryptionAlgorithm);
				SecretKey key = keyFactory.generateSecret(new PBEKeySpec(password.toCharArray()));
				Cipher cipher = Cipher.getInstance(encryptionAlgorithm);
				cipher.init(Cipher.DECRYPT_MODE, key, algorithmParameters);
				return keyInfo.getKeySpec(cipher);
			}
			catch (IOException | GeneralSecurityException ex) {
				throw new IllegalArgumentException("Error decrypting private key", ex);
			}
		}

		private static String getEncryptionAlgorithm(@Nullable AlgorithmParameters algParameters, String algName) {
			if (algParameters != null && PBES2_ALGORITHM.equals(algName)) {
				return algParameters.toString();
			}
			return algName;
		}

	}

	/**
	 * ANS.1 encoded object identifier.
	 */
	static final class EncodedOid {

		static final EncodedOid OID_1_2_840_10040_4_1 = EncodedOid.of("2a8648ce380401");

View on GitHub (pinned to 270dfe353f)