安全查看Navicat数据库密码实践 2025.6.20
引言1、Navicat数据库连接密码查看思路1.1 借助外力,灵活自如2.2 内生动力,秀出强大
2、具体实现2.0 Navicat导出数据库连接文件2.1 在线工具查看(方便快捷)2.1.1 Navicat.html(不十分推荐使用)2.1.2 navicat-password(比较不错)
2.2 本地查看(安全可靠)2.2.1 Php语言实现(可在线运行)2.2.1.1 源码2.2.1.2 运行结果
2.2.2 Nodejs后端代码实现(本地运行)2.2.2.1 源码2.2.2.2 运行结果
2.2.3 单个HTML实现(本地运行,推荐使用)2.2.3.1 源码2.2.3.2 运行结果
3. 小结
引言
在大数据、云计算、AI技术发展如此迅猛的时代,作为软件开发者、数据处理人员或者后台运维人员,我们往往需要连接各种各样的数据库(如MySQL、PostgreSQL、MongoDB、Oracle、SQL Server、SQLite3等)进行增删改查、导入导出等操作。在平时的学习、研究与工作中,每个人或多或少会面临多个不同的系统平台软件,需要对相关数据库的IP地址、端口号、用户名、密码进行统一存储,以便日常工作管理中的及时连接,进行问题诊断、日志分析、故障排查等操作,从而提高工作效率,优化工作节奏。
想必小伙伴们大多会用到Navicat这款强大的数据库管理软件,当我们第一次使用此软件能正常连接数据库并选择保存密码时,软件本身便有其独特的密码管理方式,但不知大家都是如何保存数据库密码的呢?不妨看看以下几种常用的保存方式: 【1】保存到个人的笔记资料文件当中,如NotePad、Word、OneNote、Excel、Git及Email等; 【2】OA业务化归档管理,必要时进行个人权限申请,进行快速查找; 【3】不容小觑的强大记忆力,凭借着天生我材必有用的迷之自信,坚定不移走这条路线,必要时将短期记忆修炼为长期记忆👍👍👍。
当自己面临数据库密码难以找回且又急于连接数据库进行快速操作同时又束手无策时,没必要那么忧伤和失望,千万别画地为牢,唯有秉持我不入地狱谁入地狱、前人踩过我踩的坑的乐观心态。每个人有每个人处理问题的方式和办法,正所谓八仙过海、各显神通。只需要鼓起勇气从网上寻找解决思路,再接再厉,持之以恒向热心的同事和网友求助就好了,这样大问题变小问题,小问题不值一提,问题往往不就迎刃而解了吗?
1、Navicat数据库连接密码查看思路
话不多说,开门见山。Navicat中的数据库连接密码查看思路主要有两点:(1)利用外部现有工具/代码,有效可执行,能满足现有需求即可;(2)本地搭建运行环境,尝试利用参考代码改写调试执行,得到正确结果,保证安全可靠。基于不同的出发点,用户还需综合考虑安全性、高效性和灵活性等特点,决策采用适合的思路来达到查看数据库连接密码的目的。
1.1 借助外力,灵活自如
尽可能参考互联网上的技术资料、前人经验、贴吧论坛、开源仓库、成熟工具,这就要求个人必须集思广益,海纳百川,本着“不管是白猫还是黑猫,能抓住耗子就是好猫”的原则,同时怀抱谦虚的态度和耐心的品质,去努力进行探索,勇敢尝试,结果往往还会出人意料,但并非一劳永逸!
2.2 内生动力,秀出强大
在外部力量难以被内部完全吸收接纳时,可以考虑取其精华、剔其糟粕,沉下心来,抱有“不破楼兰誓不还”的坚定决心,展现强大的实践能力,去真真正正地解决实际问题,敢于迎难而上,过程必然痛苦,但也是一种历练,尤其在究其本质、抓住规律之后,内心的坦然难以言表,曾经的回忆难以忘怀,那一刻的喜悦刻骨铭心!
2、具体实现
一旦有了清晰明确的思路,具体到个人行动上后,如同有了一座灯塔已然照亮前行之路,剩下的就需要脚踏实地,内化于心,外化于行,制定具体的行动方案并加以实施。言归正传,查看Navicat数据库连接密码的具体实现方式分为两种:在线工具查看和本地查看。
2.0 Navicat导出数据库连接文件
Navicat导出连接文件
打开Navicat,点击文件->导出连接,勾选某个数据库后选择导出路径,务必勾选导出密码后点击确定按钮,导出后的数据库连接文件connections.ncx内容,从中可以看到密文密码为A26C4BB8258A03A90FC79F8195CF269EAADB7A7A1D830D648E4F435E27996E08。
2.1 在线工具查看(方便快捷)
两个在线查看Navicat数据库连接密码的工具:Navicat.html 和 navicat-password,其中前者需要导入从Navicat导出带有密码的连接文件——connections.ncx,而后者仅需将文件中的Password粘贴至文本框进行转换接口看到明文。
2.1.1 Navicat.html(不十分推荐使用)
浏览器打开Navicat.html,选择版本号为15,点击选择文件按钮选择本地数据连接文件后点击解析密码,解析结果便会自动展示在下方表格。可以看到,此种方式解析结果十分详细,包含详细的数据连接信息,切勿将带有公网ip和开放端口的连接文件进行上传哦!!!
在线Navicat.html查看数据连接密码
2.1.2 navicat-password(比较不错)
浏览器打开navicat-password,此工具源自于热心大哥在Gitee上的开源仓库地址,可以实现数据库连接密码的明文加密与密文解密,快捷方便,无需上传数据连接文件,可以推荐学习使用。
在线navicat-password查看数据连接密码
Gitee上的开源仓库(Navicat密码加密解密)
2.2 本地查看(安全可靠)
下面会介绍Php、Nodejs和Html三种语言实现Navicat数据库连接密码本地查看的具体方法,个人实践记录与各位分享。
2.2.1 Php语言实现(可在线运行)
只需使用浏览器打开php 在线工具网站,在左侧编辑框中粘贴以下代码后点击中间顶部的【运行代码】按钮,随后运行结果便会展示在右侧的文本框中。(注:大家也可以本地搭建php开发环境,进行源码编译运行)
2.2.1.1 源码
class NavicatPassword
{
protected $version = 0;
protected $aesKey = 'libcckeylibcckey';
protected $aesIv = 'libcciv libcciv ';
protected $blowString = '3DC5CA39';
protected $blowKey = null;
protected $blowIv = null;
public function __construct($version = 12)
{
$this->version = $version;
$this->blowKey = sha1('3DC5CA39', true);
$this->blowIv = hex2bin('d9c7c3c8870d64bd');
}
public function encrypt($string)
{
$result = FALSE;
switch ($this->version) {
case 11:
$result = $this->encryptEleven($string);
break;
case 12:
$result = $this->encryptTwelve($string);
break;
default:
break;
}
return $result;
}
protected function encryptEleven($string)
{
$round = intval(floor(strlen($string) / 8));
$leftLength = strlen($string) % 8;
$result = '';
$currentVector = $this->blowIv;
for ($i = 0; $i < $round; $i++) {
$temp = $this->encryptBlock($this->xorBytes(substr($string, 8 * $i, 8), $currentVector));
$currentVector = $this->xorBytes($currentVector, $temp);
$result .= $temp;
}
if ($leftLength) {
$currentVector = $this->encryptBlock($currentVector);
$result .= $this->xorBytes(substr($string, 8 * $i, $leftLength), $currentVector);
}
return strtoupper(bin2hex($result));
}
protected function encryptBlock($block)
{
return openssl_encrypt($block, 'BF-ECB', $this->blowKey, OPENSSL_RAW_DATA|OPENSSL_NO_PADDING);
}
protected function decryptBlock($block)
{
return openssl_decrypt($block, 'BF-ECB', $this->blowKey, OPENSSL_RAW_DATA|OPENSSL_NO_PADDING);
}
protected function xorBytes($str1, $str2)
{
$result = '';
for ($i = 0; $i < strlen($str1); $i++) {
$result .= chr(ord($str1[$i]) ^ ord($str2[$i]));
}
return $result;
}
protected function encryptTwelve($string)
{
$result = openssl_encrypt($string, 'AES-128-CBC', $this->aesKey, OPENSSL_RAW_DATA, $this->aesIv);
return strtoupper(bin2hex($result));
}
public function decrypt($string)
{
$result = FALSE;
switch ($this->version) {
case 11:
$result = $this->decryptEleven($string);
break;
case 12:
$result = $this->decryptTwelve($string);
break;
default:
break;
}
return $result;
}
protected function decryptEleven($upperString)
{
$string = hex2bin(strtolower($upperString));
$round = intval(floor(strlen($string) / 8));
$leftLength = strlen($string) % 8;
$result = '';
$currentVector = $this->blowIv;
for ($i = 0; $i < $round; $i++) {
$encryptedBlock = substr($string, 8 * $i, 8);
$temp = $this->xorBytes($this->decryptBlock($encryptedBlock), $currentVector);
$currentVector = $this->xorBytes($currentVector, $encryptedBlock);
$result .= $temp;
}
if ($leftLength) {
$currentVector = $this->encryptBlock($currentVector);
$result .= $this->xorBytes(substr($string, 8 * $i, $leftLength), $currentVector);
}
return $result;
}
protected function decryptTwelve($upperString)
{
$string = hex2bin(strtolower($upperString));
return openssl_decrypt($string, 'AES-128-CBC', $this->aesKey, OPENSSL_RAW_DATA, $this->aesIv);
}
};
//需要指定版本两种,11或12
//$navicatPassword = new NavicatPassword(11);
//这里我指定的12的版本,原先指定的11,执行之后的密码是乱码
$navicatPassword = new NavicatPassword(12);
$encode = $navicatPassword->encrypt('pgTestPassword2025');
echo "加密结果:".$encode."\n";
//解密
$decode = $navicatPassword->decrypt('A26C4BB8258A03A90FC79F8195CF269EAADB7A7A1D830D648E4F435E27996E08');
echo "解密结果:".$decode."\n";
?>
2.2.1.2 运行结果
php运行数据库密码加解密结果
2.2.2 Nodejs后端代码实现(本地运行)
在php源码基础上,作者充分利用百度AI实现了Nodejs版的后端代码,同样可以实现数据库连接密码的加解密,需要在本地安装Nodejs软件,具备基础的编译环境后,将以下代码保存为Nodejs-Navicat.js文件后便可利用Nodejs编译运行,安全可靠。
2.2.2.1 源码
Nodejs-Navicat.js文件具体内容:
const crypto = require('crypto');
class NavicatPassword {
constructor(version = 12) {
this.version = version;
this.aesKey = 'libcckeylibcckey';
this.aesIv = 'libcciv libcciv ';
this.blowString = '3DC5CA39';
this.blowKey = crypto.createHash('sha1').update('3DC5CA39').digest();
this.blowIv = Buffer.from('d9c7c3c8870d64bd', 'hex');
}
encrypt(string) {
let result = false;
switch (this.version) {
case 11:
result = this.encryptEleven(string);
break;
case 12:
result = this.encryptTwelve(string);
break;
default:
break;
}
return result;
}
encryptEleven(string) {
const round = Math.floor(string.length / 8);
const leftLength = string.length % 8;
let result = Buffer.alloc(0);
let currentVector = this.blowIv;
for (let i = 0; i < round; i++) {
const temp = this.encryptBlock(
this.xorBytes(
Buffer.from(string.substr(8 * i, 8)),
currentVector
)
);
currentVector = this.xorBytes(currentVector, temp);
result = Buffer.concat([result, temp]);
}
if (leftLength) {
currentVector = this.encryptBlock(currentVector);
result = Buffer.concat([
result,
this.xorBytes(
Buffer.from(string.substr(8 * round)),
currentVector
)
]);
}
return result.toString('hex').toUpperCase();
}
encryptBlock(block) {
const cipher = crypto.createCipheriv('bf-ecb', this.blowKey, null);
cipher.setAutoPadding(false);
return Buffer.concat([cipher.update(block), cipher.final()]);
}
decryptBlock(block) {
const decipher = crypto.createDecipheriv('bf-ecb', this.blowKey, null);
decipher.setAutoPadding(false);
return Buffer.concat([decipher.update(block), decipher.final()]);
}
xorBytes(str1, str2) {
const result = Buffer.alloc(str1.length);
for (let i = 0; i < str1.length; i++) {
result[i] = str1[i] ^ str2[i];
}
return result;
}
encryptTwelve(string) {
const cipher = crypto.createCipheriv(
'aes-128-cbc',
this.aesKey,
this.aesIv
);
return Buffer.concat([
cipher.update(string, 'utf8'),
cipher.final()
]).toString('hex').toUpperCase();
}
decrypt(string) {
let result = false;
switch (this.version) {
case 11:
result = this.decryptEleven(string);
break;
case 12:
result = this.decryptTwelve(string);
break;
default:
break;
}
return result;
}
decryptEleven(upperString) {
const string = Buffer.from(upperString, 'hex');
const round = Math.floor(string.length / 8);
const leftLength = string.length % 8;
let result = Buffer.alloc(0);
let currentVector = this.blowIv;
for (let i = 0; i < round; i++) {
const encryptedBlock = string.slice(8 * i, 8 * (i + 1));
const temp = this.xorBytes(
this.decryptBlock(encryptedBlock),
currentVector
);
currentVector = this.xorBytes(currentVector, encryptedBlock);
result = Buffer.concat([result, temp]);
}
if (leftLength) {
currentVector = this.encryptBlock(currentVector);
result = Buffer.concat([
result,
this.xorBytes(string.slice(8 * round), currentVector)
]);
}
return result.toString('utf8');
}
decryptTwelve(upperString) {
const string = Buffer.from(upperString, 'hex');
const decipher = crypto.createDecipheriv(
'aes-128-cbc',
this.aesKey,
this.aesIv
);
return Buffer.concat([
decipher.update(string),
decipher.final()
]).toString('utf8');
}
}
// 使用示例
const navicatPassword = new NavicatPassword(12);
const encoded = navicatPassword.encrypt('pgTestPassword2025');
console.log("加密结果:", encoded);
const decoded = navicatPassword.decrypt('A26C4BB8258A03A90FC79F8195CF269EAADB7A7A1D830D648E4F435E27996E08');
console.log("解密结果:", decoded);
2.2.2.2 运行结果
Nodejs后端代码运行数据库密码加解密结果
2.2.3 单个HTML实现(本地运行,推荐使用)
当然,在Nodejs源码基础上,结合前段开发经验与浏览器宿主环境优势,尝试编写了单个HTMLNavicat数据库连接密码加解密的代码,充分借鉴上述方法,取长补短后,经测试同样十分安全有效、快速可靠。
2.2.3.1 源码
HTML-Navicat.html文件中的具体内容:
Navicat16导出密码 (经初步测试目前可以支持 PostgreSQL、MySQL、MongoDB 和 SQLite3 等数据库)
说明:先在Navicat中导出密码:文件 -> 导出连接 -> 勾选【导出密码】,然后使用记事本打开导出后的密码文件(如 connections.ncx ),查看想要解密的 Password
connection.ncx文件示例内容:
使用工具:
document.getElementById('sample').innerText = `
`
window.console.log("%c参考Navicat密码查看工具:" + ":http://v2.admin.dzsjshop.top/Navicat.html", "color:red")
window.console.log("%c本工具为离线运行,安全可靠,请放心使用:" + window.location, "color:green")
window.console.log("%c源码由 jing_zhong 利用AI工具 https://chat.baidu.com/search 于 2025.6.20 反复测试改写而来,参考-》如何看navicat数据库连接的密码:" + 'https://blog.csdn.net/qq_42007843/article/details/148141323', "color:green")
let curType = '解密'
function showAlert(radio) {
document.getElementById('box').innerHTML = ''
document.getElementById('frame').value = ''
if(radio.checked) {
curType = radio.value
if(curType === '加密')
document.getElementById('frame').setAttribute('placeholder','请输入需要加密的明文密码')
else if(curType === '解密')
document.getElementById('frame').setAttribute('placeholder','请输入需要解密的密文密码')
}
}
function Buffer_From(hexString, type)
{
const res = new Uint8Array(
hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16))
);
return res
}
function EncryptBlock(block, blow_Key, options) {
let blowKey = CryptoJS.enc.Utf8.parse(blow_Key);
const wordArray = CryptoJS.enc.Hex.parse(block.toString('hex'));
const encrypted = CryptoJS.Blowfish.encrypt(
wordArray,
blowKey,
options
);
return Buffer.from(encrypted.toString(), 'base64');
}
function DecryptBlock(block, blow_Key) {
let blowKey = CryptoJS.enc.Utf8.parse(blow_Key);
const ciphertext = CryptoJS.enc.Base64.parse(block.toString('base64'));
const decrypted = CryptoJS.Blowfish.decrypt(
{ ciphertext: ciphertext },
blowKey,
options
);
return Buffer.from(decrypted.toString(CryptoJS.enc.Hex), 'hex');
}
class NavicatPassword {
constructor(version = 12) {
this.version = version;
this.aesKey = 'libcckeylibcckey';
this.aesIv = 'libcciv libcciv ';
this.blowString = '3DC5CA39';
this.blowKey = CryptoJS.SHA1("3DC5CA39").toString(CryptoJS.enc.Latin1);
this.blowIv = Buffer_From('d9c7c3c8870d64bd', 'hex');
}
encrypt(string) {
let result = false;
switch (this.version) {
case 11:
result = this.encryptEleven(string);
break;
case 12:
result = this.encryptTwelve(string);
break;
default:
break;
}
return result;
}
encryptEleven(string) {
const round = Math.floor(string.length / 8);
const leftLength = string.length % 8;
let result = Buffer.alloc(0);
let currentVector = this.blowIv;
for (let i = 0; i < round; i++) {
const temp = this.encryptBlock(
this.xorBytes(
Buffer.from(string.substr(8 * i, 8)),
currentVector
)
);
currentVector = this.xorBytes(currentVector, temp);
result = Buffer.concat([result, temp]);
}
if (leftLength) {
currentVector = this.encryptBlock(currentVector);
result = Buffer.concat([
result,
this.xorBytes(
Buffer.from(string.substr(8 * round)),
currentVector
)
]);
}
return result.toString('hex').toUpperCase();
}
encryptBlock(block) {
let options = {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.NoPadding
};
return EncryptBlock(block, this.blowKey, options);
}
decryptBlock(block) {
let options = {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.NoPadding
};
return DecryptBlock(block, this.blowKey, options)
}
xorBytes(str1, str2) {
const result = Buffer.alloc(str1.length);
for (let i = 0; i < str1.length; i++) {
result[i] = str1[i] ^ str2[i];
}
return result;
}
encryptTwelve(string) {
let key = CryptoJS.enc.Utf8.parse(this.aesKey);
let iv = CryptoJS.enc.Utf8.parse(this.aesIv);
const encrypted = CryptoJS.AES.encrypt(
CryptoJS.enc.Utf8.parse(string),
key,
{
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}
);
return encrypted.ciphertext.toString().toUpperCase();
}
decrypt(string) {
let result = false;
switch (this.version) {
case 11:
result = this.decryptEleven(string);
break;
case 12:
result = this.decryptTwelve(string);
break;
default:
break;
}
return result;
}
decryptEleven(upperString) {
const string = Buffer_From(upperString, 'hex');
const round = Math.floor(string.length / 8);
const leftLength = string.length % 8;
let result = Buffer.alloc(0);
let currentVector = this.blowIv;
for (let i = 0; i < round; i++) {
const encryptedBlock = string.slice(8 * i, 8 * (i + 1));
const temp = this.xorBytes(
this.decryptBlock(encryptedBlock),
currentVector
);
currentVector = this.xorBytes(currentVector, encryptedBlock);
result = Buffer.concat([result, temp]);
}
if (leftLength) {
currentVector = this.encryptBlock(currentVector);
result = Buffer.concat([
result,
this.xorBytes(string.slice(8 * round), currentVector)
]);
}
return result.toString('utf8');
}
decryptTwelve(upperString) {
let key = CryptoJS.enc.Utf8.parse(this.aesKey);
let iv = CryptoJS.enc.Utf8.parse(this.aesIv);
const encryptedHex = CryptoJS.enc.Hex.parse(upperString.toLowerCase());
const encryptedBase64 = CryptoJS.enc.Base64.stringify(encryptedHex);
const decrypted = CryptoJS.AES.decrypt(
encryptedBase64,
key,
{
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}
);
return decrypted.toString(CryptoJS.enc.Utf8);
}
}
document.getElementById("btn").onclick = function() {
const inputVal = document.getElementById("frame").value; // 加密内容
if (!inputVal) {
alert('输入内容不能为空!');
return;
}
const navicatPassword = new NavicatPassword(12);
if(curType === '解密')
{
const decPwd = navicatPassword.decrypt(inputVal); // 解密方法
const UGC = '原内容:' + inputVal; // 原内容
const decrypted = curType + '后:' + decPwd;
document.getElementById('box').innerHTML = UGC + '
' + decrypted;
}
else if(curType === '加密')
{
const encPwd = navicatPassword.encrypt(inputVal);
const UGC = '原内容:' + inputVal; // 原内容
const encrypted = '加密后:' + encPwd; // 加密后
document.getElementById('box').innerHTML = UGC + '
' + encrypted;
}
};
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
th,
td {
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
2.2.3.2 运行结果
单个HTML文件代码浏览器运行数据库密码加密结果
单个HTML文件代码浏览器运行数据库密码解密结果
3. 小结
前人栽树,后人乘凉;海纳百川,有容乃大。无论是在线查看还是本地查看Navicat中的数据库密码,大家都要清晰地认识到明文和密文也是一种交流语言,虽然看不懂也不明白,但只需买一本厚厚的字典去查询即可,虽然这本字典并非可以买到,但方法还是有的😁😁😁。文本的加解密本质就是一种编码方式,不同的编码算法会带来不同的编码结果,而正向编码(加密)和反向编码(解密)就是一种数学映射关系,当然并非所有的映射均为可逆。本文数据库连接密码所采用的加密算法就是可逆编码,因此在掌握其基本原理(真理)和有效代码的前提下,满足需求和实现功能自然就会游刃有余👌👌👌!!!
心之所向,魂牵梦萦
笔者真诚欢迎各位同仁伙伴积极交流,诚挚希望大家共话所见所得,分享所思所想,维护开放共享生态,紧跟时代潮流,积极向上,阳光饱满,开心快乐每一天哦✨✨✨🎈🎈🎈