- 将认证信息使用 AES 加密
- 使用 RSA 算法,私钥签名公钥验签来确保 AES 加密后的内容没有被篡改
- 当然只能防君子,反编译或者修改本地时间戳都会被破解
下面是代码示例,会用到 hutool 工具类
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.symmetric.AES;
import java.nio.charset.StandardCharsets;
import java.security.Signature;
public class LicenseUtils {
// 测试
public static void main(String[] args) throws Exception {
String publicKey = RsaDemo.getPublicKey();
String privateKey = RsaDemo.getPrivateKey();
String aesKey = "2131jcefue312123";
String s = LicenseUtils.create(aesKey, privateKey, "3249234234", 1695544844000L);
System.out.println("许可证:" + s);
boolean verify = LicenseUtils.verify(aesKey, publicKey, s);
System.out.println("验证是否成功:" + verify);
}
// 创建 许可证
// 我这里要加密的内容,就只有一个项目ID和一个到期时间
public static String create(String aesKey, String privateKey, String projectId, long time) {
String body = projectId + "." + time;
String s1 = aesEncryptHex(aesKey, body);
String sign = rsaSign(privateKey, s1);
return s1 + "." + sign;
}
// 验证许可证是否有效,true表示有效
// 如何验证有效期,可以自行做逻辑处理
public static boolean verify(String aesKey, String publicKey, String content) {
String[] split = content.split("\\.");
String body = split[0];
String sign = split[1];
if (verifySign(publicKey, body, sign)) {
String s = aesDecryptStr(aesKey, body);
String[] split1 = s.split("\\.");
long time = Long.parseLong(split1[1]);
return System.currentTimeMillis() <= time;
}
return false;
}
// AES 加密
private static String aesEncryptHex(String aesKey, String body) {
AES aes = SecureUtil.aes(aesKey.getBytes());
return aes.encryptHex(body);
}
// AES 解密
private static String aesDecryptStr(String aesKey, String body) {
AES aes = SecureUtil.aes(aesKey.getBytes());
return aes.decryptStr(body, CharsetUtil.CHARSET_UTF_8);
}
// 使用公钥验证签名
private static boolean verifySign(String publicKey, String body, String sign) {
RSA rsa = new RSA(null, publicKey);
try {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(rsa.getPublicKey());
signature.update(body.getBytes(StandardCharsets.UTF_8));
return signature.verify(HexUtil.decodeHex(sign));
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
// 使用私钥 SHA256withRSA 签名
private static String rsaSign(String privateKey, String body) {
RSA rsa = new RSA(privateKey, null);
try {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(rsa.getPrivateKey());
signature.update(body.getBytes(StandardCharsets.UTF_8));
byte[] signatureBytes = signature.sign();
return HexUtil.encodeHexStr(signatureBytes);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("createLicenseErr");
}
}
}