{"record":{"id":"dcf06041db1931f6","repo":"alibaba/canal","slug":"can-t-encrypt-password-that-will-be-sent-to-mysql-dcf060","errorCode":null,"errorMessage":"can't encrypt password that will be sent to MySQL server.","messagePattern":"can't encrypt password that will be sent to MySQL server\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"critical","filePath":"driver/src/main/java/com/alibaba/otter/canal/parse/driver/mysql/packets/client/ClientAuthenticationSHA2Packet.java","lineNumber":48,"sourceCode":"\n        // 2. write max_packet_size\n        ByteHelper.writeUnsignedIntLittleEndian(MSC.MAX_PACKET_LENGTH, out);\n        // 3. write charset_number\n        out.write(getCharsetNumber());\n        // 4. write (filler) always 0x00...\n        out.write(new byte[23]);\n        // 5. write (Null-Terminated String) user\n        ByteHelper.writeNullTerminatedString(getUsername(), out);\n        // 6. write (Length Coded Binary) scramble_buff (1 + x bytes)\n        if (StringUtils.isEmpty(getPassword())) {\n            out.write(0x00);\n        } else {\n            try {\n                byte[] encryptedPassword = MySQLPasswordEncrypter.scrambleCachingSha2(getPassword().getBytes(),\n                    getScrumbleBuff());\n                ByteHelper.writeBinaryCodedLengthBytes(encryptedPassword, out);\n            } catch (Exception e) {\n                throw new IOException(\"can't encrypt password that will be sent to MySQL server.\", e);\n            }\n        }\n        // 7 . (Null-Terminated String) databasename (optional)\n        if (getDatabaseName() != null) {\n            ByteHelper.writeNullTerminatedString(getDatabaseName(), out);\n        }\n        // 8 . (Null-Terminated String) auth plugin name (optional)\n        if (getAuthPluginName() != null) {\n            ByteHelper.writeNullTerminated(getAuthPluginName(), out);\n        }\n        // end write\n        return out.toByteArray();\n    }\n\n}\n","sourceCodeStart":30,"sourceCodeEnd":64,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/driver/src/main/java/com/alibaba/otter/canal/parse/driver/mysql/packets/client/ClientAuthenticationSHA2Packet.java#L30-L64","documentation":"Thrown by ClientAuthenticationSHA2Packet.toBytes() when MySQLPasswordEncrypter.scrambleCachingSha2 raises any Exception during the caching_sha2_password scramble (which uses SHA-256). Unlike the legacy packet (which only catches NoSuchAlgorithmException), this path catches a broad Exception, so the cause may be an unsupported SHA-256 algorithm, a null/empty scramble buffer, or a digest/encoding failure. Wrapped in an IOException.","triggerScenarios":"Authenticating to MySQL 8.0+ with a non-empty password over the caching_sha2_password plugin while the JVM cannot perform SHA-256 scrambling, or when the scramble buffer (nonce) received from the server handshake is null/malformed.","commonSituations":"MySQL 8 default auth plugin (caching_sha2_password) against a FIPS JVM that disables SHA-256; corrupt handshake packet producing a null scrumbleBuff; a buggy intermediate proxy mangling the server greeting; JDK without the Sun provider.","solutions":["Inspect the chained cause in the IOException to distinguish missing-algorithm vs null-scramble cases.","Ensure the server handshake packet is intact and scrumbleBuff is non-null before building the SHA2 packet.","On a restricted JVM, re-enable SHA-256 in java.security or use a stock OpenJDK.","If caching_sha2_password cannot be supported, change the MySQL user to mysql_native_password (error 322 path) or use an empty password over TLS.","Upgrade the Canal driver to a version with the full caching_sha2_password RSA/CLS round-trip support."],"exampleFix":"// before\nbyte[] enc = MySQLPasswordEncrypter.scrambleCachingSha2(pwd.getBytes(), scrumbleBuff);\n\n// after\nif (scrumbleBuff == null || scrumbleBuff.length == 0) {\n    throw new IllegalStateException(\"Server scramble buffer is null; handshake packet may be corrupt\");\n}\nMessageDigest.getInstance(\"SHA-256\"); // fail fast with a clear message if unsupported\nbyte[] enc = MySQLPasswordEncrypter.scrambleCachingSha2(pwd.getBytes(), scrumbleBuff);","handlingStrategy":"validation","validationCode":"public static boolean canScrambleSha2(byte[] nonce) {\n    try { java.security.MessageDigest.getInstance(\"SHA-256\"); return nonce != null && nonce.length > 0; }\n    catch (java.security.NoSuchAlgorithmException e) { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n    sha2Packet.toBytes();\n} catch (java.io.IOException e) {\n    Throwable c = e.getCause();\n    if (c instanceof java.security.NoSuchAlgorithmException) { /* SHA-256 unavailable */ }\n    else if (c instanceof NullPointerException) { /* null scramble buffer */ }\n    throw e;\n}","preventionTips":["Inspect the server handshake to ensure scrumbleBuff is non-null before building the SHA2 packet.","Confirm SHA-256 is registered on the JVM (especially FIPS builds).","Keep the Canal driver current for full caching_sha2_password support."],"tags":["authentication","mysql","security","sha256","caching-sha2","crypto"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}