简介:一套面向ArchLinux用户的Navicat Premium 15安装与激活工具源码备份。因原版navicat-keygen备份已被删除,作者将完整工程重新打包分享,主要解决Linux环境下Navicat授权激活时无可用工具的问题。压缩包共41个文件,约71KB,包含21个hpp头文件与11个cpp源文件构成的核心代码,另有6个Markdown文档详细说明工作原理与构建步骤,以及Makefile、LICENSE等工程文件,模块划分清晰,便于直接阅读和二次构建。目前已有699人学习下载。这份源码特别适合研究RSA授权文件生成、序列号校验机制以及跨平台程序构建的开发者,通过阅读关键模块代码,可深入理解Keygen工具的工作流程,也能在ArchLinux上自行编译部署,节省排查时间。
1. 你的“备份”为什么救不了 Navicat Premium 15 激活现场
如果你手头还有一份navicat-keygen.zip的源码包,大概率是从某个下载站拖回来的,解压之后发现里面有navicat-keygen、navicat-patcher、how-does-it-work.md和对应的中文文档,却唯独少了编译好的二进制文件和rsa_private_key.pem——那不是你下载出错,而是这个仓库从设计上就不维护二进制产物,所有东西都要自己编。更麻烦的是,很多人把这个 zip 当成激活工具备份,等系统重装完才发现,真正的密钥文件根本没被保存下来,备份已经被删除的,再重新下载也没用。这篇博文就围绕 Navicat Premium 15 在 Linux 上的安装与激活,把navicat-keygen这条链路的原理、编译、补丁注入和密钥恢复讲清楚,适合正在用 ArchLinux 做日常开发、又不想在数据库客户端上花太多时间的工程师,也适合对 RSA 签名和 ELF 补丁感兴趣的人顺手研究一下内部机制。
2. 从 RSA 私钥到许可证签名:navicat-keygen 的激活链路拆解
激活工具看起来是“输入序列号、生成请求码、返回激活码”三步,背后其实是 RSA 非对称签名在起作用。Navicat 在验证许可证时,会用内置的公钥去校验激活码的签名,只有私钥持有者才能签出合法激活码。navicat-keygen做的事情就是把自己生成的 RSA 私钥注入到 Navicat 的二进制里,让程序相信这个私钥对应的公钥是官方密钥。
2.1 源码里的签名核心:RSACipher 和 GenerateLicense
打开GenerateLicense.cpp,可以看到这个工具的整个激活码生成过程被封装成了独立的类,核心方法大致是:
std::string GenerateLicense::generate(const std::string& requestCode) { // 1. 将请求码 base32 解码成字节流 std::vector<uint8_t> requestBytes = decodeBase32(requestCode); // 2. 用之前注入的 RSA 私钥对请求码做 SHA256 摘要 + 签名 RSACipher cipher(rsaPrivateKey); std::vector<uint8_t> digest = sha256(requestBytes); std::vector<uint8_t> signature = cipher.sign(digest); // 3. 把签名结果重新编码为 base32,格式化后输出 return formatLicense(base32Encode(signature)); }这里最值得关注的是第一步的decodeBase32。Navicat 的请求码不是普通 ASCII 明文,而是把机器码、版本号、产品 ID 等字段做 Base32 编码后的字符串,长度一般固定在 128 或 144 字符。navicat-keygen在解密请求码后,会从里面抽取出产品版本(比如premium、mysql)、平台标识(linux)、语言代码(zh-CN)等信息,再拼装到许可证内容里。如果解码后拿到的字段和你输入序列号时的选项不匹配,激活码即使生成成功也会在 Navicat 里报“Invalid license”。
2.2 序列号里的 Base32 与双校验
SerialNumberGenerator.cpp里实现了序列号的确定性生成,它不是一个随机字符串,而是包含校验位的结构化编码。核心逻辑如下:
// 伪代码,用于展示序列号结构 string GenerateSerial(int productId, int version, int language) { byte[] data = new byte[5]; data[0] = (byte)(productId >> 8); data[1] = (byte)(productId & 0xFF); data[2] = (byte)(version); data[3] = (byte)(language); data[4] = 0; // 校验位占位 data[4] = Crc8(data, 4); // 对前4字节做CRC8 return Base32Encode(data); }注意这里用了 CRC8 而不是简单的异或校验。CRC8 的计算需要查表和初值约定,navicat-keygen里的实现和 Navicat 官方校验算法一致,所以生成的序列号能骗过第一道检查。但序列号只负责第一道关卡,真正决定能否激活成功的是第二道:请求码里的机器指纹与激活码签名是否匹配同一个 RSA 密钥对。如果你用navicat-keygen生成的序列号,却拿官方补丁或者过期工具去激活,签名验证会直接失败。
| 校验阶段 | 输入数据 | 算法 | 失败表现 |
|---|---|---|---|
| 序列号格式校验 | 序列号字符串 | Base32 解码 + CRC8 | 提示 Serial number invalid |
| 请求码结构校验 | 请求码字符串 | Base32 解码 + 字段解析 | 提示 Invalid request code |
| 激活码签名校验 | 请求码解密字段 + 激活码 | RSA + SHA256 | 提示 License is not valid |
这三层校验层层递进,任何一层过不去,激活码都白搭。
2.3 how-does-it-work.md 里没写透的密钥注入时机
仓库里的how-does-it-work.zh-CN.md把原理讲得很清楚,但它默认你已经明白“注入密钥”和“生成密钥”是两步操作。实际上,navicat-patcher是在 Navicat 安装完成之后、首次启动之前执行的,它会做三件事:定位二进制里的官方公钥储存区,把原始公钥替换成自己的 RSA 公钥,同时记录替换偏移量。这个偏移量会输出到终端,也会写进日志文件,后续navicat-keygen生成激活码时需要知道这个偏移量,才能把签名文件放在正确位置。
我一般会在执行完 patcher 后截屏保存终端输出,因为日志文件可能因为权限问题没写成功。如果偏移量丢了,激活码会生成失败,常见报错是unspecified file offset。这种问题不是重装 Navicat 能解决的,必须重新跑一遍 patcher,拿到新的偏移量。
3. ArchLinux 环境准备与 navicat-keygen 编译实战
在 ArchLinux 上编译navicat-keygen比在 Ubuntu 上要顺一些,因为 AUR 里基本能找齐依赖。但如果你之前没有装过 base-devel,第一次编译还是会踩不少坑。
3.1 Arch 系依赖:openssl 和 capstone/keystone 二选一
navicat-patcher的补丁逻辑依赖反汇编框架,代码里能看到PatchSolution0.cpp、CapstoneDisassembler.cpp和KeystoneAssembler.cpp,说明它需要 Capstone 来做反汇编、再用 Keystone 来做汇编。这两个库在 Arch 的官方源里都有,直接安装即可:
sudo pacman -Syu base-devel openssl capstone keystone rapidjson如果你的系统里之前装过openssl-1.1(比如为了兼容某个旧软件),编译时可能会链接到错误版本。建议先确认当前 openssl 版本:
openssl version pkg-config --modversion openssl如果版本是 3.x,而navicat-keygen的 Makefile 里写的是-lcrypto,一般没问题。真正容易出错的是rapidjson,这个头文件库在某些发行版里不提供pkg-config文件,Makefile 里也没有显式包含路径,编译时会报找不到rapidjson/document.h。
提示:Arch 官方源里的 rapidjson 安装在
/usr/include/rapidjson,如果报错找不到头文件,手动加-I/usr/include到 CXXFLAGS 即可。
另外,如果你在折腾完输入法(比如 archlinux 配置fcitx5 wayland)之后新装的环境里做这一步,建议先执行一遍sudo pacman -Syu,避免因为软件包版本过旧导致 capstone 的 API 不匹配。capstone 从 4.x 升到 5.x 后,部分常量名变了,旧版源码会编译失败。
3.2 拉取源码与执行 make
仓库克隆下来后,目录结构是这样的,和你在navicat-keygen.zip里看到的顶层文件对应:
git clone https://github.com/xxx/navicat-keygen.git cd navicat-keygen ls -la # 你会看到 navicat-keygen/ 和 navicat-patcher/ 两个子目录分别在两个子目录里执行 make:
cd navicat-keygen make clean && make cd ../navicat-patcher make clean && make编译完成后,navicat-keygen目录下会生成可执行文件navicat-keygen,navicat-patcher目录下生成navicat-patcher。注意,这个工具没有make install步骤,生成的二进制放在当前目录,你需要自己把它们复制到固定位置。我习惯扔到/opt/navicat-patcher/下,避免和 Navicat 安装目录混在一起。
3.3 Makefile 参数的含义与常见编译错误
navicat-keygen的 Makefile 内容不多,核心参数就几个:
CXX ?= g++ CXXFLAGS ?= -std=c++17 -O2 -Wall -Wextra LDFLAGS ?= -lcrypto -lssl-std=c++17是硬性要求,源码里用了std::filesystem和结构化绑定,如果你改成-std=c++14会直接编译失败。-lssl实际上用不到,但保留也不会报错。如果你用的是 clang,需要额外加-I/usr/local/include,因为 clang 的系统头文件搜索路径和 gcc 不一样。
编译报错最常见的是:
fatal error: keystone/keystone.h: No such file or directory这个错在 Arch 上已经很少见,但如果你是从源码编译 keystone 而不是用 pacman 安装,keystone 的头文件会被装在/usr/local/include/keystone/,而 Makefile 只搜索/usr/include/。解决办法是加软链接:
sudo ln -s /usr/local/include/keystone /usr/include/keystone另一个坑是capstone/capstone.h版本不一致,PatchSolution0.cpp里如果用了CS_ARCH_ARM64这类常量,而系统 capstone 是 4.x,会报未声明。Arch 官方源现在是 capstone 5.x,基本能通过。Ubuntu 20.04 的用户更容易遇到这个问题,Arch 反而省心。
编译完成后的第一件事不是直接跑激活,而是验证二进制依赖:
ldd navicat-keygen/navicat-keygen如果输出里有not found,说明缺动态库,最可能的是libkeystone.so或libcapstone.so。Arch 上一般不会出现,但如果用了 yay 装过 AUR 版本,路径可能指向/opt/,需要用LD_LIBRARY_PATH指定。
4. navicat-patcher 补丁注入与 ELF 文件修改细节
navicat-patcher是整个激活流程里最容易被忽略、也最容易失败的一步。它直接修改 Navicat 的可执行文件,把官方 RSA 公钥替换成你自己的公钥。这个操作要编译和运行都通过,补丁才真正生效。
4.1 定位 RSA 公钥在 ELF 中的位置
现代 Linux 下的 Navicat 可执行文件是 ELF 格式,公钥通常存放在.rodata段。navicat-patcher的做法是扫描整个文件的二进制内容,寻找符合 RSA 公钥特征的字节序列。源码里PatchSolution0.cpp就是干这个的,它先用Elf64Interpreter.cpp解析 ELF 段表,拿到.rodata的虚拟地址和文件偏移映射关系,然后在可执行段里搜索BEGIN RSA PUBLIC KEY模式。
// PatchSolution0.cpp 核心流程(简化) bool PatchSolution0::findAndPatch(const std::string& filePath) { auto elf = Elf64Interpreter::parse(filePath); auto rodata = elf.findSection(".rodata"); auto data = rodata.readBytes(); // 搜索多个可能的公钥模板 std::vector<std::string> patterns = { "BEGIN RSA PUBLIC KEY-----\\n", "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A" }; for (auto& pattern : patterns) { auto pos = data.find(pattern); if (pos != std::string::npos) { injectKeyAt(rodata.address + pos); return true; } } return false; }这里的关键是Elf64Interpreter.cpp对节区的解析。Navicat 的二进制经过了某种程度的混淆,.rodata不一定能直接被readelf -S看到标准名字,navicat-patcher会退而求其次,用程序头表的PT_LOAD段做暴力搜索。如果你的版本和某个已知的补丁版本不一致,找到的偏移量就会错位,导致激活失败。
4.2 注入你自己的 RSA 公钥并指定偏移量
执行navicat-patcher前,最好先备份 Navicat 可执行文件。虽然工具会在打补丁前自动备份,但我习惯手动复制一份,因为补丁失败后纯靠工具还原不一定可靠:
cp /opt/navicat-premium15/navicat /opt/navicat-premium15/navicat.bak然后运行:
cd navicat-patcher ./navicat-patcher /opt/navicat-premium15/navicat执行后,正常情况会打印一系列补丁信息,包括 RSA 公钥注入成功的提示、注入位置的偏移量。这个偏移量是八位十六进制数,类似0x1A2B3C4D。你需要把它记录下来,下一步生成激活码时会用到。
如果输出里出现not found或者patch failed,有几种可能:
- Navicat 版本与补丁工具不匹配,
PatchSolutions.hpp里的模板没命中 - 可执行文件已经打过补丁,再次执行找不到原始公钥
- 文件权限不足,无法写入
前两种情况相对少见,第三种最常见。务必确认你对 Navicat 安装目录有写权限,否则 patcher 会静默失败。
补丁成功后再验证一次文件完整性:
readelf -x .rodata /opt/navicat-premium15/navicat | grep -i "RSA PUBLIC KEY"能搜到自定义的公钥文本,说明注入成功。.rodata段是只读的,运行时不会修改,所以补丁是一次性的,但有部分版本的 Navicat 还会在段外做二次校验,遇到这种情况需要看ResourceTraitsOpenssl.hpp,它标记了不同版本的校验点位置,方便在后续版本更新后手动调整。
5. 备份被删除后的恢复策略与序列号激活完整流程
标题里提到的“备份已经被删除的”这个坑,到了这一步就体现出来了。如果你之前把navicat-keygen.zip里编译产生的rsa_private_key.pem当作备份,而它实际上没有被包含在压缩包里,那么重装系统后唯一能补救的方案是:用同一个源码包重新生成密钥对,并重新执行补丁。
5.1 重新生成密钥对与公钥替换
进到navicat-keygen目录,运行:
./navicat-keygen --des 0x1A2B3C4D这里的0x1A2B3C4D是你在第 4 章记录的偏移量。--des参数告诉工具在指定偏移量位置写入新生成的公钥。如果不加这个参数,工具会默认使用预置的公钥,但这个公钥和你的私钥不匹配,激活码无法通过验证。
执行后,工具会做两件事:
- 生成新的
rsa_private_key.pem文件(如果已存在则覆盖) - 把对应的公钥写入到 Navicat 可执行文件指定偏移
此时需要再跑一次navicat-patcher,因为--des只是写了公钥数据,没有更新 ELF 的校验信息。正确顺序是先跑navicat-patcher注入官方案例公钥,再跑navicat-keygen --des替换成自己的公钥。如果你顺序搞反,patcher 找不到可替换的官方公钥,会直接报错。
注意:每次重新生成
rsa_private_key.pem后,旧的激活码全部失效,需要重新注册。所以这台机器上已经激活过的数据库连接不会受影响,但下次重装时又得重复一遍。
5.2 生成序列号与请求码的完整交互
密钥准备好后,进入注册流程。运行:
./navicat-keygen工具会进入交互模式,先要求选择产品类型和语言:
[*] Navicat Premium 15 [*] Select product: 0 [*] Select language: 0 [*] Enter your name: zhangsan [*] Enter your organization: dev-team产品类型和语言代码对应关系可以在源码的main.cpp里看到,0 表示 Premium 15,语言 0 表示 Simplified Chinese,1 表示 English。姓名和组织名会作为许可证信息的一部分写入激活码,建议用英文,避免编码问题。
确认后,工具会打印类似下面的序列号:
NAVN-MN3K-3Z7E-JK9W把这个序列号复制到 Navicat 的注册界面填进去,点击激活后,Navicat 会生成一个请求码,终端里这时会变成等待输入的状态。
然后把请求码粘贴到终端里按回车,工具会输出激活码,通常是两到三行:
Activation Code: VK7Q-MN2J-K3...(省略)把完整的激活码复制回 Navicat 注册窗口。如果激活码提示无效,优先检查请求码里有没有混入换行符或多余空格。Linux 终端粘贴时经常会在末尾带个\r,导致解码失败。
5.3 备份被删除后的资料抢救与恢复建议
如果你原来的rsa_private_key.pem是随 zip 一起下载的,而 zip 本身被删了,那确实没法恢复旧的私钥。这时方案是让旧密钥“退休”,按 5.1 的流程重新配对。
在 Arch 上,我还会多做一步:把激活流程里需要的文件打成一个新的 tar 包,存到两个地方——本地~/backup/和远程 Git 私有仓库。打包内容不只是源码,还包括编译产物和生成的 key:
mkdir -p ~/backup/navicat-activate cp -r navicat-keygen navicat-patcher ~/backup/navicat-activate/ cp navicat-keygen/rsa_private_key.pem ~/backup/navicat-activate/ cd ~ && tar -czf navicat-activate.tar.gz navicat-activate/ && rm -rf navicat-activate/这样打包出来的东西,即使navicat-keygen.zip备份已经被删除的,下次重装照样能用。要注意的是,rsa_private_key.pem必须和打过补丁的 Navicat 可执行文件配套,两者必须同步备份,否则还是白搭。
6. 进阶:把整个激活过程脚本化并反向检验补丁注入结果
手动执行上面四章的操作流程,完成一次激活大约需要五到十分钟,而且容易在复制粘贴时出错。把激活流程压缩成两个脚本,可以大幅降低操作错误。同时,补丁注入完成后,用几条命令就能验证是否生效,不用等运行时报错。
6.1 一键备份脚本与恢复脚本
先写一个备份脚本,把 Navicat 本体、激活工具和密钥一次性归档:
#!/bin/bash # save-navicat-state.sh set -euo pipefail BACKUP_DIR="${HOME}/navicat-backup" STAMP=$(date +%Y%m%d-%H%M%S) mkdir -p "${BACKUP_DIR}/${STAMP}" # 备份 Navicat 可执行文件与相关配置 cp /opt/navicat-premium15/navicat "${BACKUP_DIR}/${STAMP}/" cp -r /opt/navicat-premium15/plugins "${BACKUP_DIR}/${STAMP}/" 2>/dev/null || true # 备份激活工具链 cp -r "${HOME}/src/navicat-keygen" "${BACKUP_DIR}/${STAMP}/navicat-keygen" cp -r "${HOME}/src/navicat-patcher" "${BACKUP_DIR}/${STAMP}/navicat-patcher" cp "${HOME}/src/navicat-keygen/rsa_private_key.pem" "${BACKUP_DIR}/${STAMP}/" # 用 tar 打包,避免散落文件被误删 cd "${BACKUP_DIR}" && tar -czf "navicat-${STAMP}.tar.gz" "${STAMP}" && rm -rf "${STAMP}" echo "Backup saved to ${BACKUP_DIR}/navicat-${STAMP}.tar.gz"脚本里用了set -euo pipefail,任何一条命令失败就立即退出,避免把损坏的文件归档进去。2>/dev/null || true是为了处理 plugins 目录不存在的情况,非核心文件缺失不影响激活。恢复时直接解压到对应路径即可。
这里注意,脚本中的cp -r在复制目录时如果目标存在会合并,所以恢复前建议先确认目标目录是干净的。恢复命令就一行:
tar -xzf navicat-<时间戳>.tar.gz -C /tmp && cd /tmp/navicat-<时间戳> && ./restore.sh实际上我没有写 restore.sh,你可以在解压后手动把文件放回去,或者按下面的方式组织成一个函数。
6.2 用readelf和strings验证补丁注入结果
补丁打完后不急着启动 Navicat,先用系统自带的工具做一次逆向验证。readelf -S能看到 ELF 的段表结构,确认 Navicat 的二进制没有被破坏:
readelf -S /opt/navicat-premium15/navicat | grep -E '\.(rodata|text|data)'三条段信息都能正常打印,说明 ELF 头结构完好。接着用strings搜索公钥特征:
strings /opt/navicat-premium15/navicat | grep "RSA PUBLIC KEY" | head -3如果注入的是 base64 格式的 DER 公钥,搜索 5 到 10 行能看到的特征文本可能是这样的:
-----BEGIN RSA PUBLIC KEY----- MIIBCgKCAQEAxFRNfB8P...(省略) -----END RSA PUBLIC KEY-----这段文本的映射偏移可以用grep -abo拿到:
grep -abo "BEGIN RSA PUBLIC KEY" /opt/navicat-premium15/navicat | head -1输出类似0x2c8a00,这个偏移量就是你后续要做 offset 验证的依据。如果偏移量和navicat-patcher打印的不一致,说明有两处公钥,其中一处可能藏在别的段里,需要进一步排查。Navicat 15 的某些版本会在.data段额外放一份公钥用于运行时校检,所以即便.rodata替换成功了,程序启动时仍可能检测到license section不匹配而拒绝运行。
6.3 快速重置激活状态的技巧
如果你后续想解除激活,换一个序列号,不需要重装整个 Navicat。删除配置文件里的许可证记录即可,Navicat 在 Linux 下的配置文件位置比较隐蔽,常见路径是~/.config/navicat/Premium/下的.json文件。
find ~/.config/navicat -type f -name "*.json" -exec ls -la {} \;找到类似preferences.json的文件,把其中有关 serial 和 registration 的内容删掉,或者直接删除整个 Premium 配置目录。再次启动 Navicat 时会回到未注册状态。这个方法在 Arch 上屡试不爽,而且不影响已保存的连接配置。但要注意,如果你用的是--des方式激活,回退时会要求输入旧密钥,旧密钥如果有备份就覆盖回去,没有备份就把 Navicat 的二进制还原成打过补丁的版本即可。
本文还有配套的精品资源,点击获取