MyCATApache/Mycat-Server · error · IllegalArgumentException

Failed to get public key

Error message

Failed to get public key

What it means

DecryptUtil.getPublicKey() decodes a Base64 X.509-encoded RSA public key and asks the JCE KeyFactory to reconstruct it. If Base64 decoding or KeyFactory.generatePublic() fails for any reason, it rethrows as IllegalArgumentException('Failed to get public key') with the original cause attached.

Solutions

  1. Convert the key to X.509 SubjectPublicKeyInfo format: openssl rsa -pubin -in key.pub -pubout -outform DER | base64
  2. Confirm the input is the public key (not private) and contains only valid Base64 characters with no headers/newlines
  3. Inspect the wrapped cause (e.getCause()) — InvalidKeySpecException means wrong format, IOException/Base64 means corrupt input
  4. Regenerate a fresh RSA keypair with Mycat's tooling if the source of the key is unknown

Example fix

// before
openssl rsa -in private.pem -pubout -out pub.pem // PKCS#1 or with PEM headers pasted directly
// after
openssl rsa -in private.pem -pubout -outform DER | base64 -w0 // then pass this Base64 string
Defensive patterns

Strategy: try-catch

Validate before calling

static boolean looksLikeX509Base64(String key){
    if(key==null) return false;
    String s = key.replaceAll("\\s","");
    return s.length()%4==0 && s.matches("[A-Za-z0-9+/]+=*") && s.length() > 100;
}

Try / catch

try { PublicKey pk = DecryptUtil.getPublicKey(b64); }
catch (IllegalArgumentException e) { throw new IllegalStateException("public key must be Base64 X.509 SubjectPublicKeyInfo; cause: " + e.getCause(), e); }

Prevention

When it happens

Trigger: Passing a string that is not valid Base64 or not an X.509 SubjectPublicKeyInfo blob to getPublicKey(String); supplying an RSA public key exported in a different format (e.g. PKCS#1 'BEGIN RSA PUBLIC KEY' or OpenSSH format).

Common situations: Generating a keypair with openssl and pasting the public key directly without converting to X.509/SubjectPublicKeyInfo; whitespace or newlines corrupting the Base64; attempting to decrypt with a public key that was actually the private key field.

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 MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11). Data as JSON: /api/errors/351cf79d7676c51b. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/io/mycat/util/DecryptUtil.java:142

		PublicKey publicKey = getPublicKey(publicKeyText);

		return decrypt(publicKey, cipherText);
	}

	public static PublicKey getPublicKey(String publicKeyText) {
		if (publicKeyText == null || publicKeyText.length() == 0) {
			publicKeyText = DecryptUtil.DEFAULT_PUBLIC_KEY_STRING;
		}

		try {
			byte[] publicKeyBytes = Base64.base64ToByteArray(publicKeyText);
			X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(
					publicKeyBytes);

			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			return keyFactory.generatePublic(x509KeySpec);
		} catch (Exception e) {
			throw new IllegalArgumentException("Failed to get public key", e);
		}
	}


	public static String decrypt(PublicKey publicKey, String cipherText)
			throws Exception {
		Cipher cipher = Cipher.getInstance("RSA");
		try {
			cipher.init(Cipher.DECRYPT_MODE, publicKey);
		} catch (InvalidKeyException e) {
            // 因为 IBM JDK 不支持私钥加密, 公钥解密, 所以要反转公私钥
            // 也就是说对于解密, 可以通过公钥的参数伪造一个私钥对象欺骗 IBM JDK
            RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
            RSAPrivateKeySpec spec = new RSAPrivateKeySpec(rsaPublicKey.getModulus(), rsaPublicKey.getPublicExponent());
            Key fakePrivateKey = KeyFactory.getInstance("RSA").generatePrivate(spec);
            cipher = Cipher.getInstance("RSA"); //It is a stateful object. so we need to get new one.
            cipher.init(Cipher.DECRYPT_MODE, fakePrivateKey);
		}

View on GitHub (pinned to 65f8d8beb7)