如何实现对java生成的.class加密?

背景

    在以往很多商业的系统,除了知识产权以外很多代码都是加密所以我们很难去直接去读取原码,并且这样通过加密.class文件有效的对自已的产品或系统进行保护。

实现原理

    生成.class后将原来的.class进行加密或者取反,因为.class里面最终生成的是二进制0101这类的二进制代码,当然也可以通过一些md5或一些RES等加密方式进行加密;以下案例是参考网上一些案例而来,参考文章在文末,其实原理一样。解密的时候通过去实现java的classLoader将原来的.findClass 进行改造,就可以实现针对性的加密(tomcat实现打破双亲委派也是这样的哦~),其实很简单参考如下:

代码下载地址:https://gitee.com/hong99/jdk8.git

实现代码

package com.encryption.demo;

/**
 * @description: 测试方法
 * @author hong
 * @date
 * @version 1.0
 */
public class TestContent {
    public void hong(){
        System.out.println("my name is hong!!!");
    }
}
package com.encryption.demo;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 加解密工具
 */
public class EncryptionUtils extends ClassLoader{




    /**统一加密/解密 密钥 **/
    private int password = 0xFF;

    private static String parentPath ="D://";

    /**
     * 加密方法
     * @param pathUrl 类名称
     */
    public void encryptionClass(String pathUrl){
        if(null==pathUrl || "".equals(pathUrl)){
            System.out.println("路径不能为空!");
            return;
        }
        String path =new File(pathUrl).getAbsolutePath();

        //获取文件
        File file = new File(path);
        if(!file.exists()){
            throw new NoClassDefFoundError("没有找到文件!");
        }
        //获取文件夹目录
        File awaitFileFolder = new File(file.getParent() + File.separator);
        //不存在则创建目录
        if(!awaitFileFolder.exists()){
            awaitFileFolder.mkdirs();
        }
        File encryptFolder = new File(awaitFileFolder.getParent() + File.separator );
        if (!encryptFolder.exists()) {
            encryptFolder.mkdirs();
        }
        //加密后文件指定存放目录
// String encryptedFile = file.getParent() + File.separator + File.separator + file.getName();
        String encryptedFile = parentPath + file.getName();
        try (
                FileInputStream fileInputStream = new FileInputStream(file);
                BufferedInputStream bis = new BufferedInputStream(fileInputStream);
                FileOutputStream fileOutputStream = new FileOutputStream(encryptedFile);
                BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream)
        ) {
            // 加密
            int data;
            while ((data = bis.read()) != -1) {
                bos.write(data ^ password);
            }
            bos.flush();
        } catch (IOException e) {
            System.out.println("加密异常!");
            e.printStackTrace();
        }
        // 现在将原来未加密的文件删除
       // awaitFileFolder.delete();

        // 先获取加密前文件绝对路径名,然后修改后缀,再创建File对象
        File oldFile = new File(parentPath +file.getName()+ "hong");
        // 删除未加密前的文件
// if (oldFile.exists()) {
// oldFile.delete();
// }
        // 根据加密后的文件创建File对象
        File newEncryptedFile = new File(encryptedFile);
        // 将加密后的对象重命名,这时加密后的文件就把加密前的文件替换掉了,这就是为什么刚开始加密后的文件需要单独放的原因
        newEncryptedFile.renameTo(oldFile);
        // 删除之前的加密文件夹下面的加密文件
        newEncryptedFile.getParentFile().delete();
    }

    /**
     * 解密方法
     * @param pathUrl 需要解密的文件名
     */
    protected byte[] decryptClass(String pathUrl) {
        String path;
        if (!pathUrl.contains(".class")) {
            path = new File(pathUrl).getAbsolutePath();
        } else {
            path = pathUrl;
        }
        //获取待解密文件
        File decryptClassFile = new File(path);
        if (!decryptClassFile.exists()) {
            System.out.println("decryptClass() File:" + path + " not found!");
            return null;
        }
        byte[] result = null;
        BufferedInputStream bis = null;
        ByteArrayOutputStream bos = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(decryptClassFile));
            bos = new ByteArrayOutputStream();
            // 解密
            int data;
            while ((data = bis.read()) != -1) {
                bos.write(data ^ password);
            }
            bos.flush();
            result = bos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bis != null) {
                    bis.close();
                }
                if (bos != null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] bytes = decryptClass(name);
        int length = bytes ==null?0:bytes.length;
        return defineClass("com.encryption.demo.TestContent",bytes,0,length);
    }

    /**
     * 运行主类
     * @param args
     * @throws ClassNotFoundException
     */
    public static void main(String[] args) throws ClassNotFoundException {
        //获取项目路劲
        File file = new File(EncryptionUtils.class.getResource("/").getPath());
        //加解密工具
        EncryptionUtils encryptionUtils = new EncryptionUtils();
        //解析路劲
        encryptionUtils.encryptionClass(file.getPath()+"/com/encryption/demo/TestContent.class");
        //获取解析后的文件
        Class<?> c = encryptionUtils.findClass(parentPath+"/TestContent.classhong");
        if(c != null){
            try {
                Object obj = c.newInstance();
                //获取方法
                Method method = c.getDeclaredMethod("hong");
                //通过反射调用Test类的say方法
                method.invoke(obj);
            } catch (InstantiationException | IllegalAccessException
                    | NoSuchMethodException
                    | SecurityException |
                    IllegalArgumentException |
                    InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }

}

结果

Connected to the target VM, address: '127.0.0.1:49636', transport: 'socket'
my name is hong!!!
Disconnected from the target VM, address: '127.0.0.1:49636', transport: 'socket'

Process finished with exit code 0

最后

    看过很多实现的方法大同小异,主要是用来学习,以备将来在一些特定场景上面会使用到。当然以上太简单了,如果不懂类加载机制的同学可以参考以往文章。(最近疫情有点反弹,出门注意安全防护。祝各位,一切顺利,未来可期!!!)

参考文章:

https://www.cnblogs.com/peashooter/p/9456402.html

https://blog.csdn.net/qq_28082757/article/details/81481215

https://www.jianshu.com/p/fa127d08e281

3bdc53a8cbf9bf9c776a625b315c6dec.png

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
软件介绍 本工具是对java class文件进行加密保护防止反编译的工具!本工具全面支持linux/unix/windows操作系统。 继推出v1.0版本后,获得了用户大量的支持与的反馈,我们再次推出本v2.0版,对加密算法进行了更大的改进,安全性大大提升! 众所周知,java编译后的class文件是一种中间字节字文件, 很容易被反编译工具反编译,而传统的java源代码保护方法基本都是采用混淆的方式, 但这样会带来很多麻烦,而且也不能真正保护class文件, 本工具是对class文件进行加密,采用jni的方式解密运行, 加密算法达到256位,加密后的class文件不可能被破解,反编译工具也对加密后的class文件无能为力。 运行方式: 运行时,要能正确的加载加密后的class文件, 必须使用我们提供的动态链接库classloader.dll(windows操作系统)或者libclassloader.so(Linux、Unix操作系统)。 执行java时带上参数-agentlib:\classloader 注意此处不要后缀名.dll(或者.so)。 如: 我把classloader.dll放在C:\目录下; 运行加密后的class文件命令如下: windows下执行javajava -agentlib:C:\classloader Sample Linux、Unix等系列操作系统下执行javajava -agentlib:/home/classloader Sample 或者把libclassloader.so拷贝到如“/home/yzj/jdk1.6.0_23/jre/lib/i386/”这jdk的运行目录下, 然后执行java如:java -agentlib:classloader Sample 当然如果class文件没加密,这样运行也不会出错! 应用场合: 独立的应用程序,运行java时,带上参数-agentlib:\classloader Tomcat、Jboss等Java application server修改启动脚本, 把执行java的命令行后面加上参数-agentlib:\classloader 适应环境: 操作系统:所有操作系统,Windows系统、Linux/Unix,只是运行时, 使用的动态链接库文件不一样而已,其它配置完全一样。 jdk必须1.5以上。 备注:如果下载站下载下来的程序有运行bug,请从上面两个下载地址更新软件。并给我们留言!谢谢... 升级提示:v2.1相比v2.0修改了一个注册bug。
简要介绍: 本工具是对java class文件进行加密保护的工具!本工具全面支持linux/unix/windows操作系统。 众所周知,java编译后的class文件是一种中间字节字文件, 很容易被反编译工具反编译,而传统的java源代码保护方法基本都是采用混淆的方式, 但这样会带来很多麻烦,而且也不能真正保护class文件, 本工具是对class文件进行加密,采用jni的方式解密运行, 加密算法达到256位,加密后的class文件不可能被破解,反编译工具也对加密后的class文件无能为力。 运行方式: 运行时,要能正确的加载加密后的class文件, 必须使用我们提供的动态链接库classloader.dll(wndows操作系统)或者libclassloader.so(Linux、Unix操作系统)。 执行java时带上参数-agentlib:\classloader 注意此处不要后缀名.dll(或者.so)。 如: windows下执行javajava -agentlib:C:\classloader HelloWorld Linux、Unix等系列操作系统下执行javajava -agentlib:/home/classloader HelloWorld 应用场合: 独立的应用程序,运行java时,带上参数-agentlib:\classloader Tomcat、Jboss等Java application server修改启动脚本, 把执行java的命令行后面加上参数-agentlib:\classloader 适应环境: 操作系统:所有操作系统,Windows系统、Linux/Unix,只是运行时, 使用的动态链接库文件不一样而已,其它配置完全一样。 jdk必须1.5以上。 下载地址: http://www.cr8ge.com/admin/upload/2011020917102317195.rar http://www.kmcxzs.cn/admin/upload/2011020917131925480.rar
<br> 系统介绍<br> JavaClass文件加密专家是一款针对Java应用程序Class二进制文件加密的软件,系统核心由纯C语言编写,运行效率极<br>高。传统的Java程序加密的方式多为代码混迹方式,但是无论多么复杂的混迹方式,在使用Java代码反编译程序后还是可以看<br>到代码的逻辑结构,这样并没有彻底的保护好您的代码。<br> JavaClass文件加密专家通过分析Class文件的结构,将Class二进制代码中耗时较多的部份抽出并替换为Native C代码,<br>并且使用1024位加密算法将Class文件数据加密,任何Java反编译工具均不可能对加密后的文件进行破解。<br><br> 系统特点<br> 1.采用纯C语言开发的内核算法,运行速度极快。<br> 2.抽出了JVM虚拟机耗时较多的代码,替换为原生C代码去执行,加密后的Class文件运行效率比加密前还要快。<br> 3.彻底保护您的Class二进制文件,任何通过分析Class文件结构来实现反编译的工具均不能对加密后的文件反编译。<br><br> 使用方法<br> 在要分发您的Java应用程序前,使用JavaClass文件加密专家对所有的Class文件或Jar文件进行加密,在您的系统运行参<br>数中加入以下内容:<br> 1.WEB应用程序<br> 在您使用的Java Web Server的启动参数中,增加以下内容: -agentlib:<brainysoft.dll的存放目录>\brainysoft即<br>可。<br> 举例 :<br> 假设您的Java Web Server为Tomcat,以Windows平台为例,Tomcat的存放目录为C:\Tomcat 5.5 ,brainysoft.dll存<br>放在c:\windows目录中,在Tomcat的bin目录中新建一个文件setenv.bat,setenv.bat中的内容:set JAVA_OPTS= -<br>agentlib:c:\windows\brainysoft %JAVA_OPTS%,保存setenv.bat文件,重新启动Tomcat后就可以正确加载加密类了。<br> 2.独立的Java应用程序<br> 在您的应用程序运行参数中加入以下内容: -agentlib:<brainysoft.dll的存放目录>\brainysoft<br> 举例:<br> Test.class文件的package为com.test, 在运行您的Test.class或Jar时使用以下方式:java -agentlib:<br><brainysoft.dll的存放目录>\brainysoft <-classpath 您的.jar文件> com.test.Test。<br> 3.EJB组件<br> 运行加密后的EJB组件的方式与运行WEB应用程序类似,找到您的EJB容器的启动配置文件,加入-agentlib:<br><brainysoft.dll的存放目录>\brainysoft 即可。<br><br> 应用环境<br> JavaClass文件加密专家只能用在JDK1.5及更新版本的JDK中,您在Windows平台下加密后的Class文件不必再修改就可以应<br>用于Linux、Unix等平台中。<br>
Java可以使用Apache POI库来对生成的Excel进行加密。下面是一个简单的示例: ```java import java.io.FileOutputStream; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.poifs.crypt.EncryptionInfo; import org.apache.poi.poifs.crypt.Encryptor; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ExcelEncryptionExample { public static void main(String[] args) throws Exception { // 创建一个新的Excel工作簿 XSSFWorkbook workbook = new XSSFWorkbook(); // 向工作簿中添加一些数据和格式化 // 创建一个加密信息对象 EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile); // 创建一个加密器对象 Encryptor enc = info.getEncryptor(); // 设置加密密码 enc.confirmPassword("password"); // 创建一个输出流 FileOutputStream fos = new FileOutputStream("encrypted.xlsx"); // 使用加密器将工作簿写入输出流 workbook.write(enc.getDataStream(fos)); // 关闭输出流和工作簿 fos.close(); workbook.close(); } } ``` 在上面的示例中,我们创建了一个新的Excel工作簿,并使用EncryptionInfo和Encryptor对象将其加密。在这个例子中,我们使用了一种名为“agile”的加密模式,但是POI库支持多种加密模式。请注意,在设置密码时,我们使用了enc.confirmPassword("password")方法来设置加密密码。 最后,我们将加密后的工作簿写入一个输出流,并关闭输出流和工作簿。现在,生成的Excel文件将受到密码保护,只有知道密码的人才能打开和编辑文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值