引入 pom.xml 依赖:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.14</version>
</dependency>
工具类:
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
/**
* RSA加解密工具类 <br />
*
* <ol>
* <li>公钥加密,私钥解密</li>
* <li>私钥解密,公钥解密</li>
* </ol>
*
*/
public class RSAUtil
{
/**
* 最大加密字节数 <br/>
* 超出最大字节数需要分组加密
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* 最大解密字节数 <br/>
* 超出最大字节数需要分组加密
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* 公钥加密
*
* @param publicKeyText (经过 Base64 编码)公钥
* @param text (原始)明文
* @return (经过 Base64 编码)密文
* @throws Exception
*/
public static String encryptByPublicKey(String publicKeyText, String text) throws Exception
{
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// byte[] result = cipher.doFinal(text.getBytes());
byte[] result = doBlockEncrypt(text.getBytes(), cipher);
return Base64.encodeBase64String(result);
}
/**
* 私钥加密
*
* @param privateKeyText (经过 Base64 编码)私钥
* @param text (原始)明文
* @return (经过 Base64 编码)密文
* @throws Exception
*/
public static String encryptByPrivateKey(String privateKeyText, String text) throws Exception
{
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
// byte[] result = cipher.doFinal(text.getBytes());
byte[] result = doBlockEncrypt(text.getBytes(), cipher);
return Base64.encodeBase64String(result);
}
/**
* 分段加密
* @param textBytes (原始)明文字节数组
* @param cipher 加密器
* @return
* @throws Exception
*/
private static byte[] doBlockEncrypt(byte[] textBytes, Cipher cipher) throws Exception
{
int length = textBytes.length;
int offSet = 0;
byte[] resultBytes = {};
byte[] cache;
while (length - offSet > 0)
{
if (length - offSet > MAX_ENCRYPT_BLOCK)
{
cache = cipher.doFinal(textBytes, offSet, MAX_ENCRYPT_BLOCK);
offSet += MAX_ENCRYPT_BLOCK;
}
else
{
cache = cipher.doFinal(textBytes, offSet, length - offSet);
offSet = length;
}
resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);
System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);
}
return resultBytes;
}
/**
* 公钥解密
*
* @param publicKeyText (经过 Base64 编码)公钥
* @param text (经过 Base64 编码)密文
* @return (解密)明文
* @throws Exception
*/
public static String decryptByPublicKey(String publicKeyText, String text) throws Exception
{
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
// byte[] result = cipher.doFinal(Base64.decodeBase64(text));
byte[] result = doBlockDecrypt(Base64.decodeBase64(text), cipher);
return new String(result);
}
/**
* 私钥解密
*
* @param privateKeyText (经过 Base64 编码)私钥
* @param text (经过 Base64 编码)密文
* @return (解密)明文
* @throws Exception
*/
public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception
{
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
// byte[] result = cipher.doFinal(Base64.decodeBase64(text));
byte[] result = doBlockDecrypt(Base64.decodeBase64(text), cipher);
return new String(result);
}
/**
* 分段解密
* @param textBytes (经过 Base64 解码)密文字节数组
* @param cipher 解密器
* @return
* @throws Exception
*/
private static byte[] doBlockDecrypt(byte[] textBytes, Cipher cipher) throws Exception
{
int length = textBytes.length;
int offSet = 0;
byte[] resultBytes = {};
byte[] cache;
while (length - offSet > 0)
{
if (length - offSet > MAX_DECRYPT_BLOCK)
{
cache = cipher.doFinal(textBytes, offSet, MAX_DECRYPT_BLOCK);
offSet += MAX_DECRYPT_BLOCK;
}
else
{
cache = cipher.doFinal(textBytes, offSet, length - offSet);
offSet = length;
}
resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);
System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);
}
return resultBytes;
}
/**
* 构建RSA密钥对
*
* @return Base64 编码后的 RAS 秘钥
* @throws NoSuchAlgorithmException
*/
public static RSAKeyPair generateKeyPair() throws NoSuchAlgorithmException
{
// 生成秘钥对(公钥、私钥)
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
// 对秘钥进行 Base64 编码
String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
RSAKeyPair rsaKeyPair = new RSAKeyPair(publicKeyString, privateKeyString);
return rsaKeyPair;
}
/**
* RSA密钥对对象
*/
public static class RSAKeyPair
{
private String publicKey;
private String privateKey;
public RSAKeyPair(String publicKey, String privateKey)
{
this.publicKey = publicKey;
this.privateKey = privateKey;
}
public String getPublicKey() {
return publicKey;
}
public String getPrivateKey() {
return privateKey;
}
}
/**
* 生成 licence
* @param privateKey
* @param text
* @return
* @throws Exception
*/
public static String generateLicence(String privateKey, String text) throws Exception
{
return RSAUtil.encryptByPrivateKey(privateKey, text);
}
/**
* 解析 licence
* @param publicKey
* @param text
* @return
* @throws Exception
*/
public static String resolveLicence(String publicKey, String text)
{
try
{
return RSAUtil.decryptByPublicKey(publicKey, text);
}
catch (Exception e)
{
throw new ParseLicenceException();
}
}
}
测试用例:
@Test
void test() throws Exception
{
String text = "i am a good man!";
RSAUtil.RSAKeyPair keyPair = RSAUtil.generateKeyPair();
System.out.println("\n");
System.out.println("公钥:" + keyPair.getPublicKey());
System.out.println("私钥:" + keyPair.getPrivateKey());
System.out.println("\n");
test1(keyPair, text);
System.out.println("\n");
test2(keyPair, text);
}
/**
* 公钥加密,私钥解密
*/
private static void test1(RSAUtil.RSAKeyPair keyPair, String source) throws Exception
{
System.out.println("***************** 公钥加密,私钥解密 开始 *****************");
String cipherText = RSAUtil.encryptByPublicKey(keyPair.getPublicKey(), source);
String decipherText = RSAUtil.decryptByPrivateKey(keyPair.getPrivateKey(), cipherText);
System.out.println("加密前:" + source);
System.out.println("加密后:" + cipherText);
System.out.println("解密后:" + decipherText);
if (source.equals(decipherText)) {
System.out.println("解密字符串和原始字符串一致,解密成功");
} else {
System.out.println("解密字符串和原始字符串不一致,解密失败");
}
System.out.println("***************** 公钥加密,私钥解密 结束 *****************");
}
/**
* 私钥加密,公钥解密
*
* @throws Exception
*/
private static void test2(RSAUtil.RSAKeyPair keyPair, String source) throws Exception
{
System.out.println("***************** 私钥加密,公钥解密 开始 *****************");
String cipherText = RSAUtil.encryptByPrivateKey(keyPair.getPrivateKey(), source);
String decipherText = RSAUtil.decryptByPublicKey(keyPair.getPublicKey(), cipherText);
System.out.println("加密前:" + source);
System.out.println("加密后:" + cipherText);
System.out.println("解密后:" + decipherText);
if (source.equals(decipherText)) {
System.out.println("解密字符串和原始字符串一致,解密成功");
} else {
System.out.println("解密字符串和原始字符串不一致,解密失败");
}
System.out.println("***************** 私钥加密,公钥解密 结束 *****************");
}