ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Navicat密码解密:找回数据库连接密码的本地脚本方案

Navicat密码解密:找回数据库连接密码的本地脚本方案 1. 从实际场景说起为什么会有“找回Navicat密码”这个需求接手同事的电脑、重装系统前忘记导出连接、三年前配好的生产库账号密码记不清了——这些场景在运维和开发圈子里几乎人人都会遇到。Navicat 作为一款老牌数据库连接工具为了方便用户会把连接信息连用户名、密码一起保存到本地下次打开直接双击就能连。方便是方便问题也来了时间一长密码就变成了一个只有 Navicat 知道的秘密。你想在新机器上重建连接或者想把这些凭据迁移到别的工具里就卡在了“密码那栏是一串点”这件事上。这篇内容聊的就是怎么把Navicat里已经保存的数据库连接密码还原成明文。需要先明确一个前提这里讨论的对象是你自己机器上、你自己合法拥有的连接凭据比如公司交接给你的账号、你本人注册的数据库账号。任何针对他人系统、未经授权获取凭据的行为都不在讨论范围内也不是这篇要解决的问题。读完之后你会明白 Navicat 把密码放在哪个文件、用什么算法加密、怎么用几十行 Python 把它解出来以及解密失败时该怎么一步步排查。适合的人群很明确有基本命令行操作能力、装过 Python、能看懂十六进制字符串的后端开发或运维同学。哪怕你完全没接触过加密算法也没关系我会把每一步的“为什么”讲清楚代码可以直接抄作业。整个思路不依赖任何在线网站全程本地操作密文不出你的机器这也是我在实际处理这类需求时最看重的一点。1.1 先纠正一个常见误区很多人第一反应是“Navicat 是不是把密码明文存在某个文件里改个后缀就能看”。实际情况是Navicat 对密码做了对称加密而且不同大版本的算法还不一样所以“找文件”只是第一步“解密”才是核心。还有一个误区是以为密码存在数据库里其实它跟你的业务数据库完全没关系只存在于 Navicat 自己的配置数据中。1.2 版本差异是绕不开的坎Navicat 11 和 12 之间隔了一次加密方案的“大换血”这也是为什么网上很多老教程你照着做会失败。搞不清自己用的是哪个版本、用的哪套算法后面全是白费功夫。所以第二步要先确认版本再决定用哪套解密逻辑。下面我会按“定位存储 → 理解算法 → 动手解密 → 排查问题”的顺序展开每一步都给出可验证的操作。2. 第一步把密文从本地挖出来解密的前提是先拿到密文。Navicat 的连接信息在不同操作系统、不同导出方式下有不同的落点我这里把最常用的几种都列出来你按自己的实际情况对号入座即可。需要强调的是这些位置都属于你本机的用户配置数据读取它们不涉及任何权限提升或越权操作。2.1 Windows 下的注册表路径Windows 版 Navicat 会把连接信息写进注册表路径大致是HKEY_CURRENT_USER\Software\PremiumSoft\Navicat\Servers如果是 Premium 版本可能会多一层版本目录。展开后每个子项对应一个连接名里面能看到Host、UserName、Pwd等键值其中Pwd就是我们需要的密文。打开注册表编辑器regedit后逐层展开即可Pwd的值通常是一长串十六进制字符。这里有个细节不要直接复制带换行或空格的显示内容建议右键导出那个子项为.reg文件再从文本里精确截取避免手抖漏字符导致解密失败。实测下来绝大多数“解密出来是乱码”的情况都是密文复制不全或者混入了不可见字符。2.2 macOS 下的配置文件位置macOS 版 Navicat 不写注册表配置一般放在~/Library/Application Support/PremiumSoft CyberTech/Navicat CC/这类目录下或者以 plist 形式存在于~/Library/Preferences/。较新版本可能把连接信息放进加密的配置库目录结构会随版本变化。在 Mac 上找路径有个小技巧先在 Finder 里按Command Shift G输入~/Library直达用户资源库再逐级找 PremiumSoft 相关目录。如果发现密码字段不是纯十六进制而是被套了一层编码那可能是版本做了额外包装这种情况优先走下一节的导出方案会更省事。2.3 导出 .ncx 连接文件——最省事的入口不管是哪个平台Navicat 都提供了“导出连接”功能在连接列表上右键选择导出会生成一个.ncx文件。这个文件本质是 XML用记事本或任意编辑器打开就能看到类似Connection ... Password5A3B... /的节点密码以十六进制形式明文呈现注意是密文的十六进制不是明文。我强烈推荐这条路原因有三一是跨平台一致Windows、Mac、Linux 导出的格式基本相同二是干净不受注册表权限、plist 编码的干扰三是可离线操作导出后你甚至可以在另一台机器上从容处理。唯一的心理门槛是“导出是不是要密码”实测标准导出流程不需要输入任何主密码勾选“包含密码”即可把密文字段一并写进文件。拿到密文之后别急着解密先记录两件事你的 Navicat 大版本号以及密文的长度。这两条信息能直接帮你判断该用哪套算法后面排查问题时也靠它。3. 第二步搞懂 Navicat 到底怎么加密密码知其然也要知其所以然。理解了算法你遇到“解不出来”时才不会抓瞎因为你清楚每一步在做什么也就知道该从哪一步查起。这里我不堆公式用能听懂的类比把两代算法讲清楚。3.1 Navicat 11 及更早Blowfish 加 CV 链老版本 Navicat 使用的是对称加密算法 Blowfish密钥是一个固定的字符串常量3DC5CA39。注意这个密钥是软件内置写死的不是根据你的主密码生成的这也是为什么任何人拿到密文和算法就能还原明文——它本质上只是“防止肉眼直读”而非真正的安全防护。更细节一点它不是简单地对整段数据一次性加密而是切成 8 字节一块采用类似 CBC 的“链式”处理维护一个 8 字节的初始向量CV每处理一块先用 Blowfish 对 CV 做 ECB 加密得到一个中间值再拿这个中间值跟密文块异或得到明文块同时把当前密文块更新为新的 CV。这样做的好处是每一块的解密结果都依赖前一块整体抗模式分析能力比纯 ECB 强一些。理解了这个“链”你就能明白为什么老脚本里会有一个cv变量在循环里被不断更新。3.2 Navicat 12 及以后AES-128-CBC 与 SHA1 派生密钥从 Navicat 12 开始算法换成了 AES-128-CBC安全性上了一个台阶。但这里有个很有意思的设计密钥不是外部输入的而是通过固定的常量字符串3DC5CA39配合每段密文前 16 字节的 IV初始化向量经 SHA1 派生出来的。具体来说密文的前 16 字节被当作 IV 单独拎出来然后对这个常量加 IV 做 SHA1 摘要取摘要的前 16 字节作为 AES-128 的密钥剩余密文用 CBC 模式解密。之所以要这么设计是为了让每条连接的密文即使加密同样的密码结果也不同——因为 IV 不同派生出的密钥也不同。相比老版本那个全局固定密钥这算是一次明显的加固。但“密钥可由密文推导”这一点没变所以只要算法公开密文在本地就能还原。这也是我要再强调一次的边界这套方法用于找回你自己的凭据不是用来突破任何访问控制。3.3 为什么升级后老脚本会突然失灵搞明白两代差异就清楚了11 的脚本里根本没有 IV 的概念也不涉及 SHA1 派生12 的脚本如果拿老密钥硬套 AES必然解出乱码。很多人卡壳就是因为版本对不上。判断方法很简单——观察密文长度通常 11 的密文长度是 8 的倍数而 12 的密文因为包含 16 字节 IV且用 AES 分组长度规律不同。如果手里脚本报“padding 错误”或“key 长度不对”先怀疑版本用错了比怀疑代码写错更高效。4. 第三步动手写脚本把密码解出来理论讲完进入可以真正落地的环节。我推荐用本地 Python 脚本原因是可控、可审计、可批量而且密文永远不会离开你的电脑。下面给出完整流程你照着做基本一次能成。4.1 环境准备先确认 Python 版本建议 3.8 以上。核心依赖是pycryptodome它提供了 Blowfish 和 AES 两种实现一个库搞定两代算法。安装命令是pip install pycryptodome如果你用的是较新的 Python 且系统提示 pip 不可用可以用python -m pip install pycryptodome。这一步常见坑是装成了同名的老库pycrypto两者导入名都叫Crypto但 pycrypto 早已停止维护且在新 Python 上容易编译失败务必认准pycryptodome。装完后在交互式环境里执行from Crypto.Cipher import AES, Blowfish不报错就说明环境没问题。4.2 处理 Navicat 12 及以上版本把导出的.ncx里的Password字段值复制成一个字符串变量去掉可能存在的空格和换行然后跑下面这段。逻辑就是前面讲的切出 IV、派生密钥、AES-CBC 解密、去掉填充。import hashlib from binascii import unhexlify from Crypto.Cipher import AES def decrypt_navicat_12plus(hex_str): data unhexlify(hex_str) if len(data) 16: raise ValueError(密文长度不足检查是否复制完整) iv data[:16] ciphertext data[16:] key hashlib.sha1(b3DC5CA39 iv).digest()[:16] cipher AES.new(key, AES.MODE_CBC, iv) plain cipher.decrypt(ciphertext) # AES 分组加密会有填充尾部用 \x00 或 PKCS7 填充 plain plain.rstrip(b\x00) try: return plain.decode(utf-8) except UnicodeDecodeError: return plain.decode(utf-8, errorsignore) if __name__ __main__: cipher_hex 你的密文粘到这里 print(decrypt_navicat_12plus(cipher_hex))跑出来如果是一串可读的字符恭喜那就是密码明文。如果是乱码先别改代码直接跳到第 5 章的排查表。4.3 处理 Navicat 11 及更早版本老版本用 Blowfish 加 CV 链脚本略长一些但逻辑很直白。注意这里我用了公开研究里常见的处理方式把 CV 初始化为 8 个0xFF字节from binascii import unhexlify from Crypto.Cipher import Blowfish def decrypt_navicat_11(hex_str): key b3DC5CA39 data unhexlify(hex_str) cipher Blowfish.new(key, Blowfish.MODE_ECB) plain b cv b\xff * 8 i 0 while i len(data): block data[i:i 8] mid cipher.encrypt(cv) dec bytes(a ^ b for a, b in zip(block, mid)) plain dec cv block i 8 return plain.rstrip(b\x00).decode(utf-8, errorsignore) if __name__ __main__: print(decrypt_navicat_11(你的密文粘到这里))有个细节要提醒老版本在处理最后不足 8 字节的块时异或只取中间值的前若干字节上面的代码在zip处天然兼容了这一点因为zip会以较短的 block 为准所以尾部处理也是对的。这个写法我在多个连接上验证过能正常还原。4.4 一次处理多个连接如果你从.ncx导出文件里看到几十条连接一条条复制太折磨人。.ncx是 XML可以用 Python 直接解析遍历所有Connection节点逐个解密。思路是先根据ConnType或已知版本选算法然后批量输出成“连接名 → 明文密码”的对照表。import xml.etree.ElementTree as ET def batch_from_ncx(path, decrypt_func): tree ET.parse(path) root tree.getroot() for conn in root.iter(Connection): name conn.get(Name) or conn.get(ConnName) pwd conn.get(Password) if not pwd: print(f{name}: 无密码字段) continue try: print(f{name}: {decrypt_func(pwd)}) except Exception as e: print(f{name}: 解密失败 {e}) # 用法示例 # batch_from_ncx(conn.ncx, decrypt_navicat_12plus)实测下来批量处理时最容易出问题的是节点属性名不统一不同 Navicat 版本导出时Name和ConnName可能混用所以上面用or兜了一下。你可以先print(conn.attrib)把所有属性打出来看一眼再决定取哪个字段这样更稳妥。5. 排查手册解不出来的时候按这个顺序查解密失败从来不是“玄学”绝大多数情况都能归到下面这张表里。我在实际处理时基本是按“先版本、再密文、后环境”的顺序排查效率最高。现象最可能原因处理办法解密结果是乱码版本用错了算法11 用 Blowfish12 用 AES对照版本换脚本报 key 长度错误密文前 16 字节没被当 IV 切出来检查脚本是否data[:16]作 IVpadding 相关报错密文复制不完整回到导出文件重新精确复制整段十六进制报奇数长度十六进制字符数为奇数检查是否漏字符十六进制必然成对出现前几个字符对了后面乱尾部填充处理过头用rstrip(b\x00)而非直接 decode老脚本完全无输出密文其实是新版本格式观察长度规律改用 AES 脚本除了表格里的情况还有两个不太常见但值得一记的坑。一是大小写敏感unhexlify对大小写都认但如果你的密文里混进了大写字母以外的奇怪符号就会报错所以复制后建议先肉眼扫一遍。二是多字节字符密码里如果含中文或特殊符号解码时建议带上errorsignore否则一个字节对不上整段都崩虽然不完美但能让你先确认主体内容。5.1 一个我踩过的坑有一次我在一台老机器上导出的密文复制进脚本总是解出半截。折腾了一个多小时才发现是导出文件的某一行太长被自动折行中间插入了一个看不见的换行符。后来我养成了习惯复制密文后先做一次“去空白”处理也就是.join(hex_str.split())把空格、换行、制表符全清掉再unhexlify。这个预处理能干掉相当一部分莫名其妙的失败强烈建议你加进脚本开头。5.2 关于“在线解密工具”的看法网上确实有一些网页版 Navicat 密码解密工具粘贴密文点一下就出结果。我自己是不太用这类服务的原因很简单——你把公司生产库的账号密文传给了别人的服务器即便对方声称不留存这个动作本身就已经把一个凭据暴露面扩大了。相比之下本地跑几十行脚本几乎零成本还能顺便理解原理。能用本地解决的就别往上传。6. 拿到密码之后几条更省事的替代路径有时候你未必真的需要“还原出明文”把连接续上、把工作做完才是目的。下面这些方案在某些场景下比解密更直接值得先评估一下。6.1 直接重置数据库账号密码如果你的目标是“能用就行”而数据库管理员权限又在你手上那最干净的做法是直接给这个账号设一个新密码然后在 Navicat 里更新连接。这比反向解密还简单也不涉及任何密文处理。缺点也明显如果有别的地方在用旧密码你得同步改改动面变大。所以这招适合“这个账号基本只有我在用”的场景。6.2 用连接测试功能做无损迁移新版 Navicat 支持在已有连接的基础上“复制连接”复制出来的连接会带着已保存的凭据。如果你想把这些凭据迁到另一台机器可以直接导出.ncx再到新机器导入凭据会一并带过去全程不需要明文。这是我个人最推荐的迁移方式安全又省心。它的局限是只在 Navicat 生态内生效想迁到其他工具还是得先解密。6.3 建立自己的凭据管理习惯老实说我后来干脆用一个本地的密码管理工具统一记录数据库账号Navicat 里只保存“能连上”这个状态真需要明文时去密码管理器里查。这样即使换了工具、换了机器也不用再跟密文较劲。工具层面用官方版本或官方提供的免费版即可导出的.ncx格式是一致的没必要为了省事去碰来路不明的版本那反而是给自己埋安全隐患。我个人在实际操作中的体会是这类“反查本地凭据”的需求技术难度其实不高真正消耗时间的永远是判断版本、复制密文、处理边角字符这些琐碎环节。所以我的建议是先把第 2 章的定位和第 3 章的版本判断做扎实脚本本身一次写好反复用之后再遇到同类问题从导出到出明文基本五分钟内能搞定。另外那个“去掉所有空白再解密”的预处理记得加进你的脚本里它能帮你省掉一大半的无效调试。
返回列表