提示由于该Base64使用java8的的函数,所以如果没有该函数,请重写Base64 加密解密函数。
首先,RAS是由一对秘钥组成的,分为公钥和私钥,
使用场景
1.数据加密
公钥交给客户端,客户端通过公钥加密数据,将加密后的数据传递给服务器,保证数据安全,服务器接收到客户端的消息后,通过私钥解密客户端的消息。
2.签名认证
服务器端将要给客户发送的消息通过MD5进行摘要,然后,通过RSA对MD5值进行加密,完成数字签名,客户端收到消息后,通过公钥验证签名是否为服务器发出的消息,这样就可以确保数据是服务器发出的。
当然,毕竟他只是一个加密算法,具体如何使用,还是要看具体的业务
直接刚代码
1、生成密钥
RSA中,生成密钥是一步很关键的操作,虽然,很多地方有开源的密钥生成器,但我们还是要自己尝试一下。
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class RSAKeyUtil {
// 加密算法RSA
private static final String KEY_ALGORITHM = "RSA";
// 获取公钥的key
public static final String PUBLIC_KEY = "RSAPublicKey";
// 获取私钥的key
public static final String PRIVATE_KEY = "RSAPrivateKey";
//初始化:KeyPair可以理解为公钥和私钥的存储对象
public static KeyPair initKeyPair() {
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(1024);
return keyPairGen.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
//得到公钥
public static String getPublicKey(KeyPair keyPair) {
return encoderBase64(keyPair.getPublic().getEncoded());
}
//得到私钥
public static String getPrivateKey(KeyPair keyPair) {
return encoderBase64(keyPair.getPrivate().getEncoded());
}
public static Map<String, String> getKeyMap() {
KeyPair keyPair = initKeyPair();
Map<String, String> map = new HashMap<>();
map.put(PUBLIC_KEY, getPublicKey(keyPair));
map.put(PRIVATE_KEY, getPrivateKey(keyPair));
return map;
}
private static String encoderBase64(byte[] src) {
return new String(Base64.getEncoder().encode(src));
}
private static byte[] decoderBase64(String src) {
return Base64.getDecoder().decode(src);
}
}
完全不需要依赖任何三方jar,如果写个main完全可以独立运行。首先我们需要先调用:initKeyPair这个方法,的到一个密钥的getPublicKey(KeyPair keyPair)得到公钥,通过getPrivateKey(KeyPair keyPair)得到私钥。。。
或者直接调用getKeyMap()得到一对密钥,key为上面的常亮值,value为对应的密钥。
私钥的操作
这里要说一下,我将公钥和私钥的操作分成了两个类,分别对应不同的密钥,这个是私钥可以进行的一些操作
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
public class RSAPrivate {
//RSA最大加密明文大小
//这里要说明一下,RSA一次性加密解密的数据是有限制的
//javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes这个异常表示数据一次性加密数据过多
//key长度为1024位,1024/8 - 11 = 117,所以一次加密内容不能超过117bytes
private static final int MAX_ENCRYPT_BLOCK = 117;
//RSA最大解密密文大小
//另一个密钥没有问题,因为key的长度为2048位,2048/8 - 11 = 245,一次加密内容不能超过245bytes。而分段加密代码中用128为单位分段,从而使得一个密钥报错,另一个不报错。
private static final int MAX_DECRYPT_BLOCK = 128;
private static KeyFactory factory;
private static String privateKey;
private static PrivateKey privateKeyObj;
static{
try {
factory=KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* <p>用私钥对信息生成数字签名</p>
*
* @param data 已加密数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static String sign(byte[] data, String privateKey) throws GeneralSecurityException {
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(getPrivateKey(privateKey));
signature.update(data);
return encoderBase64(signature.sign());
}
/**
* <P>私钥解密</p>
*
* @param encryptedData 已加密数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
throws Exception {
KeyFactory keyFactory = factory;
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKey));
byte[] decryptedData = decryptedData(encryptedData, cipher);
return decryptedData;
}
/**
* <p>
* 私钥加密
* </p>
*
* @param data 源数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
throws Exception {
byte[] keyBytes = decoderBase64(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
Key privateK = factory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateK);
byte[] encryptedData = encryptData(data, cipher);
return encryptedData;
}
//分段处理数据
private static byte[] solveData(byte[] encryptedData, Cipher cipher,int type) throws GeneralSecurityException, IOException {
if (encryptedData.length<type){
return cipher.doFinal(encryptedData);
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (encryptedData.length - offSet > 0) {
if (encryptedData.length - offSet > type) {
cache = cipher.doFinal(encryptedData, offSet, type);
} else {
cache = cipher.doFinal(encryptedData, offSet, encryptedData.length - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * type;
}
byte[] bytes = out.toByteArray();
out.flush();
out.close();
return bytes ;
}
private static byte[] encryptData(byte[] encryptedData, Cipher cipher) throws Exception {
return solveData(encryptedData,cipher,MAX_ENCRYPT_BLOCK);
}
private static byte[] decryptedData(byte[] encryptedData, Cipher cipher) throws Exception {
return solveData(encryptedData,cipher,MAX_DECRYPT_BLOCK);
}
// 获取私钥对象
private static PrivateKey getPrivateKey(String privateKey) throws GeneralSecurityException {
if (privateKey==null || "".equals(privateKey) || !privateKey.equals(RSAPrivate.privateKey)) {
try {
RSAPrivate.privateKey = privateKey;
byte[] keyBytes = decoderBase64(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
privateKeyObj = factory.generatePrivate(pkcs8KeySpec);
}catch (Exception e){
RSAPrivate.privateKey=null;
throw new RuntimeException("解析私钥错误",e);
}
}
return privateKeyObj;
}
private static String encoderBase64(byte[] src) {
return new String(Base64.getEncoder().encode(src));
}
private static byte[] decoderBase64(String src) {
return Base64.getDecoder().decode(src);
}
}
使用的时候不需要管下面private修饰的方法,直接调用public的方法,非常简单
公钥的操作
公钥操作和私钥类似,同样不需要管private的函数
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RSAPublic {
//加密算法RSA
public static final String KEY_ALGORITHM = "RSA";
//签名算法
//public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
//RSA最大加密明文大小
private static final int MAX_ENCRYPT_BLOCK = 117;
//RSA最大解密密文大小
private static final int MAX_DECRYPT_BLOCK = 128;
private static KeyFactory factory;
private static String publicKey;
private static PublicKey publicKeyObj;
static{
try {
factory=KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* <p> 校验数字签名</p>
*
* @param data 已加密数据
* @param publicKey 公钥(BASE64编码)
* @param sign 数字签名
* @return
* @throws Exception
*/
public static boolean verify(byte[] data, String publicKey, String sign)
throws GeneralSecurityException {
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(getPublicKey(publicKey));
signature.update(data);
return signature.verify(decoderBase64(sign));
}
/**
* <p>
* 公钥解密
* </p>
*
* @param encryptedData 已加密数据
* @param publicKey 公钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)
throws Exception {
byte[] keyBytes = decoderBase64(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
Key publicK = factory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicK);
byte[] decryptedData = decryptedData(encryptedData, cipher);
return decryptedData;
}
/**
* <p>
* 公钥加密
* </p>
*
* @param data 源数据
* @param publicKey 公钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, String publicKey)
throws Exception {
Key publicK = getPublicKey(publicKey);
// 对数据加密
Cipher cipher = Cipher.getInstance(publicK.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
byte[] encryptedData = encryptData(data, cipher);
return encryptedData;
}
private static byte[] solveData(byte[] encryptedData, Cipher cipher,int type) throws GeneralSecurityException, IOException {
if (encryptedData.length<type){
return cipher.doFinal(encryptedData);
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (encryptedData.length - offSet > 0) {
if (encryptedData.length - offSet > type) {
cache = cipher.doFinal(encryptedData, offSet, type);
} else {
cache = cipher.doFinal(encryptedData, offSet, encryptedData.length - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * type;
}
byte[] bytes = out.toByteArray();
out.flush();
out.close();
return bytes ;
}
private static byte[] encryptData(byte[] encryptedData, Cipher cipher) throws Exception {
return solveData(encryptedData,cipher,MAX_ENCRYPT_BLOCK);
}
private static byte[] decryptedData(byte[] encryptedData, Cipher cipher) throws Exception {
return solveData(encryptedData,cipher,MAX_DECRYPT_BLOCK);
}
//获取公钥对象
private static PublicKey getPublicKey(String publicKey) throws GeneralSecurityException {
if (publicKey==null || "".equals(publicKey) || !publicKey.equals(RSAPublic.publicKey)) {
try {
RSAPublic.publicKey = publicKey;
byte[] keyBytes = decoderBase64(publicKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
publicKeyObj = factory.generatePublic(pkcs8KeySpec);
}catch (Exception e){
RSAPublic.publicKey=null;
throw new RuntimeException("解析私钥错误",e);
}
}
return publicKeyObj;
}
private static String encoderBase64(byte[] src) {
return new String(Base64.getEncoder().encode(src));
}
private static byte[] decoderBase64(String src) {
return Base64.getDecoder().decode(src);
}
}