HMCL-dev/HMCL · error · JsonParseException
Failed to protect JSON payload
Error message
Failed to protect JSON payload
What it means
OBFUSCATED_V1.encryptPayload wraps any GeneralSecurityException from the ChaCha20-Poly1305 Cipher (getInstance/init/doFinal) into JsonParseException with this message. It means the JCE provider could not supply or execute the cipher, so HMCL cannot protect the payload before writing the envelope.
Solutions
- Run on a JDK/JRE 11+ that ships the ChaCha20-Poly1305 cipher (JDK 11+ via JEP 323/329).
- Check java.security file and installed security providers; ensure a provider offering ChaCha20-Poly1305 is registered.
- Print the cause with e.getCause() to see whether it is NoSuchAlgorithmException, InvalidKeyException, etc., and fix that specific provider/key issue.
Example fix
// before java -jar HMCL.jar // on Java 8 // after java -jar HMCL.jar // on Java 17 (cipher available) // or register a provider: Security.addProvider(new BouncyCastleProvider());
Defensive patterns
Strategy: try-catch
Validate before calling
try {
javax.crypto.Cipher.getInstance("ChaCha20-Poly1305");
} catch (javax.crypto.NoSuchPaddingException | java.security.NoSuchAlgorithmException e) {
throw new IllegalStateException("ChaCha20-Poly1305 unsupported on this JVM", e);
} Type guard
static boolean chaChaSupported() {
try {
javax.crypto.Cipher.getInstance("ChaCha20-Poly1305");
return true;
} catch (java.security.GeneralSecurityException e) {
return false;
}
} Try / catch
try {
ProtectedPayload.read(envelope, JsonElement.class);
} catch (com.google.gson.JsonParseException e) {
if (e.getCause() instanceof java.security.GeneralSecurityException gse) {
logger.warning("Cipher unavailable/failed: " + gse, gse);
}
} Prevention
- Run HMCL on JDK 11+ where ChaCha20-Poly1305 is bundled.
- Inspect e.getCause() to distinguish NoSuchAlgorithmException vs InvalidKeyException.
- Do not strip security providers from custom JRE builds (jlink).
- Test cipher availability early at startup if embedding the code.
When it happens
Trigger: Calling writePayload/envelope serialization on a JVM whose JDK does not support 'ChaCha20-Poly1305' (pre-JDK 11 or missing provider), or a provider that rejects the 32-byte ChaCha20 SecretKeySpec / IvParameterSpec nonce.
Common situations: Running HMCL on an old JRE (Java 8) or a stripped-down/custom runtime without the ChaCha20 cipher; security policy restricting crypto providers; broken java.security configuration.
Related errors
- Failed to reveal protected JSON payload
- Protected payload nonce has invalid length
- Missing protected payload member: nonce
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/df4843e0594a61d5.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/setting/ProtectedPayload.java:130
(byte) 0x6e, (byte) 0xb0, (byte) 0xa9, (byte) 0x4d,
(byte) 0xeb, (byte) 0x93, (byte) 0x99, (byte) 0x6f,
(byte) 0x84, (byte) 0x07, (byte) 0x5a, (byte) 0x9e,
(byte) 0xbd, (byte) 0xc8, (byte) 0xd1, (byte) 0xeb
}, "ChaCha20");
/// Encrypts the plain payload bytes.
///
/// @param payload the plain payload bytes
/// @param nonce the encryption nonce
/// @return the encrypted payload bytes with the authentication tag appended
/// @throws JsonParseException if the cipher is not available
private byte[] encryptPayload(byte[] payload, byte[] nonce) {
try {
Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, PROTECTION_KEY, new IvParameterSpec(nonce));
return cipher.doFinal(payload);
} catch (GeneralSecurityException e) {
throw new JsonParseException("Failed to protect JSON payload", e);
}
}
/// Decrypts the protected payload bytes.
///
/// @param payload the encrypted payload bytes with the authentication tag appended
/// @param nonce the encryption nonce
/// @return the plain payload bytes
/// @throws JsonParseException if the payload cannot be decrypted
private byte[] decryptPayload(byte[] payload, byte[] nonce) {
try {
Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, PROTECTION_KEY, new IvParameterSpec(nonce));
return cipher.doFinal(payload);
} catch (GeneralSecurityException e) {
throw new JsonParseException("Failed to reveal protected JSON payload", e);
}
}View on GitHub (pinned to 24702dc5a0)