最近从Navicat换到了DBeaver,导出配置文件发现配置文件里的密码都是加密的,看网上的都是给的PHP代码,因为环境问题,就算是在线上运行的PHP代码也会报错,所以就把这段代码改成Java了。
package com.unicdata.system.controller.marketing;/**
* @Author: PengShangXing
* @Date: 2025/01/07/0007 15:13
*/
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;
/**
* @Author: PengShangXing
* @Date: 2025/01/07/0007 15:13
*/
public class NavicatPassword {
private int version = 0;
private final String aesKey = "libcckeylibcckey";
private final String aesIv = "libcciv libcciv ";
private final String blowString = "3DC5CA39";
private byte[] blowKey;
private byte[] blowIv;
public NavicatPassword(int version) {
this.version = version;
this.blowKey = sha1("3DC5CA39");
this.blowIv = hexToBytes("d9c7c3c8870d64bd");
}
public String encrypt(String string) throws Exception {
String result = null;
switch (this.version) {
case 11:
result = encryptEleven(string);
break;
case 12:
result = encryptTwelve(string);
break;
default:
break;
}
return result;
}
private String encryptEleven(String string) throws Exception {
int round = string.length() / 8;
int leftLength = string.length() % 8;
StringBuilder result = new StringBuilder();
byte[] currentVector = blowIv;
for (int i = 0; i < round; i++) {
byte[] temp = encryptBlock(xorBytes(string.substring(8 * i, 8 * (i + 1)).getBytes(), currentVector));
currentVector = xorBytes(currentVector, temp);
result.append(bytesToHex(temp));
}
if (leftLength > 0) {
currentVector = encryptBlock(currentVector);
result.append(bytesToHex(xorBytes(string.substring(8 * round).getBytes(), currentVector)));
}
return result.toString().toUpperCase();
}
private byte[] encryptBlock(byte[] block) throws Exception {
Cipher cipher = Cipher.getInstance("Blowfish/ECB/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(blowKey, "Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
return cipher.doFinal(block);
}
private byte[] decryptBlock(byte[] block) throws Exception {
Cipher cipher = Cipher.getInstance("Blowfish/ECB/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(blowKey, "Blowfish");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
return cipher.doFinal(block);
}
private String encryptTwelve(String string) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(aesKey.getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(aesIv.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encrypted = cipher.doFinal(string.getBytes());
return bytesToHex(encrypted).toUpperCase();
}
public String decrypt(String string) throws Exception {
String result = null;
switch (this.version) {
case 11:
result = decryptEleven(string);
break;
case 12:
result = decryptTwelve(string);
break;
default:
break;
}
return result;
}
private String decryptEleven(String upperString) throws Exception {
byte[] string = hexToBytes(upperString.toLowerCase());
int round = string.length / 8;
int leftLength = string.length % 8;
StringBuilder result = new StringBuilder();
byte[] currentVector = blowIv;
for (int i = 0; i < round; i++) {
byte[] encryptedBlock = Arrays.copyOfRange(string, 8 * i, 8 * (i + 1));
byte[] temp = xorBytes(decryptBlock(encryptedBlock), currentVector);
currentVector = xorBytes(currentVector, encryptedBlock);
result.append(new String(temp));
}
if (leftLength > 0) {
currentVector = encryptBlock(currentVector);
result.append(new String(xorBytes(Arrays.copyOfRange(string, 8 * round, string.length), currentVector)));
}
return result.toString();
}
private String decryptTwelve(String upperString) throws Exception {
// 将十六进制字符串转换为字节数组
byte[] string = hexToBytes(upperString.toLowerCase());
// 初始化AES解密
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(aesKey.getBytes("UTF-8"), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(aesIv.getBytes("UTF-8"));
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
// 解密并按照UTF-8编码返回字符串
return new String(cipher.doFinal(string), "UTF-8");
}
private byte[] xorBytes(byte[] str1, byte[] str2) {
byte[] result = new byte[str1.length];
for (int i = 0; i < str1.length; i++) {
result[i] = (byte) (str1[i] ^ str2[i]);
}
return result;
}
private byte[] sha1(String input) {
try {
java.security.MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1");
return digest.digest(input.getBytes());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private byte[] hexToBytes(String hex) {
int len = hex.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
+ Character.digit(hex.charAt(i + 1), 16));
}
return data;
}
private String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public static void main(String[] args) throws Exception {
// Example usage
NavicatPassword navicatPassword = new NavicatPassword(12);
// Decrypt
String decode = navicatPassword.decrypt("xxxxx");
System.out.println(decode);
}
}