前言
-
相信你会遇到使用navicat忘记已连接数据密码的问题吧!实在是,密码太多容易忘记!!!
-
感谢大佬as_dmy的文章如何查看navicat已连接数据库密码,然后才有了此文!
-
1.0版本需要手动查看导出的connections.ncx文件中的加密密码值,然后解密
-
2.0版本直接选择文件【支持一个数据库密码的导出文件】,然后解密
-
源码相关资源免费获取!请查看工具获取章节内容!
-
有愿意研究源码的可以看看
源码
1.0 版本源码
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.nio.charset.StandardCharsets;
public class NavicatPasswordGUI {
private JFrame frame;
private JComboBox<String> versionComboBox;
private JTextField originalPasswordTextField;
private JTextField encryptedPasswordTextField;
private JTextField decryptedPasswordTextField;
private String blowKey = "3DC5CA39";
private byte[] blowIv = hexStringToByteArray("d9c7c3c8870d64bd");
private String aesKey = "libcckeylibcckey";
private String aesIv = "libcciv libcciv ";
public NavicatPasswordGUI() {
frame = new JFrame("Navicat Password Encryption/Decryption");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 250);
frame.setLayout(new GridLayout(5, 2));
JLabel versionLabel = new JLabel("navicat Version:");
versionComboBox = new JComboBox<>(new String[]{"11", "12"});
frame.add(versionLabel);
frame.add(versionComboBox);
JLabel originalPasswordLabel = new JLabel("Original Password:");
originalPasswordTextField = new JTextField();
frame.add(originalPasswordLabel);
frame.add(originalPasswordTextField);
JLabel encryptedPasswordLabel = new JLabel("Encrypted Password:");
encryptedPasswordTextField = new JTextField();
encryptedPasswordTextField.setEditable(false);
frame.add(encryptedPasswordLabel);
frame.add(encryptedPasswordTextField);
JLabel decryptedPasswordLabel = new JLabel("Decrypted Password:");
decryptedPasswordTextField = new JTextField();
frame.add(decryptedPasswordLabel);
frame.add(decryptedPasswordTextField);
JButton encryptButton = new JButton("Encrypt");
frame.add(encryptButton);
JButton decryptButton = new JButton("Decrypt");
frame.add(decryptButton);
encryptButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
int version = Integer.parseInt((String) versionComboBox.getSelectedItem());
String originalPassword = originalPasswordTextField.getText();
NavicatPassword navicatPassword = new NavicatPassword(version);
String encryptedPassword = navicatPassword.encrypt(originalPassword);
encryptedPasswordTextField.setText(encryptedPassword);
} catch (Exception ex) {
JOptionPane.showMessageDialog(frame, "Error: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
decryptButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
int version = Integer.parseInt((String) versionComboBox.getSelectedItem());
String encryptedPassword = decryptedPasswordTextField.getText();
NavicatPassword navicatPassword = new NavicatPassword(version);
String decryptedPassword = navicatPassword.decrypt(encryptedPassword);
originalPasswordTextField.setText(decryptedPassword);
} catch (Exception ex) {
JOptionPane.showMessageDialog(frame, "Error: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new NavicatPasswordGUI();
}
});
}
private byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
}
return data;
}
}
class NavicatPassword {
private int version;
private String blowKey = "3DC5CA39";
private byte[] blowIv = hexStringToByteArray("d9c7c3c8870d64bd");
private String aesKey = "libcckeylibcckey";
private String aesIv = "libcciv libcciv ";
public NavicatPassword(int version) {
this.version = version;
}
public String encrypt(String input) throws Exception {
switch (version) {
case 11:
return encryptEleven(input);
case 12:
return encryptTwelve(input);
default:
throw new IllegalArgumentException("Unsupported version: " + version);
}
}
public String decrypt(String input) throws Exception {
switch (version) {
case 11:
return decryptEleven(input);
case 12:
return decryptTwelve(input);
default:
throw new IllegalArgumentException("Unsupported version: " + version);
}
}
private String encryptEleven(String input) throws Exception {
int round = input.length() / 8;
int leftLength = input.length() % 8;
StringBuilder result = new StringBuilder();
byte[] currentVector = blowIv.clone();
for (int i = 0; i < round; i++) {
byte[] temp = encryptBlock(xorBytes(input.getBytes(StandardCharsets.UTF_8), currentVector));
currentVector = xorBytes(currentVector, temp);
result.append(byteArrayToHexString(temp));
}
if (leftLength != 0) {
currentVector = encryptBlock(currentVector);
result.append(byteArrayToHexString(xorBytes(input.substring(8 * round).getBytes(StandardCharsets.UTF_8), currentVector)));
}
return result.toString().toUpperCase();
}
private byte[] encryptBlock(byte[] block) throws Exception {
Cipher cipher = Cipher.getInstance("Blowfish/ECB/NoPadding");
SecretKeySpec secretKeySpec = new SecretKeySpec(blowKey.getBytes(StandardCharsets.UTF_8), "Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
return cipher.doFinal(block);
}
private byte[] decryptBlock(byte[] block) throws Exception {
Cipher cipher = Cipher.getInstance("Blowfish/ECB/NoPadding");
SecretKeySpec secretKeySpec = new SecretKeySpec(blowKey.getBytes(StandardCharsets.UTF_8), "Blowfish");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
return cipher.doFinal(block);
}
private 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 String decryptEleven(String upperString) throws Exception {
String input = upperString.toLowerCase();
int round = input.length() / 16;
int leftLength = input.length() % 16;
StringBuilder result = new StringBuilder();
byte[] currentVector = blowIv.clone();
for (int i = 0; i < round; i++) {
byte[] encryptedBlock = hexStringToByteArray(input.substring(16 * i, 16 * (i + 1)));
byte[] temp = xorBytes(decryptBlock(encryptedBlock), currentVector);
currentVector = xorBytes(currentVector, encryptedBlock);
result.append(byteArrayToHexString(temp));
}
if (leftLength != 0) {
currentVector = encryptBlock(currentVector);
result.append(byteArrayToHexString(xorBytes(input.substring(16 * round).getBytes(StandardCharsets.UTF_8), currentVector)));
}
return new String(hexStringToByteArray(result.toString()), StandardCharsets.UTF_8);
}
private String encryptTwelve(String input) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(aesIv.getBytes(StandardCharsets.UTF_8));
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);
byte[] encrypted = cipher.doFinal(input.getBytes(StandardCharsets.UTF_8));
return byteArrayToHexString(encrypted).toUpperCase();
}
private String decryptTwelve(String upperString) throws Exception {
byte[] input = hexStringToByteArray(upperString.toLowerCase());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(aesIv.getBytes(StandardCharsets.UTF_8));
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
byte[] decrypted = cipher.doFinal(input);
return new String(decrypted, StandardCharsets.UTF_8);
}
private byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
}
return data;
}
private String byteArrayToHexString(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02X", b));
}
return result.toString();
}
}
2.0 版本源码
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class NavicatPasswordGUI {
private final JFrame frame;
private final JComboBox<String> versionComboBox;
private final JTextField originalPasswordTextField;
private final JTextField encryptedPasswordTextField;
private final JTextField decryptedPasswordTextField;
private final JButton selectFileButton;
private final String blowKey = "3DC5CA39";
private final byte[] blowIv = hexStringToByteArray("d9c7c3c8870d64bd");
private final String aesKey = "libcckeylibcckey";
private final String aesIv = "libcciv libcciv ";
public NavicatPasswordGUI() {
frame = new JFrame("Navicat Password Encryption/Decryption");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 250);
frame.setLayout(new GridLayout(6, 2));
JLabel versionLabel = new JLabel("navicat Version:");
versionComboBox = new JComboBox<>(new String[]{"11", "12"});
frame.add(versionLabel);
frame.add(versionComboBox);
JLabel originalPasswordLabel = new JLabel("Original Password:");
originalPasswordTextField = new JTextField();
frame.add(originalPasswordLabel);
frame.add(originalPasswordTextField);
JLabel encryptedPasswordLabel = new JLabel("Encrypted Password:");
encryptedPasswordTextField = new JTextField();
encryptedPasswordTextField.setEditable(false);
frame.add(encryptedPasswordLabel);
frame.add(encryptedPasswordTextField);
JLabel decryptedPasswordLabel = new JLabel("Decrypted Password:");
decryptedPasswordTextField = new JTextField();
decryptedPasswordTextField.setEditable(false);
frame.add(decryptedPasswordLabel);
frame.add(decryptedPasswordTextField);
selectFileButton = new JButton("Select File");
frame.add(selectFileButton);
JButton encryptButton = new JButton("Encrypt");
frame.add(encryptButton);
JButton decryptButton = new JButton("Decrypt");
frame.add(decryptButton);
selectFileButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fileChooser = new JFileChooser();
int returnValue = fileChooser.showOpenDialog(null);
if (returnValue == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
try {
// 使用DOM解析XML文件
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(selectedFile);
// 查找密码字段
NodeList connectionsList = doc.getElementsByTagName("Connection");
if (connectionsList.getLength() > 0) {
Element connectionElement = (Element) connectionsList.item(0);
String password = connectionElement.getAttribute("Password");
decryptedPasswordTextField.setText(password);
} else {
JOptionPane.showMessageDialog(frame, "No Connection element found in the XML file.", "Error", JOptionPane.ERROR_MESSAGE);
}
} catch (ParserConfigurationException | IOException | org.xml.sax.SAXException ex) {
JOptionPane.showMessageDialog(frame, "Error reading XML file: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
}
});
encryptButton.addActionListener(e -> {
try {
int version = Integer.parseInt((String) versionComboBox.getSelectedItem());
String originalPassword = originalPasswordTextField.getText();
NavicatPassword navicatPassword = new NavicatPassword(version);
String encryptedPassword = navicatPassword.encrypt(originalPassword);
encryptedPasswordTextField.setText(encryptedPassword);
} catch (Exception ex) {
JOptionPane.showMessageDialog(frame, "Error: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
});
decryptButton.addActionListener(e -> {
try {
int version = Integer.parseInt((String) versionComboBox.getSelectedItem());
String encryptedPassword = decryptedPasswordTextField.getText();
NavicatPassword navicatPassword = new NavicatPassword(version);
String decryptedPassword = navicatPassword.decrypt(encryptedPassword);
originalPasswordTextField.setText(decryptedPassword);
} catch (Exception ex) {
JOptionPane.showMessageDialog(frame, "Error: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
});
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new NavicatPasswordGUI());
}
private byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
}
return data;
}
}
class NavicatPassword {
private final int version;
private final String blowKey = "3DC5CA39";
private final byte[] blowIv = hexStringToByteArray("d9c7c3c8870d64bd");
private final String aesKey = "libcckeylibcckey";
private final String aesIv = "libcciv libcciv ";
public NavicatPassword(int version) {
this.version = version;
}
public String encrypt(String input) throws Exception {
switch (version) {
case 11:
return encryptEleven(input);
case 12:
return encryptTwelve(input);
default:
throw new IllegalArgumentException("Unsupported version: " + version);
}
}
public String decrypt(String input) throws Exception {
switch (version) {
case 11:
return decryptEleven(input);
case 12:
return decryptTwelve(input);
default:
throw new IllegalArgumentException("Unsupported version: " + version);
}
}
private String encryptEleven(String input) throws Exception {
int round = input.length() / 8;
int leftLength = input.length() % 8;
StringBuilder result = new StringBuilder();
byte[] currentVector = blowIv.clone();
for (int i = 0; i < round; i++) {
byte[] temp = encryptBlock(xorBytes(input.getBytes(StandardCharsets.UTF_8), currentVector));
currentVector = xorBytes(currentVector, temp);
result.append(byteArrayToHexString(temp));
}
if (leftLength != 0) {
currentVector = encryptBlock(currentVector);
result.append(byteArrayToHexString(xorBytes(input.substring(8 * round).getBytes(StandardCharsets.UTF_8), currentVector)));
}
return result.toString().toUpperCase();
}
private byte[] encryptBlock(byte[] block) throws Exception {
Cipher cipher = Cipher.getInstance("Blowfish/ECB/NoPadding");
SecretKeySpec secretKeySpec = new SecretKeySpec(blowKey.getBytes(StandardCharsets.UTF_8), "Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
return cipher.doFinal(block);
}
private byte[] decryptBlock(byte[] block) throws Exception {
Cipher cipher = Cipher.getInstance("Blowfish/ECB/NoPadding");
SecretKeySpec secretKeySpec = new SecretKeySpec(blowKey.getBytes(StandardCharsets.UTF_8), "Blowfish");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
return cipher.doFinal(block);
}
private 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 String decryptEleven(String upperString) throws Exception {
String input = upperString.toLowerCase();
int round = input.length() / 16;
int leftLength = input.length() % 16;
StringBuilder result = new StringBuilder();
byte[] currentVector = blowIv.clone();
for (int i = 0; i < round; i++) {
byte[] encryptedBlock = hexStringToByteArray(input.substring(16 * i, 16 * (i + 1)));
byte[] temp = xorBytes(decryptBlock(encryptedBlock), currentVector);
currentVector = xorBytes(currentVector, encryptedBlock);
result.append(byteArrayToHexString(temp));
}
if (leftLength != 0) {
currentVector = encryptBlock(currentVector);
result.append(byteArrayToHexString(xorBytes(input.substring(16 * round).getBytes(StandardCharsets.UTF_8), currentVector)));
}
return new String(hexStringToByteArray(result.toString()), StandardCharsets.UTF_8);
}
private String encryptTwelve(String input) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(aesIv.getBytes(StandardCharsets.UTF_8));
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);
byte[] encrypted = cipher.doFinal(input.getBytes(StandardCharsets.UTF_8));
return byteArrayToHexString(encrypted).toUpperCase();
}
private String decryptTwelve(String upperString) throws Exception {
byte[] input = hexStringToByteArray(upperString.toLowerCase());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(aesIv.getBytes(StandardCharsets.UTF_8));
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
byte[] decrypted = cipher.doFinal(input);
return new String(decrypted, StandardCharsets.UTF_8);
}
private byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
}
return data;
}
private String byteArrayToHexString(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02X", b));
}
return result.toString();
}
}
打包步骤
-
编写并保存上述Java代码为一个.java文件
-
打开终端或命令提示符,进入包含.java文件的目录。
-
使用Java编译器(javac)编译Java类文件。例如:
javac NavicatPasswordGUI.java
-
创建一个包含
MANIFEST.MF
文件的目录,其中包含以下内容:Manifest-Version: 1.0 Main-Class: NavicatPasswordGUI
-
打包成JAR文件,使用以下命令:
- 创建一个名为
NavicatPasswordGUI.jar
的JAR文件,其中包含Java类以及MANIFEST文件。
jar cfm NavicatPasswordGUI.jar MANIFEST.MF *.class
- 创建一个名为
-
运行JAR文件,或者双击:
java -jar NavicatPasswordGUI.jar
工具获取
- 相关资源获取 NavicatPassword Decryp tools.zip
操作方法
导出navicat数据库连接信息
-
打开navicat,点击文件➡导出连接
-
勾选需要导出的连接,注意,勾选“导出密码”
使用工具
- 相信使用navicat的小伙伴,电脑一定配置了java环境,如果有例外,请自行百度,安装java环境!
工具1.0使用方法
- 打开connections.ncx复制password内容
- 双击打开1.0版本目录下jar包 ,选择navicate版本,粘贴复制的密码内容,点击解密即可
- Navicat 15和Navicat 16请选择版本为12,其他请尝试不同版本的的解密!
- 如果版本选择错误,会出现乱码的结果,请多多尝试
工具2.0 使用方法
- 运行工具,选择导出的连接文件,点击解密即可