一、案例内容:
RSA 公钥加密,私钥解密;
RSA 私钥加密,公钥解密;
RSA 私钥加签,公钥验签(SHA1WithRSA或者SHA256WithRSA-数字签名)
二、引入的jar包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<!-- Base64编码 -->
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
三、案例代码
package com.cn.dl;
import com.alibaba.fastjson.JSONObject;
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;
/**
* 1、RSA 公钥加密,私钥解密
* 2、RSA 私钥加密,公钥解密
* 3、RSA 私钥加签,公钥验签(SHA1WithRSA或者SHA256WithRSA-数字签名)
*
* Created by yanshao on 2018/12/12.
*/
public class NewRSAUtils {
//加密算法
private static final String SHA256WithRSA = "SHA256WithRSA";
//public static final String SIGN_ALGORITHMS = "SHA1WithRSA";
private static final String RSA = "RSA";
//编码
private static final String CHARSET_UTF_8 = "utf-8";
//私钥
private static final String privateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCqrpUHZx/NSRsK" +
"jQc9i/gCGzU9Q3qRf44pm0lML9FfJf+m9mo9qdAEsMl3N0Y/nVcdGWb8VBry+dyl" +
"mKNR4VPfFNGQKWW8OtvUlT9l3I9/MTd/ZsoVt2dQdBvOp7+9hrClS+rmw/HFz81l" +
"RCFcku8HIIIcFxPQylRgSxHI8PMVJEodBsQSRvOzGtzWTfhTfG0Y0sgZPt75hKjd" +
"J1rTo4264AG3YzlxHlmqrrQxxmYEKEnNplmNVga2bXvPICZ2VPbl9w/52mlSobg3" +
"6VPKMzdlhTUgFsADPMaG2Pf3GqOa2GTSupzgTyz/54LyF6gCbXcAknRFgH5eyAv5" +
"tPqV9CsrAgMBAAECggEAAXIHCxABgfCLjRRSql/EEuh+E+29XPwSjSGmhkGlaUPe" +
"HWDa13jXrSJ+IkdSjflcIn/zklF4BPS+vJxFTc01s57ug2UGWoi5EdzNs6Qhhvc4" +
"vBh3v6VU96Z0EdTz17wLROsWqyufoYg3+hKQocMQySOqVmiPn2YHPuWD2grIVDZ9" +
"68mC1FykGEcv9De0m6yVEsfZDXNUxm3cz1758iBqakvyOVxGsI+V+e7/iSxJiwIB" +
"6f3NSGQVtEsqwyhnl6dZRYDtnq5iUiwUOshl5Z2CYBfBcyTpMKC2RuHp3u9THHpc" +
"3TFE4I1Li5HkiFy+ai6QKl2M85ce3GCXmjyw7n2vmQKBgQDTHihNX6uu6YlVFcRa" +
"XhhGigyLrIP8LbLd4r/dKMXuGa8XqkLPlDtXelh2n565Lo5DPGlpANi3Jp495Hzn" +
"bL+YnHJs7boVOGtORB0XHUbiMaTlT85snpvVjwFngHvY/ZxtXclpsnX563AvzCyl" +
"amrKEhV17BFZbRQOTEL1UNp57QKBgQDO98AyfVgs1tCdtLOsFSFiWrAsJJimBS7b" +
"ec+W/UPGDAl3hFzQzJ2SUvF4EneatYVOEDdHLUzVnT7XXeA/eMZL56N8BTSffh8q" +
"XK0E21K8tW4hRbze6CIjbsJ1x7ZLZaoM4Ub2YAvkulF0PcasX0kWl+bv/DnkI09x" +
"/n3vgbO2dwKBgQCoAnj6UmeztEDJiKARdo6FHHmtciY7Ozb8Y+Zin38c5C22fJXc" +
"0k+DZ2cdSBwtrQIkOeB9YuIUp1QJV1ubZKz5S4+4ZlvPZW3oBEbOTUtK2U0r/J3/" +
"TR4hD0SD1Pk6j2G8m4Wdaxt+P8KxFyB0p8LCey++/5Yy/56VXlVvGuAzZQKBgQCU" +
"VfcXeMTIplGwpkGcFSzvLCZWDQim/NH/lYdWJUD84cWrNl+7ett4cyADueClLnJT" +
"Z8Xmqq4F8ASJIQxHEY21+1gt3CFCKoe1ueR7taHQBIzhJfVfIarOEGUpOzEJSt0d" +
"DBzrGh2MGomksV4CTuy4V7i5yeHIBBK9lfO2xBQEswKBgQCIzYO53kTFl6YGjmWO" +
"qUJsT+5WegR4GdxtqYpQGPC1RmU7ig1TZzen+X3xB+lIHqgA1HvTr6M+tPkmnMwU" +
"iARPOgjXY0zmsStXaHQYKruT3EjZRs2GnmVpVOAj1asqi+/2t0NgLgB5gPLYMXS+" +
"BGf01OehvUt5Ge+OChDBXSW5Bw==";
//公钥
private static final String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqq6VB2cfzUkbCo0HPYv4" +
"Ahs1PUN6kX+OKZtJTC/RXyX/pvZqPanQBLDJdzdGP51XHRlm/FQa8vncpZijUeFT" +
"3xTRkCllvDrb1JU/ZdyPfzE3f2bKFbdnUHQbzqe/vYawpUvq5sPxxc/NZUQhXJLv" +
"ByCCHBcT0MpUYEsRyPDzFSRKHQbEEkbzsxrc1k34U3xtGNLIGT7e+YSo3Sda06ON" +
"uuABt2M5cR5Zqq60McZmBChJzaZZjVYGtm17zyAmdlT25fcP+dppUqG4N+lTyjM3" +
"ZYU1IBbAAzzGhtj39xqjmthk0rqc4E8s/+eC8heoAm13AJJ0RYB+XsgL+bT6lfQr" +
"KwIDAQAB";
/**
* 生成公私钥对
* @return String[0]:公钥,String[1]:私钥
*/
public static String[] generateKeyPair()
{
KeyPairGenerator keyPairGenerator = null;
try
{
keyPairGenerator = keyPairGenerator.getInstance(RSA);
keyPairGenerator.initialize(1024, new SecureRandom());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
return new String[]{new Base64().encodeToString(publicKey.getEncoded()),
new Base64().encodeToString(privateKey.getEncoded())};
}
catch (Exception e){
e.printStackTrace();
return null;
}
}
/**
* 使用私钥给入参签名
* @param privateKey 私钥
* @param param 签名的数据
* @return 返回入参签名16进制字符串
* */
public static String sign(String privateKey, String param) {
try {
//获取privatekey
byte[] privateKeyByte = new Base64().decode(privateKey);
KeyFactory keyfactory = KeyFactory.getInstance(RSA);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
PrivateKey key = keyfactory.generatePrivate(pkcs8EncodedKeySpec);
//用私钥给入参加签
Signature sign = Signature.getInstance(SHA256WithRSA);
sign.initSign(key);
sign.update(param.getBytes());
byte[] signature = sign.sign();
//将签名的入参转换成16进制字符串
return bytesToHexStr(signature);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 用公钥验证签名
* @param param 入参
* @param signature 使用私钥签名的入参字符串
* @param publicKey 公钥
* @return 返回验证结果
* */
public static boolean verifySign(String param,String signature,String publicKey){
try {
//获取公钥
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
byte[] publicKeyByte = new Base64().decode(publicKey);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
PublicKey key= keyFactory.generatePublic(x509EncodedKeySpec);
//用获取到的公钥对 入参中未加签参数param 与 入参中的加签之后的参数signature 进行验签
Signature sign=Signature.getInstance(SHA256WithRSA);
sign.initVerify(key);
sign.update(param.getBytes());
//将16进制码转成字符数组
byte[] hexByte = hexStrToBytes(signature);
//验证签名
return sign.verify(hexByte);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 使用公钥加密
* @param publicKey 公钥
* @param param 私钥
* @return 加密后的字符串
* */
public static String RSAPublicEncrypt(String publicKey, String param) throws Exception {
try {
byte[] publicKeyByte = new Base64().decode(publicKey);
KeyFactory keyfactory = KeyFactory.getInstance(RSA);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
RSAPublicKey key = (RSAPublicKey)keyfactory.generatePublic(x509EncodedKeySpec);
// 使用默认RSA
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.ENCRYPT_MODE,key);
byte[] output = cipher.doFinal(param.getBytes(CHARSET_UTF_8));
return bytesToHexStr(output);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 使用私钥解密
* @param privateKey 私钥
* @param encryptParam 公钥加密的字符串
* @return 解密后的字符串
* */
public static String RSAPrivateDecrypt(String privateKey,String encryptParam) throws Exception {
Cipher cipher = null;
try {
// 使用默认RSA
byte[] privateKeyByte = new Base64().decode(privateKey);
KeyFactory keyfactory = KeyFactory.getInstance(RSA);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
RSAPrivateKey key = (RSAPrivateKey)keyfactory.generatePrivate(pkcs8EncodedKeySpec);
cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] output = cipher.doFinal(hexStrToBytes(encryptParam));
return new String(output);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 私钥加密,公钥解密
* @param privateKey 私钥
* @param param 需要加密的数据
* @return 返回加密后的数据
* */
public static String RSAPrivateEncrypt(String privateKey, String param){
try{
// 使用默认RSA
byte[] privateKeyByte = new Base64().decode(privateKey);
KeyFactory keyfactory = KeyFactory.getInstance(RSA);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
RSAPrivateKey key = (RSAPrivateKey)keyfactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] output = cipher.doFinal(param.getBytes(CHARSET_UTF_8));
return bytesToHexStr(output);
}catch(Exception e){
e.printStackTrace();
return null;
}
}
/**
* 私钥加密,公钥解密
* @param publicKey 公钥
* @param encryptParam 需要解密的数据
* @return 返回解密后的数据
* */
public static String RSAPublicDecrypt(String publicKey, String encryptParam){
try{
byte[] publicKeyByte = new Base64().decode(publicKey);
KeyFactory keyfactory = KeyFactory.getInstance(RSA);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
RSAPublicKey key = (RSAPublicKey)keyfactory.generatePublic(x509EncodedKeySpec);
// 使用默认RSA
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.DECRYPT_MODE,key);
byte[] output = cipher.doFinal(hexStrToBytes(encryptParam));
return new String(output);
}catch(Exception e){
e.printStackTrace();
return null;
}
}
/**
* byte数组转换成十六进制字符串
* @param bytes byte数组
* @return 返回十六进制字符串
*/
private static String bytesToHexStr(byte[] bytes) {
StringBuffer stringBuffer = new StringBuffer("");
for (int i = 0; i < bytes.length; ++i) {
stringBuffer.append(Integer.toHexString(0x0100 + (bytes[i] & 0x00FF)).substring(1).toUpperCase());
}
return stringBuffer.toString();
}
/**
* 十六进制字符串转成byte数组
* @param hexStr 十六进制字符串
* @return 返回byte数组
* */
private static byte[] hexStrToBytes(String hexStr) {
byte[] bytes = new byte[hexStr.length() / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt(hexStr.substring(2 * i, 2 * i + 2), 16);
}
return bytes;
}
public static void main(String[] args) throws Exception{
String[] keyPair = generateKeyPair();
System.out.println("公钥>>"+keyPair[0]);
System.out.println("私钥>>"+keyPair[1]);
JSONObject json = new JSONObject();
json.put("name","yanshao");
json.put("ab","ab");
json.put("age",25);
json.put("address","武汉");
String params = json.toJSONString();
System.out.println("入参>>>"+params);
String sign = sign(keyPair[1],params);
System.out.println("签名后的参数>>>"+sign);
System.out.println("验证结果>>>"+verifySign(params,sign,keyPair[0]));
String encrypt = RSAPublicEncrypt(keyPair[0],params);
System.out.println("公钥加密>>>"+encrypt);
System.out.println("私钥解密>>>"+RSAPrivateDecrypt(keyPair[1],encrypt));
String encrypt1 = RSAPrivateEncrypt(keyPair[1],params);
System.out.println("私钥加密>>>"+encrypt1);
System.out.println("公钥解密>>>"+RSAPublicDecrypt(keyPair[0],encrypt1));
}
}
四、运行结果
公钥>>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9SZS0czkGetJU/+JcoVIyt3T0HYbk/s7E2kdReyEBdU06s8SPwSFIcn9D+zh2rEvzDylAYBpWIHfIWJhqkz53qxKH2GqkVrY2SipYQiVyH673mH7zmeYQWUZLW1AaAPZj+0ZJf8l82/P6c3zV1D/rgQHQDFaXS3xMwyah+KrjVQIDAQAB
私钥>>MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAL1JlLRzOQZ60lT/4lyhUjK3dPQdhuT+zsTaR1F7IQF1TTqzxI/BIUhyf0P7OHasS/MPKUBgGlYgd8hYmGqTPnerEofYaqRWtjZKKlhCJXIfrveYfvOZ5hBZRktbUBoA9mP7Rkl/yXzb8/pzfNXUP+uBAdAMVpdLfEzDJqH4quNVAgMBAAECgYEAitUhIIkyVjJXesiDenVIGLK+MR5HBkZt2axPis/IkY07q8aWcOmyQ7TW60GjVEdjHU8Nbo4OQwVlVajFgcWlllHDaXrdh1cdzR0FTpxQV+dSr/U9UyLRmuSK2q/yavn4Zp9OVvoC7jPSe/J8lEwGIo6MSGD2JwGQFyAK4l5dcLECQQD+Ccb/R15RJUqRAbwMUtFDci1l2dwR/vte95RAIybWjxZ9AxHGvlqHLX40nxWWUc9SELawdxnZJYiPLdBqRuOPAkEAvr/LRkzo0Sd9gczWkn8/JP7HuiBJOvkYZWkSRMvKuu1smO3SjWIXqjf37S/nAqxP7NKvEiEamf0pZG0JJppI2wJBANR+EzGHXhJcMhI3NDfOsnJLOEQgxp9a/KLETwKTJLKGP9ZT0fO/V/QIjq+vfhwd1GAd0OKszTdA2QiC1vl+0GsCQCa9UQ1gBVClEopQDawHB839qJaWhAjkGh5ObpVmRjAclBejBUYNi/zYDRQwzFvwnvLb/w5RhtOLZOKuelNKtk0CQQDwd7ZSgGdo57Vf+LE8q/A3tW6QaobLK8A/wBG+hJuT9oS5pdIyl9BrbVR9srpedaDUK9QDkUaL+BhN4rzV/Iei
入参>>>{"ab":"ab","address":"武汉","name":"yanshao","age":25}
签名后的参数>>>585E4FBBAF8D33D19E9CE8F7FBC9EC37C6E840BB0D1637FA84231A0D3B12942ADB768AEA15A2ADF5563C4400490254BB7F559B2B57B658C4421F408254E1F2BD759860FCED241C619FE86AE9403C5B1956AE232A1BF3B160A8D975349288421A4EB86B4AB975CE2A5788E3AA57B24E7811CFC3D8ED93BF6E8C2F3E4E599CA543
验证结果>>>true
公钥加密>>>8CB761651490298D0EBB68A78238A758E0DDC4D21CB289BF0268B50388033B2F1A1A7BB04B32BE3FD2A2911AC5C8E5EFE87340888DF193BBF17DAF67EC8D08BA24CB08C4C3086B4AEAE978E3349A1F454E87BF067101D596E77D148D2E6B092C256631D20C5D1AEA077E7765578DCC874CDC8CFC2051255009A613F159C22BB8
私钥解密>>>{"ab":"ab","address":"武汉","name":"yanshao","age":25}
私钥加密>>>360DF16454327F526FDD5B657FDBA8F2EF29210CA7797C3AD0C420A712871CD974A7ACC027009C3BF819E16344FD8EF8465D2C778A9DC8B1F839F0B60B818CC465A073A29121B736E9DFB5F82786BA1EE14155FEE9CC9145C07AC6795DF6590CA5746324DC63660560E8EA32C0722698DAD58E9BB555DBDBE961D5BBA4C93CA3
公钥解密>>>{"ab":"ab","address":"武汉","name":"yanshao","age":25}
注意:
1、
案例中的privateKey和publicKey是通过openssl生成的,可以直接用
(参考文章:https://blog.csdn.net/qq_31289187/article/details/84973338);
2、本案例有专门生成公私钥对的方法,案例中使用了(commons-codec) 这个jar包,使用JDK8自带的base64编解码也可以。