当前位置:首页 > 工具 > 正文内容

使用Python脚本解密Navicat保存的数据库连接密码

访客 工具 2026年6月24日 1

在数据库管理过程中,Navicat是一款广泛使用的工具。然而,有时用户可能会忘记保存在Navicat中的数据库连接密码,或者在迁移配置时发现这些密码已被加密且无法直接读取。本文将介绍Navicat密码的加密原理,并提供一个Python脚本来帮助用户找回这些遗忘的密码。

Navicat密码加密机制

Navicat为了保护用户数据的安全,会对存储的密码进行加密。了解其加密方式是找回密码的关键。

加密算法与固定密钥

Navicat采用AES-128-CBC(Cipher Block Chaining)加密模式。这是一种对称加密算法,意味着加密和解密使用相同的密钥。Navicat的加密过程中,使用的密钥(Key)和初始化向量(Initialization Vector, IV)是固定的:


KEY = b'libcckeylibcckey'  # 16字节的AES密钥
IV = b'libcciv libcciv '   # 16字节的初始化向量
    

由于密钥和IV是公开的,任何了解这些信息的人都可以解密Navicat加密的密码。虽然这并非最安全的做法,但它为密码恢复提供了便利。

密码加密流程

当你在Navicat中保存一个数据库连接时,其密码的处理流程如下:

  1. 将明文密码转换为UTF-8编码的字节序列。
  2. 使用PKCS7填充机制处理字节序列,确保其长度能被AES块大小整除。
  3. 使用AES-128-CBC算法、上述固定密钥和IV对填充后的数据进行加密。
  4. 将加密后的字节序列转换为大写的十六进制字符串进行存储。

需要注意的是,尽管此方法可以找回密码,但也意味着导出的Navicat连接配置文件(.ncx文件)中包含了可被解密的数据,因此应妥善保管这些文件。

获取加密密码

在进行解密操作前,需要先从Navicat的配置文件中提取加密后的密码字符串。

导出连接配置

  1. 启动Navicat。
  2. 选择菜单栏中的"文件" -> "导出连接"。
  3. 在弹出的窗口中,选择包含需要恢复密码的数据库连接。
  4. 将连接导出为 .ncx 文件格式。

定位加密密码字符串

使用任何文本编辑器打开导出的 .ncx 文件。在文件中搜索 Password 标签,你将找到类似以下的加密字符串:


<Connection ...>
    <Password>A1B2C3D4E5F678901234567890ABCDEF</Password>
    ...
</Connection>
    

<Password> 标签内的十六进制字符串就是待解密的加密密码。

Python解密脚本实现

下面是一个Python脚本,用于解密从Navicat导出的密码。

安装必要的库

首先,需要安装 cryptography 库。如果尚未安装,请在终端或命令提示符中运行以下命令:


pip install cryptography
    

编写解密函数

创建一个Python文件(例如 navicat_decrypt.py),并添加以下代码:


from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
import binascii
import xml.etree.ElementTree as ET

# Navicat固定的AES密钥和初始化向量
KEY = b'libcckeylibcckey'
IV = b'libcciv libcciv '

def decrypt_navicat_password(encrypted_password_hex):
    """
    解密Navicat加密的密码字符串。

    Args:
        encrypted_password_hex: Navicat保存的十六进制大写加密密码字符串。

    Returns:
        解密后的明文密码字符串,如果解密失败则返回None。
    """
    try:
        # 将十六进制字符串转换为字节
        encrypted_bytes = binascii.unhexlify(encrypted_password_hex)

        # 创建AES-128-CBC解密器
        cipher = Cipher(algorithms.AES(KEY), modes.CBC(IV), backend=default_backend())
        decryptor = cipher.decryptor()

        # 执行解密
        decrypted_padded_bytes = decryptor.update(encrypted_bytes) + decryptor.finalize()

        # PKCS7解填充
        # 注意:Navicat的填充可能与标准的PKCS7略有不同,这里尝试标准解填充
        # 如果标准解填充不成功,可能需要根据实际填充字节进行调整
        # PKCS7填充的标准是,填充的字节值等于填充的字节数
        # 例如,如果需要填充3个字节,则每个填充字节的值都是0x03
        # 查找最后一个字节的值,该值即为填充的字节数
        padding_len = decrypted_padded_bytes[-1]
        
        # 验证填充是否正确(可选,但推荐)
        # 检查最后padding_len个字节是否都等于padding_len
        is_correct_padding = all(p == padding_len for p in decrypted_padded_bytes[-padding_len:])
        
        if not is_correct_padding:
             # 尝试另一种常见的填充处理方式,有时密文末尾会有额外的NULL字节
             # 这种情况在Navicat中不常见,但可以作为备选
             while decrypted_padded_bytes.endswith(b'\x00'):
                 decrypted_padded_bytes = decrypted_padded_bytes[:-1]
             # 如果依然不成功,返回错误
             # raise ValueError("Invalid padding") # 抛出异常会中断执行,这里选择返回None
             return None # 或者直接返回None表示解密失败

        # 移除填充
        decrypted_bytes = decrypted_padded_bytes[:-padding_len]

        # 将解密后的字节串解码为UTF-8字符串
        return decrypted_bytes.decode('utf-8')

    except (binascii.Error, ValueError, TypeError) as e:
        print(f"解密失败: {e}")
        return None
    except Exception as e:
        print(f"发生未知错误: {e}")
        return None

def find_and_decrypt_passwords_in_ncx(ncx_file_path):
    """
    解析.ncx文件,找到所有加密密码并尝试解密。

    Args:
        ncx_file_path: .ncx配置文件的路径。

    Returns:
        一个字典,键为连接名称,值为解密后的密码。
    """
    try:
        tree = ET.parse(ncx_file_path)
        root = tree.getroot()
        
        connections_data = {}
        
        # 遍历所有Connection节点
        for connection_node in root.findall('.//Connection'):
            connection_name_element = connection_node.find('Name')
            password_element = connection_node.find('Password')
            
            if connection_name_element is not None and password_element is not None:
                connection_name = connection_name_element.text
                encrypted_password = password_element.text
                
                if encrypted_password:
                    decrypted_password = decrypt_navicat_password(encrypted_password)
                    if decrypted_password:
                        connections_data[connection_name] = decrypted_password
                    else:
                        connections_data[connection_name] = "[解密失败]"
                else:
                    connections_data[connection_name] = "[无密码]"
            elif connection_name_element is not None:
                 connections_data[connection_name_element.text] = "[无密码字段]"

        return connections_data

    except FileNotFoundError:
        print(f"错误: 文件未找到 - {ncx_file_path}")
        return None
    except ET.ParseError:
        print(f"错误: 无法解析XML文件 - {ncx_file_path}")
        return None
    except Exception as e:
        print(f"处理文件时发生错误: {e}")
        return None

if __name__ == "__main__":
    # 示例用法:
    # 1. 替换 'your_connections.ncx' 为你实际导出的.ncx文件路径
    # 2. 脚本会打印出找到的连接名称和对应的明文密码
    
    ncx_file = 'your_connections.ncx' # !!! 请将这里替换为你的.ncx文件路径 !!!
    
    print(f"正在从文件 '{ncx_file}' 中查找并解密密码...\n")
    
    decrypted_passwords = find_and_decrypt_passwords_in_ncx(ncx_file)
    
    if decrypted_passwords:
        if not decrypted_passwords:
             print("在文件中未找到任何数据库连接配置。")
        else:
            print("="*30)
            print("  解密结果:")
            print("="*30)
            for name, pwd in decrypted_passwords.items():
                print(f"连接名: {name:<25} 密码: {pwd}")
            print("="*30)
    else:
        print("未能成功处理.ncx文件,请检查文件路径和格式。")

    # 也可以直接测试单个加密密码
    # test_encrypted_pwd = "CFCB9D0434693474F8C70FC796C7F0F3" # 示例加密密码
    # decrypted_single = decrypt_navicat_password(test_encrypted_pwd)
    # print(f"\n测试单个密码解密:")
    # print(f"加密: {test_encrypted_pwd}")
    # print(f"解密: {decrypted_single}")
    

如何使用脚本

  1. 将上面提供的Python代码保存为一个 .py 文件(例如 navicat_decrypt.py)。
  2. 确保你已经按照"准备工作"中的步骤导出了Navicat连接配置为 .ncx 文件。
  3. 修改脚本中的 ncx_file = 'your_connections.ncx' 这一行,将 'your_connections.ncx' 替换为你实际的 .ncx 文件路径。
  4. 在终端或命令提示符中,导航到保存脚本的目录,然后运行脚本:python navicat_decrypt.py
  5. 脚本将输出找到的所有数据库连接名称以及它们对应的明文密码。如果某个密码未能成功解密,将显示 [解密失败]

通过这个脚本,你可以轻松找回遗忘的Navicat连接密码,从而更高效地管理你的数据库。

标签: Navicat

相关文章

Trojan服务器搭建与配置

一、整体架构(先对齐认知)Clash Meta (PC / iOS / Android)        ↓ TLS   Trojan Server (443)        ↓     InternetTrojan 的核心是: TLS + HTTPS 流量伪装 看起来像正常网站 非常适合...

Tailscale 的详细用法

Tailscale 是一种基于 WireGuard 协议 的 零配置 VPN(虚拟私有网络)服务,让设备之间能够 安全、加密地直接连接,就像它们在同一个本地网络一样。它的核心特点是 简单、安全、跨平台。Tailscale 非常适合 没有公网 IP、两台电脑不在同一局域网 的场景。 简单来说,Tailscale 是什么?Tailscale 是一款让你的各种设备(电脑、服务器、手机...

Clash Tun 模式 导致 爱快(iKuai SD-Wan)内网域名无法访问

一、Clash  DNS 配置dns:  enable: true  listen: 0.0.0.0:53  ipv6: true  enhanced-mode: redir-host  nameserver:    - 223.5.5.5    - 223.6.6.6iKuai 内网域名 ...

深入解析Node.js运行环境与异步I/O架构

深入解析Node.js运行环境与异步I/O架构

核心定义与价值Node.js本质上是一个JavaScript运行环境,而非编程语言或应用框架。它赋予了JavaScript脱离浏览器在服务端、命令行工具及网络应用中执行的能力。其核心意义在于:用单一语言打通前后端开发壁垒。基于事件驱动与非阻塞I/O的架构特性,Node.js在处理API网关、实时通信及微服务等I/O密集型场景时表现卓越,已成为现代后端工程的主流选择。浏览器沙箱限制1995年Java...

ADO.NET SQL参数化查询的最佳实践

在 ADO.NET 中执行 SQL 查询时,参数化查询是一种关键的安全措施和性能优化手段。它通过将 SQL 命令和用户提供的数据分开处理,有效防止了 SQL 注入攻击,并有助于数据库缓存执行计划。下面总结了几种常用的参数化查询方式。 1. 使用 SqlParameter 对象(推荐) 这是最推荐的参数化查询方式。通过显式创建 SqlParameter 对象,您可以精确控制参数的类...

基于ELK的日志集中化分析系统搭建

构建统一日志管理平台的必要性 在分布式架构中,各服务节点独立运行,日志分散存储于不同主机。传统通过命令行工具如grep、awk逐个检索日志的方式,在数据量庞大时效率极低,难以实现快速定位问题。为提升运维效率,需建立集中式日志处理体系,具备日志采集、传输、存储、分析与告警能力。 ELK技术栈核心组件解析 Elasticsearch:分布式搜索引擎,支持全文检索、实时数据分析和高可用集群部署,...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。