{"record":{"id":"df4843e0594a61d5","repo":"HMCL-dev/HMCL","slug":"failed-to-protect-json-payload","errorCode":null,"errorMessage":"Failed to protect JSON payload","messagePattern":"Failed to protect JSON payload","errorType":"validation","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/setting/ProtectedPayload.java","lineNumber":130,"sourceCode":"                    (byte) 0x6e, (byte) 0xb0, (byte) 0xa9, (byte) 0x4d,\n                    (byte) 0xeb, (byte) 0x93, (byte) 0x99, (byte) 0x6f,\n                    (byte) 0x84, (byte) 0x07, (byte) 0x5a, (byte) 0x9e,\n                    (byte) 0xbd, (byte) 0xc8, (byte) 0xd1, (byte) 0xeb\n            }, \"ChaCha20\");\n\n            /// Encrypts the plain payload bytes.\n            ///\n            /// @param payload the plain payload bytes\n            /// @param nonce the encryption nonce\n            /// @return the encrypted payload bytes with the authentication tag appended\n            /// @throws JsonParseException if the cipher is not available\n            private byte[] encryptPayload(byte[] payload, byte[] nonce) {\n                try {\n                    Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);\n                    cipher.init(Cipher.ENCRYPT_MODE, PROTECTION_KEY, new IvParameterSpec(nonce));\n                    return cipher.doFinal(payload);\n                } catch (GeneralSecurityException e) {\n                    throw new JsonParseException(\"Failed to protect JSON payload\", e);\n                }\n            }\n\n            /// Decrypts the protected payload bytes.\n            ///\n            /// @param payload the encrypted payload bytes with the authentication tag appended\n            /// @param nonce the encryption nonce\n            /// @return the plain payload bytes\n            /// @throws JsonParseException if the payload cannot be decrypted\n            private byte[] decryptPayload(byte[] payload, byte[] nonce) {\n                try {\n                    Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);\n                    cipher.init(Cipher.DECRYPT_MODE, PROTECTION_KEY, new IvParameterSpec(nonce));\n                    return cipher.doFinal(payload);\n                } catch (GeneralSecurityException e) {\n                    throw new JsonParseException(\"Failed to reveal protected JSON payload\", e);\n                }\n            }","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/setting/ProtectedPayload.java#L112-L148","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\njava -jar HMCL.jar  // on Java 8\n// after\njava -jar HMCL.jar  // on Java 17 (cipher available)\n// or register a provider: Security.addProvider(new BouncyCastleProvider());","handlingStrategy":"try-catch","validationCode":"try {\n    javax.crypto.Cipher.getInstance(\"ChaCha20-Poly1305\");\n} catch (javax.crypto.NoSuchPaddingException | java.security.NoSuchAlgorithmException e) {\n    throw new IllegalStateException(\"ChaCha20-Poly1305 unsupported on this JVM\", e);\n}","typeGuard":"static boolean chaChaSupported() {\n    try {\n        javax.crypto.Cipher.getInstance(\"ChaCha20-Poly1305\");\n        return true;\n    } catch (java.security.GeneralSecurityException e) {\n        return false;\n    }\n}","tryCatchPattern":"try {\n    ProtectedPayload.read(envelope, JsonElement.class);\n} catch (com.google.gson.JsonParseException e) {\n    if (e.getCause() instanceof java.security.GeneralSecurityException gse) {\n        logger.warning(\"Cipher unavailable/failed: \" + gse, gse);\n    }\n}","preventionTips":["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."],"tags":["crypto","jce","cipher"],"backgroundTag":"crypto-provider-missing","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}