Navicat密码找回:基于Blowfish算法与PHP/Java的本地解密方案

发布时间:2026/6/30 5:53:06
Navicat密码找回:基于Blowfish算法与PHP/Java的本地解密方案 1. 引言当Navicat密码成为“熟悉的陌生人”相信不少数据库管理员和开发者都遇到过这个让人瞬间血压升高的场景打开Navicat准备连接一个许久未碰的测试服务器或者一个老项目数据库双击那个熟悉的连接配置弹出的不是熟悉的数据库列表而是一个冷冰冰的密码输入框。大脑一片空白尝试了几个常用的密码组合都宣告失败。Navicat为了安全默认会将连接密码加密后存储在本地配置文件中而不是明文保存。这原本是好事但当我们自己忘了密码时它就成了一道打不开的锁。网上流传着一些方法比如用专门的解密工具或者修改注册表、配置文件。但这些方法要么工具难找、版本不兼容要么操作复杂有风险。今天我想分享一个我亲自验证过的、更通用且安全的思路自己写一个简单的在线工具来“找回”密码。核心原理并不复杂就是利用Navicat存储密码的加密算法写一个反向的解密程序。我将提供一个清晰易懂的PHP实现版本并附上对应的Java版核心逻辑让你无论身处何种技术栈都能在5分钟内解决问题。这个方法的好处是完全自主可控无需安装不明来源的软件尤其适合在受控的内网环境或对安全有要求的场景下使用。2. Navicat密码存储机制深度解析要“找回”密码首先得知道Navicat把它藏在了哪里以及它是怎么藏的。这不是破解而是理解其存储机制后的合法读取。2.1 密码的藏身之处Navicat的版本和操作系统不同配置文件的位置也略有差异。对于最常见的Windows系统上的Navicat for MySQLNavicat 11及更早版本连接信息通常以注册表项形式存储。路径类似于HKEY_CURRENT_USER\Software\PremiumSoft\Navicat\Servers。Navicat 12及更新版本推荐查看位置连接信息转移到了用户目录的配置文件里通常是XML格式。路径例如C:\Users\[你的用户名]\Documents\Navicat\MySQL\Servers。你会看到以连接名命名的.ncx文件。注意macOS 或 Linux 版本路径不同通常在~/Documents/Navicat/...或~/.config/navicat/...下。本文以Windows为例原理是相通的。用文本编辑器打开一个.ncx文件你会看到类似下面的结构?xml version1.0 encodingUTF-8? Connection Namelocalhost/Name Host127.0.0.1/Host Port3306/Port UserNameroot/UserName Password15057D7BA390/Password !-- 注意这里这就是加密后的密码 -- ... /Connection那个Password标签里的字符串如15057D7BA390就是我们本次行动的目标——经过Navicat加密后的密码密文。2.2 加密算法揭秘Blowfish与异或的“二人转”Navicat使用的加密算法并非高深莫测它主要基于Blowfish算法的一个变种并结合了一个固定的异或XOR操作。其流程可以简化为生成密钥使用一个固定的字符串我们称之为“盐”或“密钥种子”“3DC5CA39”通过MD5哈希生成一个Blowfish算法所需的密钥。这个固定字符串是公开的也是我们能够逆向计算的基础。Blowfish加密使用上一步生成的密钥对用户的明文密码进行Blowfish加密ECB模式。这一步是标准加密。异或混淆将Blowfish加密后的结果与一个固定的字节序列0xAA进行逐字节的异或操作。这一步可以看作是一种简单的二次混淆。十六进制表示将最终混淆后的字节数组转换为大写的十六进制字符串就是我们在XML文件中看到的样子。所以解密过程就是上述步骤的逆序读取十六进制字符串 - 与0xAA异或 - Blowfish解密。关键在于我们需要使用与加密时完全相同的密钥种子“3DC5CA39”来初始化Blowfish解密器。实操心得不同版本的Navicat可能在某些细节上有微调比如密钥种子字符串、是否包含异或步骤。但主流版本Navicat 12-17的MySQL连接基本遵循上述规则。如果遇到解密失败可以尝试搜索对应版本特定的密钥种子。3. PHP在线解密工具实战理解了原理我们就可以动手了。PHP版本的优势是部署快速一个文件就能跑起来非常适合临时搭建一个解密页面。3.1 环境准备与核心代码你需要一个支持PHP的Web服务器环境如Apache、Nginx with PHP-FPM或者直接用PHP内置服务器。代码的核心是openssl扩展用于Blowfish解密确保你的PHP环境已启用它php -m | grep openssl。下面是完整的decrypt_navicat_password.php文件内容?php /** * Navicat密码解密工具 (for MySQL) * 注意本工具仅用于找回用户自己遗忘的密码请勿用于非法用途。 */ // 设置页面编码 header(Content-Type: text/html; charsetutf-8); // 定义Navicat使用的固定密钥Blowfish密钥的生成种子 define(NAVICAT_KEY, 3DC5CA39); /** * 解密Navicat加密的密码 * param string $encryptedHex 加密后的十六进制字符串 * return string|false 解密后的明文密码失败返回false */ function decryptNavicatPassword($encryptedHex) { // 1. 将十六进制字符串转换为二进制数据 $encryptedData hex2bin($encryptedHex); if ($encryptedData false) { return false; // 非法的十六进制字符串 } // 2. 与固定值0xAA进行异或操作解密的第一步是反向异或 $xoredData ; for ($i 0; $i strlen($encryptedData); $i) { $xoredData . $encryptedData[$i] ^ chr(0xAA); } // 3. 准备Blowfish解密 // 使用固定的密钥种子生成MD5作为Blowfish的实际密钥 $bfKey md5(NAVICAT_KEY, true); // true参数返回原始二进制数据 // 4. 使用OpenSSL进行Blowfish解密 (ECB模式无填充) // Navicat使用的Blowfish是ECB模式并且可能不使用标准填充。 // 这里我们使用openssl_decrypt并尝试无填充选项。 $method BF-ECB; $options OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING; // 使用零填充或原始数据 $decrypted openssl_decrypt($xoredData, $method, $bfKey, $options); // 5. 清理解密结果移除末尾的空白字符如\0 if ($decrypted ! false) { $decrypted rtrim($decrypted, \x00..\x1F); // 移除控制字符和空字符 } return $decrypted; } // 处理表单提交 $decryptedPassword ; $error ; $inputHex ; if ($_SERVER[REQUEST_METHOD] POST) { $inputHex trim($_POST[encrypted_password] ?? ); if (empty($inputHex)) { $error 请输入加密后的密码字符串。; } elseif (!preg_match(/^[0-9A-Fa-f]$/, $inputHex)) { $error 输入的内容必须是有效的十六进制字符0-9, A-F。; } else { // 确保字符串长度为偶数十六进制字节对 if (strlen($inputHex) % 2 ! 0) { $error 十六进制字符串长度应为偶数。; } else { $result decryptNavicatPassword(strtoupper($inputHex)); // 统一转为大写处理 if ($result false) { $error 解密失败请检查输入的字符串是否正确或尝试其他版本密钥。; } else { $decryptedPassword htmlspecialchars($result, ENT_QUOTES, UTF-8); } } } } ? !DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleNavicat密码解密工具/title style body { font-family: sans-serif; margin: 40px; line-height: 1.6; background-color: #f5f5f5; } .container { max-width: 800px; margin: auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } h1 { color: #333; border-bottom: 2px solid #4CAF50; padding-bottom: 10px; } .form-group { margin-bottom: 20px; } label { display: block; margin-bottom: 8px; font-weight: bold; color: #555; } input[typetext] { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; font-family: monospace; } button { background-color: #4CAF50; color: white; padding: 12px 24px; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; } button:hover { background-color: #45a049; } .result, .error { padding: 15px; border-radius: 4px; margin-top: 20px; } .result { background-color: #dff0d8; border: 1px solid #d6e9c6; color: #3c763d; } .error { background-color: #f2dede; border: 1px solid #ebccd1; color: #a94442; } code { background-color: #f8f9fa; padding: 2px 6px; border-radius: 3px; border: 1px solid #eaecf0; } .steps { background-color: #e7f3fe; padding: 15px; border-left: 4px solid #2196F3; margin: 20px 0; } /style /head body div classcontainer h1Navicat (MySQL) 密码解密工具/h1 p本工具用于解密Navicat for MySQL存储在配置文件.ncx中的加密密码。请将配置文件中 codelt;Passwordgt;/code 标签内的字符串粘贴到下框。/p div classsteps strong操作步骤/strong ol li找到Navicat连接配置文件通常位于 code文档\Navicat\MySQL\Servers\连接名.ncx/code。/li li用文本编辑器打开找到类似 codelt;Passwordgt;15057D7BA390lt;/Passwordgt;/code 的行。/li li复制 code15057D7BA390/code 这部分字符串不含标签。/li li粘贴到下方输入框点击“解密”。/li /ol /div form methodpost div classform-group label forencrypted_password加密的密码字符串/label input typetext idencrypted_password nameencrypted_password value?php echo htmlspecialchars($inputHex, ENT_QUOTES); ? placeholder例如15057D7BA390 required /div button typesubmit开始解密/button /form ?php if (!empty($error)): ? div classerror strong错误/strong ?php echo $error; ? /div ?php endif; ? ?php if (!empty($decryptedPassword)): ? div classresult strong解密成功明文密码是/strong div stylemargin-top:10px; padding:10px; background:#fff; border:1px dashed #ccc; font-family:monospace; font-size:18px; word-break:break-all; ?php echo $decryptedPassword; ? /div p stylemargin-top:10px; font-size:0.9em; color:#666;small提示请妥善保管你的密码。解密后请关闭此页面以确保安全。/small/p /div ?php endif; ? hr stylemargin: 30px 0; h3注意事项/h3 ul li本工具运行在您的服务器或本地环境密码数据不会上传到任何第三方。/li li仅支持Navicat for MySQL常见版本的加密格式密钥种子为code3DC5CA39/code。/li li对于Navicat Premium支持多种数据库其加密方式可能因数据库类型而异。本工具主要针对MySQL连接。/li li如果解密失败请尝试检查字符串是否正确复制或搜索您使用的Navicat版本对应的特定密钥种子。/li /ul /div /body /html3.2 部署与使用指南保存文件将上面的代码完整复制保存为decrypt_navicat_password.php。放置到Web目录将该文件放到你的PHP Web服务器根目录如htdocs,www,/var/www/html。访问页面在浏览器中访问http://你的服务器地址/decrypt_navicat_password.php。获取密文按照页面提示找到你的Navicat连接配置文件.ncx复制Password标签内的加密字符串。解密将字符串粘贴到网页输入框点击“解密”按钮。如果一切顺利明文密码会显示在下方。实操心得如果部署在公网服务器使用完毕后请务必删除或重命名该PHP文件以防被他人利用。最佳实践是在本地环境如使用php -S localhost:8080启动内置服务器使用用完即关确保密码不离开本地。3.3 常见问题与排查PHP版问题解密后得到乱码或空字符串。排查首先确认复制的加密字符串完全正确没有多余空格或换行。其次确认你的Navicat版本。较老的Navicat 11或某些特定数据库类型如Oracle、SQL Server可能使用不同的加密密钥。尝试搜索“Navicat [你的版本] [数据库类型] password encryption key”。解决修改代码第9行的NAVICAT_KEY常量定义。已知的一些其他密钥包括5F5D10F2(某些旧版) 等。需要根据版本进行尝试。问题页面报错Call to undefined function openssl_decrypt()。排查PHP环境没有安装或启用OpenSSL扩展。解决打开php.ini文件找到;extensionopenssl这一行去掉前面的分号;保存并重启Web服务器。问题解密结果末尾有多余的不可见字符。排查Blowfish ECB模式解密时如果原始密码长度不是8的倍数可能会进行填充。我们的代码中使用了OPENSSL_ZERO_PADDING并随后用rtrim清理通常能处理好。如果仍有问题可能是填充方式不同。解决可以尝试将OPENSSL_ZERO_PADDING改为OPENSSL_RAW_DATA不处理填充然后手动检查解密结果去除末尾的填充字节通常是连续的0x00或0x04。4. Java版解密核心实现对于Java技术栈的开发者或者希望将解密功能集成到桌面应用、后台服务中的场景一个Java版本的实现是很有用的。这里提供核心的解密方法类。4.1 Java项目依赖与核心类你需要一个Java项目JDK 8及以上。核心依赖是Java标准库的javax.crypto包用于Blowfish解密。创建一个名为NavicatPasswordDecryptor.java的类import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; public class NavicatPasswordDecryptor { // Navicat使用的固定密钥种子用于MySQL private static final String NAVICAT_KEY 3DC5CA39; /** * 解密Navicat加密的密码 * param encryptedHex 加密后的十六进制字符串 * return 解密后的明文密码解密失败返回null */ public static String decrypt(String encryptedHex) { try { // 1. 十六进制字符串转字节数组 byte[] encryptedData hexStringToByteArray(encryptedHex); if (encryptedData null) { System.err.println(错误无效的十六进制字符串。); return null; } // 2. 与0xAA进行异或操作 for (int i 0; i encryptedData.length; i) { encryptedData[i] (byte) (encryptedData[i] ^ (byte) 0xAA); } // 3. 生成Blowfish密钥对固定密钥种子进行MD5 MessageDigest md5 MessageDigest.getInstance(MD5); byte[] bfKeyBytes md5.digest(NAVICAT_KEY.getBytes(StandardCharsets.UTF_8)); SecretKeySpec secretKey new SecretKeySpec(bfKeyBytes, Blowfish); // 4. 初始化Blowfish Cipher进行解密 (ECB模式无填充) Cipher cipher Cipher.getInstance(Blowfish/ECB/NoPadding); cipher.init(Cipher.DECRYPT_MODE, secretKey); // 5. 执行解密 byte[] decryptedBytes cipher.doFinal(encryptedData); // 6. 转换为字符串并清理尾部空字符 String decrypted new String(decryptedBytes, StandardCharsets.UTF_8); // 移除末尾的填充字符\0和控制字符 decrypted decrypted.replaceAll(\\x00$, ); decrypted decrypted.trim(); // 额外trim一下空格 return decrypted; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 将十六进制字符串转换为字节数组 */ private static byte[] hexStringToByteArray(String s) { int len s.length(); if (len % 2 ! 0) { System.err.println(错误十六进制字符串长度必须为偶数。); return null; } byte[] data new byte[len / 2]; for (int i 0; i len; i 2) { // 每两个字符解析一个字节 data[i / 2] (byte) ((Character.digit(s.charAt(i), 16) 4) Character.digit(s.charAt(i1), 16)); } return data; } /** * 主方法用于测试 */ public static void main(String[] args) { // 示例解密字符串 15057D7BA390 String encryptedPassword 15057D7BA390; // 替换成你自己的密文 String decryptedPassword decrypt(encryptedPassword.toUpperCase()); // 建议统一大写 if (decryptedPassword ! null) { System.out.println(加密字符串: encryptedPassword); System.out.println(解密后密码: decryptedPassword); } else { System.out.println(解密失败。); } } }4.2 编译与运行保存文件将代码保存为NavicatPasswordDecryptor.java。编译在命令行中切换到文件所在目录执行javac NavicatPasswordDecryptor.java。运行测试执行java NavicatPasswordDecryptor。程序会运行main方法中的示例。你需要将encryptedPassword变量的值替换成你从.ncx文件中复制的实际加密字符串。集成使用你也可以在其他Java类中直接调用NavicatPasswordDecryptor.decrypt(yourEncryptedHexString)来获取解密结果。4.3 Java版注意事项与调试填充模式代码中使用了Blowfish/ECB/NoPadding。这是基于Navicat加密时可能未使用标准PKCS填充的判断。如果解密结果末尾有乱码可以尝试更换为Blowfish/ECB/PKCS5Padding试试但根据我的经验NoPadding配合后续的字符串清理更通用。字符编码确保在转换字节数组到字符串时使用UTF-8这与Navicat的编码方式通常一致。密钥版本同样如果解密失败首要怀疑是密钥种子不对。修改NAVICAT_KEY常量为其他可能的值如5F5D10F2进行尝试。异常处理在生产环境中集成时建议对decrypt方法进行更细致的异常捕获和日志记录而不是简单地打印堆栈跟踪。5. 安全考量与最佳实践虽然我们找回了密码但这个过程本身也提醒我们注意数据库连接的安全管理。工具使用安全本文提供的PHP工具强烈建议仅在本地环境localhost运行并在使用完毕后立即删除。绝对不要将其部署在公网上即使有简单的防护也存在被恶意利用的风险。Java版程序也应妥善保管编译后的class或jar文件。密码管理升级频繁忘记密码说明当前的密码管理方式可能存在问题。考虑使用专业的密码管理器如KeePass、Bitwarden、1Password来存储数据库密码等敏感信息。Navicat本身也提供了“导出连接”不含密码和“导入连接”的功能可以将连接配置不含密码备份密码由密码管理器记忆。连接配置的备份定期备份Navicat的配置文件夹即包含Servers目录的整个Navicat文件夹。这样即使重装系统或更换电脑也能快速恢复连接设置但密码仍需重新输入或通过本文方法找回。使用SSH隧道或SSL连接对于生产环境数据库尽量避免使用密码直接连接。配置SSH隧道或启用数据库的SSL证书认证可以提升连接的安全性。最小权限原则为Navicat连接使用的数据库账号分配最小必要的权限避免使用root或拥有超级权限的账号进行日常连接操作。这样即使密码泄露也能将损失降到最低。找回密码只是补救措施养成良好的密码管理和连接配置习惯才是根本。希望这个自己动手、丰衣足食的小工具和背后的原理讲解不仅能帮你解决眼前的困境也能让你对Navicat这类工具的运作机制有更深的理解。毕竟知其然并知其所以然是我们技术人员解决问题的乐趣所在。