新增RSA加解密和签名校验工具

This commit is contained in:
椰子 2022-07-13 15:03:38 +08:00
parent 774d2d0533
commit ab645264df
3 changed files with 232 additions and 0 deletions

View File

@ -8,6 +8,15 @@
<artifactId>utils</artifactId> <artifactId>utils</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties> <properties>
<maven.compiler.source>8</maven.compiler.source> <maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target> <maven.compiler.target>8</maven.compiler.target>

View File

@ -0,0 +1,173 @@
package com.simaek.util;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
/**
* RSA加密解密工具类
*
* @author Yaser Hsueh
*/
public final class RSAUtil {
private RSAUtil() {
throw new AssertionError();
}
private static final int defaultBits = 1024;
/**
* 最大解密明文长度
*/
private static final int MAX_DECRYPT_BLOCK = defaultBits >> 3;
/**
* 最大加密明文长度
*/
private static final int MAX_ENCRYPT_BLOCK = (defaultBits >> 3) - 11;
/**
* 生成秘钥对(默认长度1024Bits)
*/
public static KeyPair getKeyPair() throws Exception {
return getKeyPair(defaultBits);
}
/**
* 生成秘钥对
*/
public static KeyPair getKeyPair(int keySize) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(keySize);
return keyPairGenerator.generateKeyPair();
}
/**
* 获取公钥(Base64编码)
*/
public static String getPublicKey(KeyPair keyPair) {
PublicKey publicKey = keyPair.getPublic();
byte[] bytes = publicKey.getEncoded();
return byte2Base64(bytes);
}
/**
* 获取私钥(Base64编码)
*/
public static String getPrivateKey(KeyPair keyPair) {
PrivateKey privateKey = keyPair.getPrivate();
byte[] bytes = privateKey.getEncoded();
return byte2Base64(bytes);
}
/**
* 将Base64编码后的公钥转换成PublicKey对象
*/
public static PublicKey string2PublicKey(String pubStr) throws Exception {
byte[] keyBytes = base642Byte(pubStr);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(keySpec);
}
/**
* 将Base64编码后的私钥转换成PrivateKey对象
*/
public static PrivateKey string2PrivateKey(String priStr) throws Exception {
byte[] keyBytes = base642Byte(priStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(keySpec);
}
/**
* 公钥加密
*/
public static byte[] publicEncrypt(byte[] content, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return fragment(content, cipher, MAX_ENCRYPT_BLOCK);
}
/**
* 私钥解密
*/
public static byte[] privateDecrypt(byte[] content, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return fragment(content, cipher, MAX_DECRYPT_BLOCK);
}
/**
* 私钥签名
*/
public static String privateSign(byte[] content, String privateKey) throws Exception {
byte[] keyBytes = base642Byte(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateK);
signature.update(content);
return byte2Base64(signature.sign());
}
/**
* 公钥验签
*/
public static boolean publicVerify(byte[] content, String publicKey, String sign) throws Exception {
byte[] keyBytes = base642Byte(publicKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicK = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicK);
signature.update(content);
return signature.verify(base642Byte(sign));
}
/**
* 字节数组转Base64编码
*/
public static String byte2Base64(byte[] bytes) {
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(bytes);
}
/**
* Base64编码转字节数组
*/
public static byte[] base642Byte(String base64Key) {
Base64.Decoder decoder = Base64.getDecoder();
return decoder.decode(base64Key);
}
/**
* 分片处理长度超过RSA支持范文的明文数据
*
* @param content 加密/解密内容
* @param cipher 加密/解密算法
* @param slice 分片长度
* @return 分片加密/解密后整合的数据
*/
private static byte[] fragment(byte[] content, Cipher cipher, int slice) throws Exception {
int inputLength = content.length;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] cache;
int i = 0, offset = 0;
while (inputLength - offset > 0) {
if (inputLength - offset > slice) {
cache = cipher.doFinal(content, offset, slice);
} else {
cache = cipher.doFinal(content, offset, inputLength - offset);
}
byteArrayOutputStream.write(cache, 0, cache.length);
offset = slice * ++i;
}
byte[] resultBytes = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.close();
return resultBytes;
}
}

View File

@ -0,0 +1,50 @@
package com.simaek.util;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.security.KeyPair;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* 测试RSA加密工具类的加密和解密功能签名和校验功能
*
* @author Yaser Hsueh
* @see com.simaek.util.RSAUtil
*/
class RSAUtilTest {
private static String publicKeyString;
private static String privateKeyString;
@BeforeAll
static void before() throws Exception {
final KeyPair keyPair = RSAUtil.getKeyPair();
publicKeyString = RSAUtil.getPublicKey(keyPair);
privateKeyString = RSAUtil.getPrivateKey(keyPair);
}
@Test
void encryptAndDecrypt() throws Exception {
final String origin = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
final byte[] bytes = RSAUtil.publicEncrypt(origin.getBytes(), RSAUtil.string2PublicKey(publicKeyString));
final String base64 = RSAUtil.byte2Base64(bytes);
final byte[] decrypt = RSAUtil.privateDecrypt(RSAUtil.base642Byte(base64), RSAUtil.string2PrivateKey(privateKeyString));
final String result = new String(decrypt);
System.out.println("Original: " + origin);
System.out.println("Encrypted: " + base64);
System.out.println("Decrypted: " + result);
assertEquals(origin, result);
}
@Test
void signAndVerify() throws Exception {
final String origin = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
final String sign = RSAUtil.privateSign(origin.getBytes(), privateKeyString);
final boolean verify = RSAUtil.publicVerify(origin.getBytes(), publicKeyString, sign);
System.out.println("Original: " + origin);
System.out.println("Signature: " + sign);
assertTrue(verify);
}
}