Navicat密码恢复全攻略:从导出到解密的完整解决方案
忘记数据库连接密码是每个DBA或开发人员都可能遇到的棘手问题。Navicat作为一款流行的数据库管理工具,其保存的密码采用了不同版本的加密机制。本文将系统性地介绍三种导出加密密码的方法,并针对Navicat 11(Blowfish)和12+(AES-128-CBC)两种加密算法提供PHP/Python解密脚本的详细实现。
1. Navicat密码导出方法
1.1 通过连接文件导出
这是最直接的密码获取方式,适用于所有Navicat版本:
- 打开Navicat,点击顶部菜单栏的"文件"→"导出连接"
- 在弹出窗口中勾选"导出密码"选项
- 选择保存位置,文件将被保存为
connections.ncx格式 - 用文本编辑器打开该文件,搜索
Password=字段
注意:导出的connections.ncx文件包含所有连接的配置信息,请妥善保管以防信息泄露
1.2 通过注册表提取(Windows系统)
对于无法直接导出连接文件的情况,可以通过注册表获取:
# 打开注册表编辑器 regedit导航至以下路径:
- Navicat 11:
HKEY_CURRENT_USER\Software\PremiumSoft\Navicat\Servers - Navicat 12+:
HKEY_CURRENT_USER\Software\PremiumSoft\NavicatPremium\Servers
每个连接对应一个子项,其中的Pwd字段存储了加密后的密码。
1.3 不同版本的导出差异
| 版本范围 | 加密方式 | 存储位置 | 备注 |
|---|---|---|---|
| Navicat 11及之前 | Blowfish | 注册表/导出文件 | 密钥固定 |
| Navicat 12-15 | AES-128-CBC | 注册表/导出文件 | 需要特定IV |
| Navicat 16+ | AES-256-CBC | 导出文件优先 | 注册表可能不完整 |
2. Navicat 11(Blowfish)解密实现
2.1 PHP解密脚本
<?php class Navicat11Decryptor { private $blowKey; private $blowIv; public function __construct() { $this->blowKey = sha1('3DC5CA39', true); $this->blowIv = hex2bin('d9c7c3c8870d64bd'); } private function decryptBlock($block) { return openssl_decrypt( $block, 'BF-ECB', $this->blowKey, OPENSSL_RAW_DATA|OPENSSL_NO_PADDING ); } private function xorBytes($a, $b) { $result = ''; for ($i = 0; $i < strlen($a); $i++) { $result .= chr(ord($a[$i]) ^ ord($b[$i])); } return $result; } public function decrypt($encrypted) { $data = hex2bin(strtolower($encrypted)); $length = strlen($data); $plaintext = ''; $iv = $this->blowIv; for ($i = 0; $i < floor($length / 8); $i++) { $block = substr($data, $i * 8, 8); $decrypted = $this->decryptBlock($block); $plaintext .= $this->xorBytes($decrypted, $iv); $iv = $this->xorBytes($iv, $block); } return rtrim($plaintext, "\0"); } } // 使用示例 $decryptor = new Navicat11Decryptor(); $password = $decryptor->decrypt('15057D7BA390'); // 替换为实际加密字符串 echo "解密结果: ".$password; ?>2.2 Python解密实现
from Crypto.Cipher import Blowfish from binascii import unhexlify def decrypt_navicat11(encrypted): key = b'3DC5CA39' cipher = Blowfish.new(key, Blowfish.MODE_ECB) iv = b'\xD9\xC7\xC3\xC8\x87\x0D\x64\xBD' data = unhexlify(encrypted.lower()) result = bytearray() for i in range(0, len(data), 8): block = data[i:i+8] decrypted = cipher.decrypt(block) plain = bytes(a ^ b for a, b in zip(decrypted, iv)) result.extend(plain) iv = bytes(a ^ b for a, b in zip(iv, block)) return result.decode('utf-8').rstrip('\x00') # 使用示例 password = decrypt_navicat11('15057D7BA390') print(f"解密结果: {password}")3. Navicat 12+(AES)解密实现
3.1 PHP解密脚本
<?php class Navicat12Decryptor { private $aesKey = 'libcckeylibcckey'; private $aesIv = 'libcciv libcciv '; public function decrypt($encrypted) { $data = hex2bin(strtolower($encrypted)); return openssl_decrypt( $data, 'AES-128-CBC', $this->aesKey, OPENSSL_RAW_DATA, $this->aesIv ); } } // 使用示例 $decryptor = new Navicat12Decryptor(); $password = $decryptor->decrypt('AE137B98AB3AD0F913EBEF2E8D3C52E9'); echo "解密结果: ".$password; ?>3.2 Python解密实现
from Crypto.Cipher import AES from binascii import unhexlify def decrypt_navicat12(encrypted): key = b'libcckeylibcckey' iv = b'libcciv libcciv ' cipher = AES.new(key, AES.MODE_CBC, iv) data = unhexlify(encrypted.lower()) decrypted = cipher.decrypt(data) return decrypted.decode('utf-8').rstrip('\x00') # 使用示例 password = decrypt_navicat12('AE137B98AB3AD0F913EBEF2E8D3C52E9') print(f"解密结果: {password}")4. 版本判断与自动化工具
4.1 版本识别方法
通过加密字符串长度判断:
- Blowfish加密结果通常为12字符(如
15057D7BA390) - AES加密结果为32字符(如
AE137B98AB3AD0F913EBEF2E8D3C52E9)
- Blowfish加密结果通常为12字符(如
通过Navicat关于界面确认:
- 帮助 → 关于Navicat [产品名称]
4.2 自动化解密脚本
以下是一个自动识别版本并解密的Python脚本:
import re from Crypto.Cipher import AES, Blowfish from binascii import unhexlify class NavicatDecryptor: @staticmethod def detect_version(encrypted): if len(encrypted) == 12: return 11 # Blowfish elif len(encrypted) == 32: return 12 # AES else: raise ValueError("无法识别的加密格式") @staticmethod def decrypt(encrypted): version = NavicatDecryptor.detect_version(encrypted) if version == 11: return NavicatDecryptor.decrypt_11(encrypted) else: return NavicatDecryptor.decrypt_12(encrypted) @staticmethod def decrypt_11(encrypted): # Blowfish解密实现 pass @staticmethod def decrypt_12(encrypted): # AES解密实现 pass # 使用示例 encrypted_pwd = "AE137B98AB3AD0F913EBEF2E8D3C52E9" # 替换为实际加密密码 password = NavicatDecryptor.decrypt(encrypted_pwd) print(f"解密结果: {password}")4.3 批量处理connections.ncx文件
对于需要批量解密多个连接密码的情况,可以使用以下Shell脚本:
#!/bin/bash # 提取所有加密密码 encrypted_passwords=$(grep -o 'Password="[^"]*"' connections.ncx | cut -d'"' -f2) # 遍历解密 for enc_pwd in $encrypted_passwords; do # 调用解密脚本 plain_pwd=$(php navicat_decrypt.php "$enc_pwd") echo "加密: $enc_pwd → 明文: $plain_pwd" done5. 安全建议与最佳实践
密码管理:
- 避免在Navicat中保存敏感生产环境密码
- 使用专业密码管理工具存储重要凭证
连接配置:
- 定期清理不再使用的连接配置
- 对导出的连接文件进行加密存储
权限控制:
- 限制对注册表和配置文件的访问权限
- 在团队环境中使用最小权限原则
替代方案:
- 考虑使用SSH隧道连接数据库
- 评估使用命令行工具或API替代GUI工具
重要提示:本文提供的技术方案仅适用于合法恢复自己遗忘的密码。未经授权解密他人密码可能违反法律法规和服务条款。