小技能Navicat如何快速找回Navicat本地数据库密码?
時光前言
在日常工作中,数据库密码的管理至关重要。然而,难免会遇到忘记密码的情况,比如我之前就遇到了MySQL密码遗忘的困扰,而Navicat是我日常工作中最常用的数据库连接工具,因此我自然而然地想到通过Navicat来恢复之前保存的连接密码。于是,我撰写了这篇文章,分享如何通过Navicat恢复已保存的数据库密码。
近期,不少读者反馈之前的方法已经失效,因此我特意寻找并测试了新的解决方案。
本文基于 Navicat Premium 16 版本进行测试,测试日期为 2024年12月16日。
尽管本文提供了通过Navicat找回密码的方法,但我并不建议长期依赖此方式。原因在于,随着软件版本的升级或加密策略的调整,这种方法可能会因不可控因素而再次失效。因此,更值得我们关注的是:当数据库密码遗忘时,如何从根本上解决问题?
以MySQL为例,网上有大量详细的文章介绍如何重置MySQL密码。通过学习这些方法,我们不仅能有效解决实际工作中的问题,还能掌握一种“永久有效”的解决方案。这种方法不会因软件更新或加密策略变化而过时,是更为可靠的选择。
总之,本文旨在提供一种临时的解决方案,但更推荐大家深入学习数据库密码重置的方法,以应对未来可能出现的类似问题。
最新方案
第一步,获取连接密文
文件 -> 导出连接
选择要导出的连接,勾选导出密码
使用文本编辑器(如Notepad–)打开文件,找到 Password
获取密文
第二步,使用在线工具解密
打开 Java在线工具,粘贴以下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
| import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.util.Arrays;
public class NavicatPasswordUtil {
public static void main(String[] args) throws Exception { NavicatPasswordUtil passwordUtil = new NavicatPasswordUtil();
String encryptedPassword = "6EE58FD042645AF6E22B8E376B8EA727";
String decryptedPassword = passwordUtil.decryptPassword(encryptedPassword, NavicatVersion.VERSION_12);
decryptedPassword = decryptedPassword.replaceAll("\\p{Cntrl}", "");
System.out.println("解密后的密码: " + decryptedPassword); }
private static final String AES_KEY = "libcckeylibcckey"; private static final String AES_IV = "libcciv libcciv "; private static final String BLOWFISH_KEY = "3DC5CA39"; private static final String BLOWFISH_IV = "d9c7c3c8870d64bd";
public String encryptPassword(String plaintextPassword, NavicatVersion navicatVersion) throws Exception { switch (navicatVersion) { case VERSION_11: return encryptBlowfish(plaintextPassword); case VERSION_12: return encryptAES(plaintextPassword); default: throw new IllegalArgumentException("不支持的 Navicat 版本"); } }
public String decryptPassword(String encryptedPassword, NavicatVersion navicatVersion) throws Exception { switch (navicatVersion) { case VERSION_11: return decryptBlowfish(encryptedPassword); case VERSION_12: return decryptAES(encryptedPassword); default: throw new IllegalArgumentException("不支持的 Navicat 版本"); } }
private String encryptBlowfish(String plaintextPassword) throws Exception { byte[] iv = hexStringToByteArray(BLOWFISH_IV); byte[] key = hashToBytes(BLOWFISH_KEY);
int round = plaintextPassword.length() / 8; int leftLength = plaintextPassword.length() % 8; StringBuilder encryptedResult = new StringBuilder(); byte[] currentVector = iv.clone();
Cipher cipher = Cipher.getInstance("Blowfish/ECB/NoPadding"); SecretKeySpec secretKeySpec = new SecretKeySpec(key, "Blowfish"); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
for (int i = 0; i < round; i++) { byte[] block = xorBytes(plaintextPassword.substring(i * 8, (i + 1) * 8).getBytes(), currentVector); byte[] encryptedBlock = cipher.doFinal(block); currentVector = xorBytes(currentVector, encryptedBlock); encryptedResult.append(bytesToHex(encryptedBlock)); }
if (leftLength > 0) { currentVector = cipher.doFinal(currentVector); byte[] block = xorBytes(plaintextPassword.substring(round * 8).getBytes(), currentVector); encryptedResult.append(bytesToHex(block)); }
return encryptedResult.toString().toUpperCase(); }
private String encryptAES(String plaintextPassword) throws Exception { byte[] iv = AES_IV.getBytes(); byte[] key = AES_KEY.getBytes();
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encryptedResult = cipher.doFinal(plaintextPassword.getBytes()); return bytesToHex(encryptedResult).toUpperCase(); }
private String decryptBlowfish(String encryptedPassword) throws Exception { byte[] iv = hexStringToByteArray(BLOWFISH_IV); byte[] key = hashToBytes(BLOWFISH_KEY); byte[] encryptedBytes = hexStringToByteArray(encryptedPassword.toLowerCase());
int round = encryptedBytes.length / 8; int leftLength = encryptedBytes.length % 8; StringBuilder decryptedResult = new StringBuilder(); byte[] currentVector = iv.clone();
Cipher cipher = Cipher.getInstance("Blowfish/ECB/NoPadding"); SecretKeySpec secretKeySpec = new SecretKeySpec(key, "Blowfish"); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
for (int i = 0; i < round; i++) { byte[] encryptedBlock = Arrays.copyOfRange(encryptedBytes, i * 8, (i + 1) * 8); byte[] decryptedBlock = xorBytes(cipher.doFinal(encryptedBlock), currentVector); currentVector = xorBytes(currentVector, encryptedBlock); decryptedResult.append(new String(decryptedBlock)); }
if (leftLength > 0) { currentVector = cipher.doFinal(currentVector); byte[] block = Arrays.copyOfRange(encryptedBytes, round * 8, round * 8 + leftLength); decryptedResult.append(new String(xorBytes(block, currentVector), StandardCharsets.UTF_8)); }
return decryptedResult.toString(); }
private String decryptAES(String encryptedPassword) throws Exception { byte[] iv = AES_IV.getBytes(); byte[] key = AES_KEY.getBytes(); byte[] encryptedBytes = hexStringToByteArray(encryptedPassword.toLowerCase());
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] decryptedResult = cipher.doFinal(encryptedBytes); return new String(decryptedResult); }
private static byte[] xorBytes(byte[] bytes1, byte[] bytes2) { byte[] result = new byte[bytes1.length]; for (int i = 0; i < bytes1.length; i++) { result[i] = (byte) (bytes1[i] ^ bytes2[i]); } return result; }
private static byte[] hexStringToByteArray(String hexString) { int len = hexString.length(); byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16)); } return data; }
private static byte[] hashToBytes(String inputString) throws Exception { return MessageDigest.getInstance("SHA-1").digest(inputString.getBytes()); }
private static String bytesToHex(byte[] byteArray) { StringBuilder result = new StringBuilder(); for (byte b : byteArray) { result.append(String.format("%02X", b)); } return result.toString(); } }
enum NavicatVersion { VERSION_11, VERSION_12 }
|
点击运行即可查看密码
注意:粘贴代码时注意删除自动附加的版权信息内容,否则会导致运行错误
我已将代码发布到GitHub,想要学习的同学可自行克隆下载:NavicatPasswordUtil
了解更多关于Navicat 加密算法的内容:
当然,GitHub上还有很多大佬制作好的现成的工具,例如:navicat_password_decrypt
大家自行探索吧,有什么新的收获或任何疑问可在评论区留言分享或反馈。
历史文章
第一步,找到数据库连接登录密码(密文显示)
方案一,用 navicat 导出连接,查看密码(推荐)
文件 > 导出连接
选择要导出的连接,勾选导出密码
这样就得到了加密显示的连接密码
方案二,通过注册表查看加密显示的密码
按快捷键 Win+R 在弹出的运行窗口中输入 regedit 点击确定 打开注册表编辑器
找到 计算机\HKEY_CURRENT_USER\SOFTWARE\PremiumSoft\NavicatMSSQL\Servers
Servers 目录下就是保存在本地的连接
双击右侧Pwd 即可赋值加密显示的密码字符串
第二步,对密码解密
复制如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
| <?php namespace FatSmallTools; 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); } } use FatSmallTools\NavicatPassword;
$navicatPassword = new NavicatPassword(11);
$decode = $navicatPassword->decrypt('15057D7BA390'); echo $decode."\n";
|
打开网页 https://tool.lu/coderunner/ 或 http://www.dooccn.com/php7/ 可在线运行代码
将原来内容替换为复制的代码块,将密码替换,点击执行 即可对密码进行解密
如果执行后的密码乱码
更改一下版本即可