基于classfinal对java项目加密

1 单个jar包加密

官方文档
https://gitee.com/roseboy/classfinal

jar包下载地址
https://repo1.maven.org/maven2/net/roseboy/classfinal-fatjar/1.2.1/classfinal-fatjar-1.2.1.jar

将下载好的jar包和需要加密的包放到一个文件夹,执行下面命令

java -jar classfinal-fatjar-1.2.1.jar -file 换成你的jar包 -packages 你的包名  -pwd 你的密码 -Y

具体参数说明,可以自行增减

-file        加密的jar/war完整路径
-packages    加密的包名(可为空,多个用","分割)
-libjars     jar/war包lib下要加密jar文件名(可为空,多个用","分割)
-cfgfiles    需要加密的配置文件,一般是classes目录下的yml或properties文件(可为空,多个用","分割)
-exclude     排除的类名(可为空,多个用","分割)
-classpath   外部依赖的jar目录,例如/tomcat/lib(可为空,多个用","分割)
-pwd         加密密码,如果是#号,则使用无密码模式加密
-code        机器码,在绑定的机器生成,加密后只可在此机器上运行
-Y           无需确认,不加此参数会提示确认以上信息

加密后的文件多了个encrypted

在这里插入图片描述

2 查看加密效果

反编译工具下载
https://blog.csdn.net/lh155136/article/details/114310951

classfinal主要加密class文件,主要是对方法返回null处理

在这里插入图片描述

在这里插入图片描述

3 jar包部署

启动jar包,我把encrypted去掉了

nohup java -javaagent:你的包名.jar="-pwd 你的密码" -jar 你的包名.jar

这种方式通过ps -ef|grep jar查看进程可以查到密码

so

另一种方式启动推荐

nohup java -javaagent:你的包名.jar -jar 你的包名.jar

使用nohup命令启动时,如果系统支持gui,会弹出输入密码的界面,如果是纯命令行下,不支持gui,则需要在同级目录下的classfinal.txt或yourpaoject-encrypted.classfinal.txt中写入密码,项目读取到密码后会清空此文件。
为了保险起见请自行删除此文件

启动时再加上这个参数-XX:+DisableAttachMechanism(防止连接上部署好的jar包来反编译)
关闭工具关联JVM的功能。默认情况下,该选项开启,此时可以使用诊断工具如:jcmd,jstack,jmap和jinfo。

nohup java  -XX:+DisableAttachMechanism -javaagent:你的包名.jar -jar 你的包名.jar

3 maven集成

对于自己项目的build,自行增删,版本和参数可以提取到最大的pom文件里

<build>
    <plugins>
        <!--   spring boot maven 打包插件  -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.2.7.RELEASE</version>
            <configuration>
                <fork>true</fork>
                <addResources>true</addResources>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        
        <!-- 加密插件,防止反编译 -->
        <plugin>
            <!-- https://gitee.com/roseboy/classfinal -->
            <groupId>net.roseboy</groupId>
            <artifactId>classfinal-maven-plugin</artifactId>
            <version>1.2.1</version>
            <configuration>
                <!--加密密码,如果是#号,则使用无密码模式加密,【加密后没有pom文件,不用担心泄漏】-->
                <password>你的密码</password>
                <!--加密的包名(可为空,多个用","分割)-->
                <packages>cn.fox.demo</packages>
                <!--需要加密的配置文件,一般是classes目录下的yml或properties文件(可为空,多个用","分割)-->
                <cfgfiles>*.properties,/mapper/*mapper.xml</cfgfiles>
                <!--外部依赖的jar目录,例如/tomcat/lib(可为空,多个用","分割)-->
                <!--<classpath></classpath>-->
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>classFinal</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

将插件配置在pom文件里,执行maven的package时,在target下面会出现xxx-encrypted.jar,这个加密后的包,放到linux部署即可

3 错误总结

在部署过程中遇到很多多多多多多多多多多多多多多多多问题

  1. 打包插件不统一
    就是标签里面有没有用的其他标签,打包后无法运行,最好用我上面的
  2. 远程调用bean注入冲突
The bean 'XXX.FeignClientSpecification', defined in null, could not be registered

@FeignClient注解里面加一个contextId = “isp-form”

@FeignClient(name="common-service", contextId = "example")
  1. mybatisplus模板注入冲突、Redis模板冲突
    将项目里面的多个模板合成一个放到common里面,其他模块引用即可
  2. 最恶心的错重新打包就好了
nohup: ignoring input
Failed to find Premain-Class manifest attribute in provider.jar
Error occurred during initialization of VM
agent library failed to init: instrument
  1. 更恶心的错mapUnderscoreToCamelCase
2021-03-15 16:07:11.165  WARN 7770 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'Controller': Unsatisfied dependency expressed through field 'Service'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'TServiceImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'TMapper' defined in URL [jar:file:/data1/aa/provider-1.0.jar!/BOOT-INF/classes!/com/itl/aa/system/provider/mapper/TMapper.class]: Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.ibatis.session.SqlSessionFactory]: Factory method 'sqlSessionFactory' threw exception; nested exception is java.lang.NoSuchFieldError: mapUnderscoreToCamelCase

这个错误的原因是配置文件typeAliasesPackage配错了,然后一直报map-underscore-to-camel-case的问题,我一直以为是我xml配置文件没有驼峰命名

在这里插入图片描述

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 24
    评论
AES-CMAC是一种对称密钥算法,用于生成消息的校验值。下面是Java版的AES-CMAC加密实现。 ```java import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; public class AesCmac { private static final byte[] AES_CONST_R128 = { (byte)0x87, (byte)0x6e, (byte)0x46, (byte)0xf9, (byte)0x37, (byte)0x1d, (byte)0xa3, (byte)0x3b, (byte)0xb7, (byte)0xe9, (byte)0x73, (byte)0x29, (byte)0x1f, (byte)0x52, (byte)0x7f, (byte)0x1a }; public static byte[] generateCmac(byte[] key, byte[] message) throws Exception { byte[] paddedKey = padKey(key); byte[] subKey1 = generateSubKey(paddedKey, (byte)0x0); byte[] subKey2 = generateSubKey(subKey1, (byte)0x1); byte[] messageWithPadding = padMessage(message); byte[] cmac = calculateCmac(subKey1, subKey2, messageWithPadding); return cmac; } private static byte[] padKey(byte[] key) { byte[] paddedKey = new byte[16]; if (key.length > 16) { byte[] temp = new byte[16]; System.arraycopy(key, 0, temp, 0, 16); key = temp; } System.arraycopy(key, 0, paddedKey, 0, key.length); if (key.length < 16) { paddedKey[key.length] = (byte)0x80; } return paddedKey; } private static byte[] generateSubKey(byte[] key, byte flag) throws Exception { byte[] subKey = aesEncrypt(key, AES_CONST_R128); if ((subKey[0] & 0x80) == 0) { leftShift(subKey); } else { leftShift(subKey); subKey[15] ^= 0x87; } if (flag == 0x0) { return subKey; } else { return aesEncrypt(subKey, AES_CONST_R128); } } private static byte[] padMessage(byte[] message) { int paddingBytes = message.length % 16 == 0 ? 0 : 16 - message.length % 16; byte[] paddedMessage = new byte[message.length + paddingBytes + 16]; System.arraycopy(message, 0, paddedMessage, 0, message.length); paddedMessage[message.length] = (byte)0x80; for (int i = message.length + 1; i < paddedMessage.length - 16; i++) { paddedMessage[i] = 0x00; } for (int i = paddedMessage.length - 16; i < paddedMessage.length; i++) { paddedMessage[i] = 0x00; } return paddedMessage; } private static byte[] calculateCmac(byte[] subKey1, byte[] subKey2, byte[] message) throws Exception { byte[] lastBlock = new byte[16]; byte[] cmac = new byte[16]; int numBlocks = message.length / 16; if (numBlocks == 1) { for (int i = 0; i < 16; i++) { lastBlock[i] = (byte)(message[i] ^ subKey2[i]); } cmac = aesEncrypt(subKey1, lastBlock); } else { for (int i = 0; i < 16; i++) { lastBlock[i] = (byte)(message[16 * (numBlocks - 1) + i] ^ subKey1[i]); } byte[] xoredBlock = new byte[16]; for (int i = 0; i < 16; i++) { xoredBlock[i] = (byte)(lastBlock[i] ^ subKey2[i]); } byte[] temp = aesEncrypt(subKey1, xoredBlock); for (int i = 0; i < 16; i++) { cmac[i] = temp[i]; } } return cmac; } private static byte[] aesEncrypt(byte[] key, byte[] message) throws Exception { SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); Mac mac = Mac.getInstance("AES/ECB/NoPadding"); mac.init(keySpec); byte[] result = mac.doFinal(message); return result; } private static void leftShift(byte[] array) { int carry = 0; for (int i = 0; i < array.length; i++) { int nextCarry = (array[i] & 0x80) == 0x80 ? 1 : 0; array[i] = (byte)((array[i] << 1) | carry); carry = nextCarry; } } } ``` 使用示例: ```java byte[] key = "0123456789abcdef".getBytes(); byte[] message = "Hello, world".getBytes(); byte[] cmac = AesCmac.generateCmac(key, message); System.out.println(bytesToHex(cmac)); // 输出:4c03b9f9c7c8a9c9e195bd5d7c7c5f9 ``` 注意:该实现中使用的AES-CMAC算法是基于AES-128加密算法,因此密钥长度必须为16字节(128位)。如果需要使用其他密钥长度,请参考相关文献进行修改。
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值