**
**
转载请注明出处!!!
RSA是一种非对称加密算法,需要通过不同的密钥来加解密和加解签。通过RSA我们可以对信息传输做到防泄漏放篡改的目的。
RSA的几个概念:
公钥:用于信息信加密和验证签名
私钥:用于信息解密和签名
加密:防止信息泄漏
加签:防止信息被篡改
总结下来就是:公钥解密、私钥加密、私钥加签、公钥验签。加密防泄漏、加签防篡改。
至于RSA的加解密算法这里不做研究,下面谈谈RSA加解密和签名、验签的JAVA实现
1、RSA的密钥对
如果用公钥加密则用私钥解密,用私钥加密则公钥解密,也就是一方加密,则另一方用来解密,签名和验签也是同样的道理。下面代码使用随机数自动产生一对随机密钥对:
/**
* 随机生成一对密钥
* @return Map map中key为pub的为公钥,key为pri的为私钥
* @throws NoSuchAlgorithmException
*/
public static Map<String,String> generateKeyPair() throws NoSuchAlgorithmException{
Map<String,String> result = new HashMap<String,String>();
//使用KeyPairGenerator来创建密钥对生成器,基于RSA算法
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA);
//使用随机数来初始化密钥对生成器
SecureRandom sRan = new SecureRandom();
keyPairGen.initialize(1024, sRan);
//生成密钥对
KeyPair keyPair = keyPairGen.generateKeyPair();
//获取私钥
RSAPrivateKey priKey = (RSAPrivateKey) keyPair.getPrivate();
//获取公钥
RSAPublicKey pubKey = (RSAPublicKey)keyPair.getPublic();
//对密钥对做Base64编码处理
String priKeyStr = Base64.getEncoder().encodeToString(priKey.getEncoded());
String pubKeyStr = Base64.getEncoder().encodeToString(pubKey.getEncoded());
result.put("pri",priKeyStr);
result.put("pub",pubKeyStr);
return result;
}
2、RSA使用java实现加密和解密
由于RSA加密的原文最长不能超过117byte,解密的原文最长不能超过128byte,不然加密会产生异常:Data must not be longer than 117 bytes,解密会产生异常:Data must not be longer than 128 bytes。下面使用分段逻辑的方法来实现加解密
package com.lsk.util;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
public class RsaUtil {
private final static String RSA = "RSA";
private final static String UTF8 = "UTF-8";
//最大加密长度不能超过117byte
private final static int MAX_ENCRYPT_BLOCK = 117;
//最大解密长度不能超过128byte
private final static int MAX_DECRYPT_BLOCK = 128;
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
// TODO Auto-generated method stub
Map<String,String> result = generateKeyPair();
System.out.println("获取到的公钥:\t"+result.get("pub"));
System.out.println("获取到的私钥:\t"+result.get("pri"));
String src = "Linsk110";
System.out.println("Linsk110使用RSA加密后密文:");
String encryStr = encry(src,result.get("pub"));
System.out.println(encryStr);
String decryStr = decry(encryStr,result.get("pri"));
System.out.println("密文解密后:"+decryStr);
}
/**
* 随机生成一对密钥
* @return Map map中key为pub的为公钥,key为pri的为私钥
* @throws NoSuchAlgorithmException
*/
public static Map<String,String> generateKeyPair() throws NoSuchAlgorithmException{
Map<String,String> result = new HashMap<String,String>();
//使用KeyPairGenerator来创建密钥对生成器,基于RSA算法
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA);
//使用随机数来初始化密钥对生成器
SecureRandom sRan = new SecureRandom();
keyPairGen.initialize(1024, sRan);
//生成密钥对
KeyPair keyPair = keyPairGen.generateKeyPair();
//获取私钥
RSAPrivateKey priKey = (RSAPrivateKey) keyPair.getPrivate();
//获取公钥
RSAPublicKey pubKey = (RSAPublicKey)keyPair.getPublic();
//对密钥对做Base64编码处理
String priKeyStr = Base64.getEncoder().encodeToString(priKey.getEncoded());
String pubKeyStr = Base64.getEncoder().encodeToString(pubKey.getEncoded());
result.put("pri",priKeyStr);
result.put("pub",pubKeyStr);
return result;
}
/**
* 使用公钥加密(分段加密)
* @param src 加密的原文
* @param publicKey 加密的公钥
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
*/
public static String encry(String src,String publicKey) throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
//对公钥先做base64解码
byte[] decodeKey = Base64.getDecoder().decode(publicKey);
//获取一个加密key对象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodeKey);
//通过RSA算法获取一个密钥工厂对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
//通过解码的公钥字节来获取公钥对象
RSAPublicKey pubKey = (RSAPublicKey)keyFactory.generatePublic(keySpec);
//获取RSA加密对象
Cipher cipher = Cipher.getInstance(RSA);
//初始化加密对象
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
//原文字节长度
int srcLength = src.getBytes().length;
int offset = 0;//计算标识
byte[] resultByte = {
};
byte[] cache = {
};
byte[] srcByteArry = src.getBytes();
//对原文做分段加密
while(srcLength - offset > 0) {
int offsetResult = srcLength-offset;
//原文字节超过117字节
if(offsetResult > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(srcByteArry,offset,MAX_ENCRYPT_BLOCK);
offset += MAX_ENCRYPT_BLOCK;
}else {
cache = cipher.doFinal(srcByteArry,offset,offsetResult);
offset = offsetResult;
}
//数组扩容
resultByte = Arrays.copyOf(resultByte, resultByte.length+cache.length);
/*
* 把cache中的字节拷贝到resultByte中去
* cache:待拷贝的原始字节数组
* 0:从原始字节数组的第0位开始拷贝
* resultByte:要拷贝到的目标数组
* resultByte.length-cache.length:拷贝的内容要放在目标数组的开始位置
* cache.length:原始字节数组拷贝内容的截至位置
*/
System.arraycopy(cache, 0, resultByte, resultByte.length-cache.length, cache.length);
}
return Base64.getEncoder().encodeToString(resultByte);
}
/**
* 使用公钥加密(分段解密)
* @param src
* @param privateKey
* @return
* @throws InvalidKeySpecException
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
* @throws UnsupportedEncodingException
*/
public static String decry(String src,String privateKey) throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
//对密钥字串做解码
byte[] decodeKey = Base64.getDecoder().decode(privateKey);
//获取一个加密key对象
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodeKey);
//通过RSA算法获取一个密钥工厂对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
//通过解码的私钥字节来获取私钥对象
RSAPrivateKey priKey = (RSAPrivateKey)keyFactory.generatePrivate(keySpec);
//获取RSA加密对象
Cipher cipher = Cipher.getInstance(RSA);
//初始化解密对象
cipher.init(Cipher.DECRYPT_MODE, priKey);
//对原文做解码操作,原因是加密后通过base64做了一次编码
byte[] srcByteArry = Base64.getDecoder().decode(src);
int srcLength = srcByteArry.length;
int offset = 0;//计算标识
byte[] resultByte = {
};
byte[] cache = {
};
//对原文做分段解密
while(srcLength - offset > 0) {
int offsetResult = srcLength-offset;
//原文字节超过128字节
if(offsetResult > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(srcByteArry,offset,MAX_DECRYPT_BLOCK);
offset += MAX_DECRYPT_BLOCK;
}else {
cache = cipher.doFinal(srcByteArry,offset,offsetResult);
offset = MAX_DECRYPT_BLOCK;
}
//数组扩容
resultByte = Arrays.copyOf(resultByte, resultByte.length+cache.length);
/*
* 把cache中的字节拷贝到resultByte中去
* cache:待拷贝的原始字节数组
* 0:从原始字节数组的第0位开始拷贝
* resultByte:要拷贝到的目标数组
* resultByte.length-cache.length:拷贝的内容要放在目标数组的开始位置
* cache.length:原始字节数组拷贝内容的截至位置
*/
System.arraycopy(cache, 0, resultByte, resultByte.length-cache.length, cache.length);
}
return new String(resultByte);
}
}
至此完毕,如有问题,欢迎留言交流~~~