吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4565|回复: 35
上一主题 下一主题
收起左侧

[原创] DBeaver Ultimate Edition License 验证分析 25.3.0版本

  [复制链接]
跳转到指定楼层
楼主
mixyoung 发表于 2026-2-4 13:54 回帖奖励

前序

最近重装系统顺带重装DBeaver,之前一直用现成的,输入激活码还是一直提示失效。现在还想要做便携化,不想再c盘生成文件。索性从头到尾跑一遍。DBeaver现在更新到25.3.0了。搞一波。

依然是瞻仰大佬

环境

操作系统:Windows10
Java版本:JDK21(DBeaver配置文件里面写了,要求最低21了)
软件版本:DBeaver Ultimate 25.3.0

较之前变化

依赖产生了变化

org.jkiss.lm_1.0.136.202206121739.jar -->com.dbeaver.lm.api.*.jar

思路

前面的各位大佬已经研究过各个包或者函数的构造,需要看具体过程的直接见前文链接。核心是com.dbeaver.lm.api.*.jar中已经实现了生成密钥、生成License、解密License、导入License的测试代码,只需稍作修改就可以直接使用。相当于本地离线授权。

  1. 生成一对RAS加解密使用的公钥和私钥;
  2. 将com.dbeaver.app.ultimate_*.jar中的公钥替换成自己生成的公钥;
  3. 用自己的私钥生成一个License文件导入到DBEaver中;
  4. 绕过License网络校验。

步骤

  1. 新建项目并导入需要研究的DBeaver版本的中对应的依赖的jar包
  2. 创建一个新的类贴入下面代码

    package main;
    
    /**
    * DBeaver Ultimate 版本许可证实现方法研究
    * 注意事项:
    * - 建议备份原始jar文件
    * - 仅供学习研究使用
    */
    import com.dbeaver.lm.api.LMEncryption;
    import com.dbeaver.lm.api.LMException;
    import com.dbeaver.lm.api.LMLicense;
    import com.dbeaver.lm.api.LMLicenseType;
    import com.dbeaver.lm.api.LMProduct;
    import com.dbeaver.lm.api.LMProductType;
    import com.dbeaver.lm.api.LMUtils;
    import org.jkiss.utils.Base64;
    
    import java.awt.*;
    import java.awt.datatransfer.Clipboard;
    import java.awt.datatransfer.StringSelection;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.security.KeyPair;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.Enumeration;
    import java.util.List;
    import java.util.jar.JarEntry;
    import java.util.jar.JarFile;
    import java.util.jar.JarOutputStream;
    
    /**
    * DBeaver许可证主类
    * 
    * 该类实现了完整的DBeaver Ultimate许可证生成和应用流程
    * 包括密钥生成、许可证创建、文件替换等功能
    */
    public class DBeaverLicenseCrack {
    
       // ==================== 许可证基本信息配置 ====================
    
       /** 产品标识符 - DBeaver Ultimate Edition */
       private static final String PRODUCT_ID = "dbeaver-ue";
    
       /** 产品版本号 */
       private static final String PRODUCT_VERSION = "25.3.0";
    
       /** 所有者ID */
       private static final String OWNER_ID = "10006";
    
       /** 所有者公司名称 */
       private static final String OWNER_COMPANY = "DBeaver Corporation";
    
       /** 所有者姓名 */
       private static final String OWNER_NAME = "Ultimate User";
    
       /** 所有者邮箱 */
       private static final String OWNER_EMAIL = "developer@dbeaver.com";
    
       // ==================== 路径配置 ====================
    
       /** DBeaver安装目录路径 */
       private static final String DBEAVER_ECLIPSE_HOME = "D:\\Program Files\\dbeaver-ue";
    
       /** IDEA主目录路径 - 用于存储生成的密钥文件 */
       private static final String IDEA_HOME = "D:\\Program Files\\dbeaver-ue";
    
       // ==================== 文件路径变量 ====================
    
       /** 私钥文件路径 */
       private static File privateKeyFile;
    
       /** 公钥文件路径 */
       private static File publicKeyFile;
    
       /** 许可证文件路径 */
       private static File licenseFile;
    
       /** JAR包中使用的公钥文件路径 */
       private static File jarPublicKey;
    
       // ==================== 静态初始化块 ====================
    
       /**
        * 静态初始化块 - 在类加载时执行
        * 
        * 功能:
        * 1. 创建必要的目录结构
        * 2. 初始化所有文件路径变量
        * 3. 输出调试信息
        * 
        * 执行时机:类第一次被加载时自动执行
        */
       static {
           try {
               // 构建密钥存储目录路径
               File keysDir = new File(IDEA_HOME, "portable_data\\keys");
    
               // 如果目录不存在则创建
               if (!keysDir.exists()) {
                   if (keysDir.mkdirs()) {
                       System.out.println("[INFO] 成功创建密钥目录: " + keysDir.getAbsolutePath());
                   } else {
                       System.err.println("[ERROR] 创建密钥目录失败: " + keysDir.getAbsolutePath());
                   }
               }
    
               System.out.println("[DEBUG] 密钥存储目录: " + keysDir.getAbsolutePath());
    
               // 初始化各个文件的完整路径
               privateKeyFile = new File(keysDir, "private-key.txt");
               publicKeyFile = new File(keysDir, "public-key.txt");
               licenseFile = new File(keysDir, "license.txt");
               jarPublicKey = new File(keysDir, "dbeaver-ue-public.key");
    
               // 输出调试信息
               System.out.println("[DEBUG] 私钥文件路径: " + privateKeyFile.getAbsolutePath());
               System.out.println("[DEBUG] 公钥文件路径: " + publicKeyFile.getAbsolutePath());
               System.out.println("[DEBUG] 许可证文件路径: " + licenseFile.getAbsolutePath());
               System.out.println("[DEBUG] JAR公钥文件路径: " + jarPublicKey.getAbsolutePath());
    
           } catch (Exception e) {
               System.err.println("[ERROR] 初始化目录时发生错误: " + e.getMessage());
               e.printStackTrace();
           }
       }
    
       // ==================== 主方法 ====================
    
       /**
        * 程序入口点
        * 
        * 执行完整的DBeaver许可证破解流程:
        * 1. 验证DBeaver安装目录
        * 2. 查找目标jar文件
        * 3. 生成密钥对和许可证
        * 4. 替换jar包中的公钥文件
        * 5. 修改配置文件
        * 
        * @Param args 命令行参数(未使用)
        * @throws Exception 如果执行过程中发生任何错误
        */
       public static void main(String[] args) throws Exception {
           System.out.println("=========================================");
           System.out.println("    DBeaver Ultimate 许可证破解工具");
           System.out.println("=========================================");
           System.out.println("[INFO] 开始执行DBeaver许可证破解流程...");
    
           // ==================== 第一步:验证DBeaver安装环境 ====================
           System.out.println("\n[STEP 1] 验证DBeaver安装环境");
    
           // 检查DBeaver主目录是否存在
           File dbeaverHome = new File(DBEAVER_ECLIPSE_HOME);
           if (!dbeaverHome.exists()) {
               System.err.println("[ERROR] DBeaver安装目录不存在: " + DBEAVER_ECLIPSE_HOME);
               System.err.println("[SOLUTION] 请检查DBEAVER_ECLIPSE_HOME配置是否正确");
               return;
           }
           System.out.println("[SUCCESS] DBeaver安装目录验证通过");
    
           // 检查插件目录是否存在
           String dbeaverPluginDir = DBEAVER_ECLIPSE_HOME + File.separator + "plugins";
           File pluginDir = new File(dbeaverPluginDir);
           if (!pluginDir.exists()) {
               System.err.println("[ERROR] 插件目录不存在: " + dbeaverPluginDir);
               System.err.println("[SOLUTION] 请确认DBeaver安装完整");
               return;
           }
           System.out.println("[SUCCESS] 插件目录验证通过: " + dbeaverPluginDir);
    
           // ==================== 第二步:查找目标jar文件 ====================
           System.out.println("\n[STEP 2] 查找目标jar文件");
    
           // 需要替换公钥的文件模式 (com.dbeaver.app.ultimate_**.jar)
           String replaceJarFile = "com\\.dbeaver\\.app\\.ultimate_.+\\.jar";
           List<File> matchingFiles = findFilesByPattern(dbeaverPluginDir, replaceJarFile);
    
           System.out.println("[INFO] 找到匹配的文件数量: " + matchingFiles.size());
           for (File file : matchingFiles) {
               System.out.println("[FOUND] 匹配文件: " + file.getAbsolutePath());
           }
    
           // 验证是否找到唯一的目标文件
           if (matchingFiles.size() != 1) {
               System.err.println("[ERROR] 未找到需要替换的jar文件,或找到多个匹配文件");
               System.err.println("[SOLUTION] 请手动确认目标jar文件");
               return;
           }
    
           String dbeaverJar = matchingFiles.get(0).getAbsolutePath();
           System.out.println("[SUCCESS] 确定目标JAR文件: " + dbeaverJar);
    
           // ==================== 第三步:生成密钥和许可证 ====================
           System.out.println("\n[STEP 3] 生成密钥对和许可证");
           generateKeyLicenseAndPatch(dbeaverJar, "keys/dbeaver-ue-public.key");
    
           // ==================== 第四步:修改配置文件 ====================
           System.out.println("\n[STEP 4] 修改配置文件");
           String iniFile = DBEAVER_ECLIPSE_HOME + File.separator + "dbeaver.ini";
           System.out.println("[INFO] 配置文件路径: " + iniFile);
           updateEclipseIniFile(iniFile, "-Dlm.debug.mode=true");
    
           // ==================== 完成 ====================
           System.out.println("\n=========================================");
           System.out.println("    执行完成!");
           System.out.println("=========================================");
           System.out.println("[NEXT STEP] 请启动DBeaver并输入生成的许可证");
       }
    
       /**
        * 在文件中追加一行配置文本(已经存在则跳过)
        *
        * @Param iniFile
        * @param configLine
        * @throws IOException
        */
       public static void updateEclipseIniFile(String iniFile, String configLine) throws IOException {
           boolean targetLineFound = false;
    
           // 读取 ini 文件
           File file = new File(iniFile);
           FileReader fr = new FileReader(file);
           BufferedReader br = new BufferedReader(fr);
    
           String line;
           StringBuilder content = new StringBuilder();
           while ((line = br.readLine()) != null) {
               content.append(line).append(System.lineSeparator());
               if (line.trim().equals(configLine)) {
                   targetLineFound = true;
               }
           }
           br.close();
    
           // 如果未找到目标行,在内容的末尾追加文本
           if (!targetLineFound) {
               content.append(configLine).append(System.lineSeparator());
    
               // 将更新的内容写回 ini 文件
               FileWriter fw = new FileWriter(file);
               BufferedWriter bw = new BufferedWriter(fw);
               bw.write(content.toString());
               bw.close();
           }
       }
    
       /**
        * 通过正则表达匹配,搜索匹配的文件
        *
        * @param directoryPath 目录
        * @param pattern       文件匹配正则
        * @return
        */
       public static List<File> findFilesByPattern(String directoryPath, String pattern) {
           List<File> matchingFiles = new ArrayList<>();
           File directory = new File(directoryPath);
    
           System.out.println("搜索目录: " + directoryPath);
           System.out.println("匹配模式: " + pattern);
    
           if (directory.exists() && directory.isDirectory()) {
               File[] files = directory.listFiles();
    
               if (files != null) {
                   System.out.println("目录中的文件总数: " + files.length);
                   int showCount = 0;
                   for (File file : files) {
                       if (file.isFile()) {
                           boolean matches = file.getName().matches(pattern);
                           if (matches) {
                               System.out.println("匹配文件: " + file.getName());
                               matchingFiles.add(file);
                           } else {
                               // 显示前几个文件名用于调试
                               if (showCount < 10) {
                                   System.out.println("不匹配文件: " + file.getName());
                                   showCount++;
                               }
                           }
                       }
                   }
                   if (showCount >= 10) {
                       System.out.println("...(还有更多文件)");
                   }
               } else {
                   System.out.println("无法列出目录内容");
               }
           } else {
               System.out.println("无效的目录,或者找不到目录路径!");
           }
    
           return matchingFiles;
       }
    
       /**
        * 生成RSA密钥对、创建许可证并替换jar包中的公钥文件
        * 
        * 核心功能流程:
        * 1. 生成2048位RSA密钥对
        * 2. 将公钥保存到文件
        * 3. 使用私钥加密生成许可证
        * 4. 将公钥文件替换到目标jar包中
        * 
        * @param jarFilePath 需要替换公钥的jar文件路径
        * @param filePathInJar jar包中公钥文件的相对路径
        * @throws LMException 如果许可证生成过程出错
        * @throws IOException 如果文件操作失败
        */
       public static void generateKeyLicenseAndPatch(String jarFilePath, String filePathInJar) throws LMException, IOException {
           // 从 LMMain.generateKeyPair() 复制的代码
           KeyPair keyPair = LMEncryption.generateKeyPair(2048);
           PublicKey publicKey = keyPair.getPublic();
           PrivateKey privateKey = keyPair.getPrivate();
           System.out.println("\n--- PUBLIC KEY ---");
           String publicKeyContent = Base64.splitLines(Base64.encode(publicKey.getEncoded()), 76);
           System.out.println(publicKeyContent);
           writeFileToPath(publicKeyContent, publicKeyFile, "公钥");
           System.out.println("\n--- PRIVATE KEY ---");
           String privateKeyContent = Base64.splitLines(Base64.encode(privateKey.getEncoded()), 76);
           System.out.println(privateKeyContent);
           writeFileToPath(publicKeyContent, privateKeyFile, "私钥");
           writeFileToPath(publicKeyContent, jarPublicKey, "公钥");
    
           // 替换 jar 包中的 public key 文件
           replaceFileInJar(jarFilePath, filePathInJar, jarPublicKey.getAbsolutePath());
    
           // 从 LMMain.encryptLicense() 复制的代码
           LMProduct TEST_PRODUCT = new LMProduct("dbeaver-ue", "DB", "DBeaver Ultimate", "DBeaver Ultimate Edition", "23.1", LMProductType.DESKTOP, new Date(), new String[0]);
           String licenseID = LMUtils.generateLicenseId(TEST_PRODUCT);
           LMLicense license = new LMLicense(licenseID, LMLicenseType.ULTIMATE, new Date(), new Date(), (Date) null, LMLicense.FLAG_UNLIMITED_SERVERS, PRODUCT_ID, PRODUCT_VERSION, OWNER_ID, OWNER_COMPANY, OWNER_NAME, OWNER_EMAIL);
           byte[] licenseData = license.getData();
           byte[] licenseEncrypted = LMEncryption.encrypt(licenseData, privateKey);
    
           String licenseContent = Base64.splitLines(Base64.encode(licenseEncrypted), 76);
           System.out.println("\n--- LICENSE ---");
           System.out.println(licenseContent);
           System.out.println("--- 处理完成,请打开软件使用以上授权码(已复制到剪切板) ---");
           copyToClipboard(licenseContent);
           writeFileToPath(licenseContent, licenseFile, "授权码");
       }
    
       /**
        * 写入并覆盖文件内容
        *
        * @param content  写入覆盖的内容
        * @param filePath 要写入的文件路径
        * @param tip      提示
        */
       public static void writeFileToPath(String content, File filePath, String tip) {
           try {
               Path path = Paths.get(filePath.getAbsolutePath());
               Files.write(path, content.getBytes());
               System.out.println(String.format("[%s内容]已成功写入文件:%s", tip, path));
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
    
       /**
        * 替换 jar 包中的指定路径的文件为新文件
        *
        * @param jarFilePath
        * @param targetFile
        * @param newFile
        * @throws IOException
        */
       public static void replaceFileInJar(String jarFilePath, String targetFile, String newFile) throws IOException {
           File tempFile = File.createTempFile("temp-file", ".tmp");
           File tempJarFile = File.createTempFile("temp-jar", ".tmp");
    
           boolean replaceSuccess = false;
           try (JarFile jarFile = new JarFile(new File(jarFilePath));
                JarOutputStream tempJarOutputStream = new JarOutputStream(new FileOutputStream(tempJarFile))) {
    
               // Copy the existing entries to the temp jar, excluding the entry to be replaced
               Enumeration<JarEntry> entries = jarFile.entries();
               while (entries.hasMoreElements()) {
                   JarEntry entry = entries.nextElement();
    
                   if (!entry.getName().equals(targetFile)) {
                       tempJarOutputStream.putNextEntry(new JarEntry(entry.getName()));
                       try (InputStream inputStream = jarFile.getInputStream(entry)) {
                           copyStream(inputStream, tempJarOutputStream);
                       }
                   }
               }
    
               // 将新文件添加到临时jar
               tempJarOutputStream.putNextEntry(new JarEntry(targetFile));
               try (InputStream newFileStream = new FileInputStream(newFile)) {
                   copyStream(newFileStream, tempJarOutputStream);
               }
               replaceSuccess = true;
           } finally {
               // 将原始 jar 文件替换为临时 jar 文件
               File originalJarFile = new File(jarFilePath);
               if (originalJarFile.delete() && tempJarFile.renameTo(originalJarFile) && replaceSuccess) {
                   System.out.println(String.format("jar包中的文件 [%s] 替换成功!", targetFile));
               } else {
                   System.out.println(String.format("jar包中的文件 [%s] 替换失败!", targetFile));
               }
    
               tempFile.delete();
               tempJarFile.delete();
           }
       }
    
       private static void copyStream(InputStream in, OutputStream out) throws IOException {
           byte[] buffer = new byte[1024];
           int bytesRead;
           while ((bytesRead = in.read(buffer)) != -1) {
               out.write(buffer, 0, bytesRead);
           }
       }
    
       /**
        * 将指定字符串复制到剪切板
        *
        * @param text
        */
       public static void copyToClipboard(String text) {
           StringSelection stringSelection = new StringSelection(text);
           Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
           clipboard.setContents(stringSelection, null);
       }
    }
  3. 上述代码具体工作内容,
    创建文件public-key.txt,private-key.txt,dbeaver-ue-public.key,
    将私钥复制到private-key.txt中,
    将公钥复制到public-key.txt和dbeaver-ue-public.key中
    Java代码中传入参数encrypt-license,生成License字符串
    修改配置文件dbeaver.ini,增加 -Dlm.debug.mode=true 配置
  4. 现在需要做的就是打开DBeaver,导入License,如图:

免费评分

参与人数 13威望 +1 吾爱币 +33 热心值 +11 收起 理由
cooltnt + 1 谢谢@Thanks!
加载中... + 1 + 1 谢谢@Thanks!
ptootp + 1 + 1 我很赞同!
Alleine + 1 + 1 希望哪个大神能做成直接执行的脚本
萌八喜 + 1 + 1 用心讨论,共获提升!
No__大大吉 + 1 + 1 谢谢@Thanks!
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
fightingmy + 1 谢谢@Thanks!
ffjjideas + 1 + 1 我很赞同!
evea + 1 + 1 谢谢@Thanks!
rolacn + 2 + 1 谢谢@Thanks!
onlylovewww + 1 + 1 兄弟做成了绿色版嘛?能发我一个嘛,一个不爱安装的人
laohucai + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
fulinxin 发表于 2026-7-10 23:37
本帖最后由 fulinxin 于 2026-7-10 23:42 编辑

根据这些大佬的思路和源码,搞出了26.1的注册码生成
[Java] 纯文本查看 复制代码
import com.dbeaver.lm.api.*;
import org.jkiss.utils.Base64;

import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;

/**
 * 本代码依赖 2 个 jar 包
 * <ul>
 *     <li>${DBEAVER_ECLIPSE_HOME}/plugins/org.jkiss.utils_2.7.0.202606291110.jar</li>
 *     <li>${DBEAVER_ECLIPSE_HOME}/plugins/com.dbeaver.lm.api_3.0.35.202606291110.jar</li>
 * </ul>
 */
public class DBeaverLicenseCrack {
    private static String productID = "dbeaver-ue";
    private static String productVersion = "26.1.0";
    private static String ownerID = "10006";
    private static String ownerCompany = "DBeaver Corporation";
    private static String ownerName = "Ultimate User";
    private static String ownerEmail = "developer@dbeaver.com";

    private static File folderPath = new File(".jkiss-lm");
    private static File privateKeyFile = new File(folderPath , "private-key.txt");
    private static File publicKeyFile = new File(folderPath , "public-key.txt");
    private static File licenseFile = new File(folderPath , "license.txt");

    /** 
     *  实践发现26.1断网激活即可,所以激活前记得断网
     */
    private static File jarPublicKey = new File(folderPath , "dbeaver-ue-public.key");
    
    //将这个参数替换成你的dbeaver的安装目录
    //将这个参数替换成你的dbeaver的安装目录
   //将这个参数替换成你的dbeaver的安装目录
    private static final String DBEAVER_ECLIPSE_HOME = "E:\\Program Files\\DBeaverUltimate";

    public static void main(String[] args) throws Exception {
        String dbeaverPluginDir = DBEAVER_ECLIPSE_HOME + File.separator + "plugins";
        // 需要替换公钥的文件 (com.dbeaver.app.ultimate_**.jar)
        String replaceJarFile = "com\\.dbeaver\\.app\\.ultimate_.+\\.jar";
        createFiles(folderPath,privateKeyFile,publicKeyFile,licenseFile,jarPublicKey);
        List<File> matchingFiles = findFilesByPattern(dbeaverPluginDir, replaceJarFile);
        if (matchingFiles.size() != 1) {
            throw new IOException("未找到需要替换的 jar 文件");
        }
        String dbeaverJar = matchingFiles.get(0).getAbsolutePath();
        generateKeyLicenseAndPatch(dbeaverJar, "keys/dbeaver-ue-public.key");
        //String iniFile = DBEAVER_ECLIPSE_HOME + File.separator + "dbeaver.ini";
        //updateEclipseIniFile(iniFile, "-Dlm.debug.mode=true");
    }

    //创建接收字符串的公钥、私钥、注册码、jar包里的公钥文件
    public static void createFiles(File folder,File privateKeyFile,File publicKeyFile,File licenseFile,File jarPublicKey){
        // 创建文件夹
        folder.mkdirs(); // 使用mkdirs()创建多级目录

        // 创建文件
        try {
            privateKeyFile.createNewFile();
            publicKeyFile.createNewFile();
            licenseFile.createNewFile();
            jarPublicKey.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 在文件中追加一行配置文本(已经存在则跳过)
     *
     * @Param iniFile
     * @param configLine
     * @throws IOException
     */
    public static void updateEclipseIniFile(String iniFile, String configLine) throws IOException {
        boolean targetLineFound = false;
    //com.dbeaver.model.license.embedded.LicenseServiceEmbedded.importProductLicense
        // 读取 ini 文件
        File file = new File(iniFile);
        FileReader fr = new FileReader(file);
        BufferedReader br = new BufferedReader(fr);

        String line;
        StringBuilder content = new StringBuilder();
        while ((line = br.readLine()) != null) {
            content.append(line).append(System.lineSeparator());
            if (line.trim().equals(configLine)) {
                targetLineFound = true;
            }
        }
        br.close();

        // 如果未找到目标行,在内容的末尾追加文本
        if (!targetLineFound) {
            content.append(configLine).append(System.lineSeparator());

            // 将更新的内容写回 ini 文件
            FileWriter fw = new FileWriter(file);
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(content.toString());
            bw.close();
        }
    }

    /**
     * 通过正则表达匹配,搜索匹配的文件
     *
     * @param directoryPath 目录
     * @param pattern       文件匹配正则
     * @return
     */
    public static List<File> findFilesByPattern(String directoryPath, String pattern) {
        List<File> matchingFiles = new ArrayList<>();
        File directory = new File(directoryPath);

        if (directory.exists() && directory.isDirectory()) {
            File[] files = directory.listFiles((dir, name) -> name.matches(pattern));

            if (files != null) {
                for (File file : files) {
                    if (file.isFile()) {
                        matchingFiles.add(file);
                    }
                }
            }
        } else {
            System.out.println("无效的目录,或者找不到目录路径!");
        }

        return matchingFiles;
    }

    public static KeyPair generateKeyPair(int keySize) throws LMException {
        try {
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            keyGen.initialize(keySize, random);
            return keyGen.generateKeyPair();
        } catch (Exception e) {
            throw new LMException(e);
        }
    }

    /**
     * 生成公钥、私钥、授权码,并替换文件
     *
     * @param jarFilePath   需要替换公钥的 jar 文件
     * @param filePathInJar jar 包中的公钥文件路径
     * @throws LMException
     * @throws IOException
     */
    public static void generateKeyLicenseAndPatch(String jarFilePath, String filePathInJar) throws LMException, IOException {
        // 从 LMMain.generateKeyPair() 复制的代码
        KeyPair keyPair = generateKeyPair(2048);
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();
        System.out.println("\n--- PUBLIC KEY ---");
        String publicKeyContent = Base64.splitLines(Base64.encode(publicKey.getEncoded()), 76);
        System.out.println(publicKeyContent);
        writeFileToPath(publicKeyContent, publicKeyFile, "公钥");
        System.out.println("\n--- PRIVATE KEY ---");
        String privateKeyContent = Base64.splitLines(Base64.encode(privateKey.getEncoded()), 76);
        System.out.println(privateKeyContent);
        writeFileToPath(publicKeyContent, privateKeyFile, "私钥");
        writeFileToPath(publicKeyContent, jarPublicKey, "公钥");

        // 替换 jar 包中的 public key 文件
        replaceFileInJar(jarFilePath, filePathInJar, jarPublicKey.getAbsolutePath());

        // 从 LMMain.encryptLicense() 复制的代码
        LMProduct TEST_PRODUCT = new LMProduct("dbeaver-ue", "DB", "DBeaver Ultimate", "DBeaver Ultimate Edition", "23.1", LMProductType.DESKTOP, new Date(), new String[0]);
        String licenseID = LMUtils.generateLicenseId(TEST_PRODUCT);
        LMLicense license = new LMLicense(licenseID, LMLicenseType.ULTIMATE, new Date(), new Date(), (Date) null, LMLicense.FLAG_UNLIMITED_SERVERS, productID, productVersion, ownerID, ownerCompany, ownerName, ownerEmail);
        byte[] licenseData = license.getData();
        byte[] licenseEncrypted = LMEncryption.encrypt(licenseData, privateKey);

        String licenseContent = Base64.splitLines(Base64.encode(licenseEncrypted), 76);
        System.out.println("\n--- LICENSE ---");
        System.out.println(licenseContent);
        System.out.println("--- 处理完成,请打开软件使用以上授权码(已复制到剪切板) ---");
        copyToClipboard(licenseContent);
        writeFileToPath(licenseContent, licenseFile, "授权码");
    }

    /**
     * 写入并覆盖文件内容
     *
     * @param content  写入覆盖的内容
     * @param filePath 要写入的文件路径
     * @param tip      提示
     */
    public static void writeFileToPath(String content, File filePath, String tip) {
        try {
            Path path = Paths.get(filePath.getAbsolutePath());
            Files.write(path, content.getBytes());
            System.out.println(String.format("[%s内容]已成功写入文件:%s", tip, path));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 替换 jar 包中的指定路径的文件为新文件
     *
     * @param jarFilePath
     * @param targetFile
     * @param newFile
     * @throws IOException
     */
    public static void replaceFileInJar(String jarFilePath, String targetFile, String newFile) throws IOException {
        File tempFile = File.createTempFile("temp-file", ".tmp");
        File tempJarFile = File.createTempFile("temp-jar", ".tmp");

        boolean replaceSuccess = false;
        try (JarFile jarFile = new JarFile(new File(jarFilePath));
             JarOutputStream tempJarOutputStream = new JarOutputStream(new FileOutputStream(tempJarFile))) {

            // Copy the existing entries to the temp jar, excluding the entry to be replaced
            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();

                if (!entry.getName().equals(targetFile)) {
                    tempJarOutputStream.putNextEntry(new JarEntry(entry.getName()));
                    try (InputStream inputStream = jarFile.getInputStream(entry)) {
                        copyStream(inputStream, tempJarOutputStream);
                    }
                }
            }

            // 将新文件添加到临时jar
            tempJarOutputStream.putNextEntry(new JarEntry(targetFile));
            try (InputStream newFileStream = new FileInputStream(newFile)) {
                copyStream(newFileStream, tempJarOutputStream);
            }
            replaceSuccess = true;
        } finally {
            // 将原始 jar 文件替换为临时 jar 文件
            File originalJarFile = new File(jarFilePath);
            if (originalJarFile.delete() && tempJarFile.renameTo(originalJarFile) && replaceSuccess) {
                System.out.println(String.format("jar包中的文件 [%s] 替换成功!", targetFile));
            } else {
                System.out.println(String.format("jar包中的文件 [%s] 替换失败!", targetFile));
            }

            tempFile.delete();
            tempJarFile.delete();
        }
    }

    private static void copyStream(InputStream in, OutputStream out) throws IOException {
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = in.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
        }
    }

    /**
     * 将指定字符串复制到剪切板
     *
     * @param text
     */
    public static void copyToClipboard(String text) {
        StringSelection stringSelection = new StringSelection(text);
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        clipboard.setContents(stringSelection, null);
    }
}


使用源码的话改一下dbeaver安装的目录就OK了
不会使用源码的朋友可以试试以下方式
下载解压使用
https://pan.quark.cn/s/b0a37f2b8c0e?pwd=3Wbw


如果运行程序提示替换文件失败,可以手动替换试试
输入注册码时,需要断网,我试了几次,断网是能成功的,如果没成功,重新运行程序看看是不是jar包内的文件没有替换成功

image.png (14.8 KB, 下载次数: 2)

需要修改的参数

需要修改的参数

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
perch + 1 + 1 用心讨论,共获提升!

查看全部评分

推荐
Alleine 发表于 2026-3-29 22:04
发现host最好多加几个,不然还是会有可能联网检测到license 失效。
比如这些:
0.0.0.0 stats.dbeaver.com
0.0.0.0 telemetry.dbeaver.com
0.0.0.0 analytics.dbeaver.com
0.0.0.0 update.dbeaver.com
0.0.0.0 download.dbeaver.com
0.0.0.0 dbeaver.io
0.0.0.0 dbeaver.com
0.0.0.0 appcenter.ms
0.0.0.0 api.appcenter.ms
0.0.0.0 in.appcenter.ms
0.0.0.0 assets.appcenter.ms
沙发
不苦小和尚 发表于 2026-2-4 18:40
3#
Semoon 发表于 2026-2-4 20:13

确实自带JDK
4#
Andy1024 发表于 2026-2-5 09:24
感谢分享,正需要!
5#
alxe1528 发表于 2026-2-5 09:34

提示:
Error importing license
Error importing license
  License 'DB-1Z1MVZKB-ZHBL' not found
6#
冥界3大法王 发表于 2026-2-5 12:21
alxe1528 发表于 2026-2-5 09:34
提示:
Error importing license
Error importing license


看来可能不太完美啊。
7#
evea 发表于 2026-2-5 17:38
已经用上了  感谢

17702841034195.png (183.45 KB, 下载次数: 3)

17702841034195.png
8#
cgbchen 发表于 2026-2-5 18:19
强烈支持!好东西~
9#
hipj 发表于 2026-2-6 14:31
赞!25.3支持的数据库更多
10#
baronm 发表于 2026-2-6 23:56
本帖最后由 baronm 于 2026-2-6 23:59 编辑
alxe1528 发表于 2026-2-5 09:34
提示:
Error importing license
Error importing license

可以断网试试,我断网之后重新生成再导入license就成功了。
亦或者更改一下hosts文件,加入
127.0.0.1  dbeaver.com

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
alxe1528 + 1 + 1 我很赞同!

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-7-22 21:03

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表