rsa作为一种安全高效的非对称加密方法,经常在需要身份验证和加解密场景下使用。
由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全。
base64编码工具依赖jar
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency>
RSA加解密和签名验签的工具类
签名方法sign()和验证签名verify()方法是一对,配合使用。代码如下:
public class RsaUtils {
public static final String KEY_ALGORITHM = "RSA";
public static final String UTF8 = "utf-8";
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* 私钥签名
*/
public static String sign(String content, String privateKeyPem) {
try {
byte[] encodedKey = privateKeyPem.getBytes();
encodedKey = Base64.decode(encodedKey);
PrivateKey privateKey = KeyFactory.getInstance(KEY_ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
Signature signature = Signature.getInstance("SHA256WithRSA");
signature.initSign(privateKey);
signature.update(content.getBytes(UTF8));
byte[] signed = signature.sign();
return new String(Base64.encode(signed));
} catch (Exception ex) {
String errorMessage = "RSA签名异常,content=" + content + " privateKeySize=" + privateKeyPem.length() + " reason=" + ex.getMessage();
throw new RuntimeException(errorMessage, ex);
}
}
/**
* 公钥验签
*/
public static boolean verify(String content, String sign, String publicKeyPem) {
try {
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
byte[] encodedKey = publicKeyPem.getBytes();
encodedKey = Base64.decode(encodedKey);
PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
Signature signature = Signature.getInstance("SHA256WithRSA");
signature.initVerify(publicKey);
signature.update(content.getBytes(UTF8));
return signature.verify(Base64.decode(sign.getBytes()));
} catch (Exception ex) {
String errorMessage = "RSA验签异常,content=" + content + " sign=" + sign + " publicKey=" + publicKeyPem + " reason=" + ex.getMessage();
throw new RuntimeException(errorMessage, ex);
}
}
/**
* 私钥加密
*/
public static String encryptByPrivateKey(String text, String privateKey) throws Exception {
byte[] keyBytes = Base64.decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateK);
byte[] data = text.getBytes(StandardCharsets.UTF_8);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
byte[] base64Arr = Base64.encode(encryptedData);
String base64 = new String(base64Arr, "utf-8");
return base64;
}
/**
* 公钥解密
*/
public static String decryptByPublicKey(String base64Str, String publicKey)
throws Exception {
byte[] keyBytes = Base64.decode(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicK);
byte[] encryptedData = Base64.decode(base64Str);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
String source = new String(decryptedData, "utf-8");
return source;
}
}
如何使用?
测试代码如下:
public class RsaUtilsTest{
static String PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAND7PIe2no4HwLDeFq5muHjigwktYnXFPKSYHKbOgI/sONaqFojfqR5Aq6XdSRA6sj0gVsFTRI/xY96nWu5BiJ5iY9Y1RH83hd0uWnWEuWraJb1Q/D1haWmCRNDfcLEzHHlDbXQabP62fwfb6t7WJfC4NKvtzRXXVKYQ+zWQDqLNAgMBAAECgYAh+ebCbcdjchE68DCh1CODy9fgAxfx68pLPEvUNtiiDZbEF80oHaziNUNy6QI6+EAIPhy8u6v29xj0lyLqf48VXYdwYAS74pD9vTFk8Gl+Nd8tk6y63DP25ZGYGIov0jAJxjr1+8y/CrIa5jEotuzeKPe1z5w+7iAfasryGcITpQJBAP0kyrRVKG02ekWbzIrn6GVmD1Pq7QLkwzs7pTWI492sNtTLjxuR6TSlRCxe6EL3khgi8/ty8pVry2rHPNm4TO8CQQDTVuGdZ0fQj1ZEVGmlsSe/glqSpdsGx0Whh/D22tffTf+6j9JVNnWypP0HgWr678d0tHQvVFWbjOR6XtAdbgQDAkEA2qWSp9v+BQbO6Zy+OSRBqINUrej2Ok+ZCWplMi5AktESsw33V5rZ0O0GS0TWXDE18L8P+Zm5SbJHirz4JB155QJAVD8FDycVtKj+/ZwcxUU6kBgZnO3qwuf69Opo/y678TN5ptggQ4HDJ2SnzS8lA0VEYFxzGE7pFWnzxmg3VBQAGwJBAJiJDNsouSKPqxdOZhBLKPHPnce1/V8oXSvyeDc1J2jEzWIPsS0IvRokXA0ggq5UM5EcUb/q01/Uda6iv6O8umg=";
static String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQ+zyHtp6OB8Cw3hauZrh44oMJLWJ1xTykmBymzoCP7DjWqhaI36keQKul3UkQOrI9IFbBU0SP8WPep1ruQYieYmPWNUR/N4XdLlp1hLlq2iW9UPw9YWlpgkTQ33CxMxx5Q210Gmz+tn8H2+re1iXwuDSr7c0V11SmEPs1kA6izQIDAQAB";
public static void main(String[] args) throws Exception {
String text = "hello world,good job.";
String sign = RsaUtils.sign(text, PRIVATE_KEY);
boolean verify = RsaUtils.verify(text, sign, PUBLIC_KEY);
System.out.println("sign--verify = " + verify);
final String rsaSign = RsaUtils.encryptByPrivateKey(text, PRIVATE_KEY);
System.out.println("encrypt=" + rsaSign);
String decSign = RsaUtils.decryptByPublicKey(rsaSign, PUBLIC_KEY);
System.out.println("decrypt=" + decSign);
System.out.println("encrypt--decrypt");
}
}
执行结果如下图: