背景
本地Client链接的数据库密码忘记了,恰好密码当初是保持到本地的。记录一下通过DBeaver源码找回密码,为此类问题提供个思路。
存储目录
窗口-> 首选项 -> 工作空间 打开下图workspace path 目录,其中子目录 \General\.dbeaver有个credentials-config.json文件存储着链接的数据源用户名和密码,不过是加密的。
解密
第一步:
DBeaver的版本22.3.5
第二步:
解密代码来自DBeaver仓库,经过裁剪移除无关代码。
dbeaver/DefaultValueEncryptor.java at 22.3.5 · dbeaver/dbeaver · GitHub
解密需要的密钥在代码仓库中搜索变量 LOCAL_KEY_CACHE可以找到。不同版本所在的位置略有差异。
dbeaver/BaseProjectImpl.java at 22.3.5 · dbeaver/dbeaver · GitHub
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
public class DefaultValueEncryptor {
public static final String CIPHER_NAME = "AES/CBC/PKCS5Padding";
public static final String KEY_ALGORITHM = "AES";
private final SecretKey secretKey;
private final Cipher cipher;
public DefaultValueEncryptor(SecretKey secretKey) {
this.secretKey = secretKey;
try {
this.cipher = Cipher.getInstance(CIPHER_NAME);
} catch (Exception e) {
// throw new IllegalStateException("Internal error during encrypted init", e);
System.out.println("Internal error during encrypted init" + e);
throw new RuntimeException(e);
}
}
public byte[] decryptValue(byte[] value) {
try (InputStream byteStream = new ByteArrayInputStream(value)) {
byte[] fileIv = new byte[16];
byteStream.read(fileIv);
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(fileIv));
try (CipherInputStream cipherIn = new CipherInputStream(byteStream, cipher)) {
ByteArrayOutputStream resultBuffer = new ByteArrayOutputStream();
//IOUtils.copyStream(cipherIn, resultBuffer);
int bufferSize = 100;
byte[] buffer = new byte[bufferSize];
while ((bufferSize = cipherIn.read(buffer)) != -1) {
resultBuffer.write(buffer, 0,bufferSize);
}
return resultBuffer.toByteArray();
}
} catch (Exception e) {
//throw new DBException("Error decrypting value", e);
System.out.println("Error decrypting value" + e);
throw new RuntimeException(e);
}
}
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println("plese input param1: full path to your credentials-config.json file");
System.exit(1);
}
//https://github.com/dbeaver/dbeaver/blob/22.3.5/plugins/org.jkiss.dbeaver.registry/src/org/jkiss/dbeaver/registry/BaseProjectImpl.java
final byte[] LOCAL_KEY_CACHE = new byte[]{-70, -69, 74, -97, 119, 74, -72, 83, -55, 108, 45, 101, 61, -2, 84, 74};
SecretKey aes = new SecretKeySpec(LOCAL_KEY_CACHE, KEY_ALGORITHM);
DefaultValueEncryptor encryptor = new DefaultValueEncryptor(aes);
byte[] credentialsConfigBytesSecret = Files.readAllBytes(Paths.get(args[0]));
byte[] credentialsConfigBytesPlain = encryptor.decryptValue(credentialsConfigBytesSecret);
System.out.println(new String(credentialsConfigBytesPlain));
}
}
第三步:
编译上面代码,执行代码(将credentials-config.json作为参数)
javac DecryptDbeaver.java
java DecryptDbeaver credentials-config.json