非对称加密算法--RSA
·
一、概念
非对称加密有一对密钥:公钥 (publickey) 和私钥 (privatekey),因为加密和解密用的是不同的密钥,所以称为非对称加密。
公钥加密,私钥解密
私钥加密,公钥解密
二、特点
- 相对于对称加密,加密速度慢,效率低
- 相对于对此加密,安全性更高
- 适合加密少量数据
三、非对称加密算法
- RSA(最常用)
- ECC
- Diffie-Hellman
- DSA
四、应用场景
4.1、信息加密

4.2、数字签名
私钥加密,公钥解密;
私钥只有一份,只要不泄露私钥,防止签名被伪造。
对哈希值进行加密可以提高效率
针对A端,进行数字签名过程:
1、A端生成密钥对,将公钥分发给B;
2、A端先将要加密数据,通过哈希算法生成hash值;
3、A端通过私钥对hash值进行加密,生成签名密文;
4、A端发送(原始数据+数字签名)给B端;
针对B端,进行签名校验过程:
1、B端获取到A端发送数据,将原始数据通过相同哈希算法生成hash值hashA;
2、B端通过公钥对签名进行解密,得到hashB;
3、比较hashA与hashB值,相同则数据没有被伪造;
4.3、数字证书
针对密钥分发,存在安全隐患,需要保证获取公钥是真实。
这样就需要第三方机构来保证公钥的合法性,这个第三方机构就是 CA (Certificate Authority),证书中心。
CA 用自己的私钥对信息原文所有者发布的公钥和相关信息进行加密,得出的内容就是数字证书。
信息原文的所有者以后发布信息时,除了带上自己的签名,还带上数字证书,就可以保证信息不被篡改了。信息的接收者先用 CA给的公钥解出信息所有者的公钥,这样可以保证信息所有者的
五、项目实战
package com.spring.util;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import java.io.File;
import java.io.IOException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* RSA 非对称加密工具类
*
* @author yilei
* @className RsaUtils
* @date 2021/1/30 15:39
**/
public class RsaUtils {
/**
* 算法名称
*/
private static final String ALGORITHM = "RSA";
/**
* 密钥长度
*/
private static final int KEY_SIZE = 2048;
/**
* 密钥对生成器
*
* @param
* @return void
* @author yilei
* @date 2021-01-30 15:39
*/
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException, IOException {
// 获取指定算法的密钥对生成器
KeyPairGenerator gen = KeyPairGenerator.getInstance(ALGORITHM);
// 初始化密钥对生成器(指定密钥长度, 使用默认的安全随机数源)
gen.initialize(KEY_SIZE);
// 随机生成一对密钥(包含公钥和私钥)
KeyPair keyPair = gen.generateKeyPair();
return keyPair;
}
/**
* 将 公钥/私钥 编码后以 Base64 的格式保存到指定文件
*
* @param key 公钥/私钥
* @param fileUrl 文件路径
* @return void
* @author yilei
* @date 2021/1/30 16:19
*/
public static void saveToFile(Key key, String fileUrl) throws IOException {
// 获取密钥编码后的格式
byte[] encBytes = key.getEncoded();
// 转换为 Base64 文本
String encBase64 = new BASE64Encoder().encode(encBytes);
// 保存到文件
IOUtils.writeFile(encBase64, new File(fileUrl));
}
/**
* 根据公钥的 Base64 文本创建公钥对象
*
* @param
* @return void
* @author yilei
* @date 2021/1/30 15:52
*/
public static PublicKey getPublicKey(String pubKeyBase64) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
// 把 公钥的Base64文本 转换为已编码的 公钥bytes
byte[] encPubKey = new BASE64Decoder().decodeBuffer(pubKeyBase64);
// 创建 已编码的公钥规格
X509EncodedKeySpec encPubKeySpec = new X509EncodedKeySpec(encPubKey);
// 获取指定算法的密钥工厂, 根据 已编码的公钥规格, 生成公钥对象
return KeyFactory.getInstance(ALGORITHM).generatePublic(encPubKeySpec);
}
/**
* 根据私钥的 Base64 文本创建私钥对象
*
* @param
* @return void
* @author yilei
* @date 2021/1/30 15:52
*/
public static PrivateKey getPrivateKey(String priKeyBase64) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
// 把 私钥的Base64文本 转换为已编码的 私钥bytes
byte[] encPriKey = new BASE64Decoder().decodeBuffer(priKeyBase64);
// 创建 已编码的私钥规格
PKCS8EncodedKeySpec encPriKeySpec = new PKCS8EncodedKeySpec(encPriKey);
// 获取指定算法的密钥工厂, 根据 已编码的私钥规格, 生成私钥对象
return KeyFactory.getInstance(ALGORITHM).generatePrivate(encPriKeySpec);
}
/**
* 公钥加密数据
*
* @param plainData 明文
* @param pubKey 公钥
* @return byte[]
* @author yilei
* @date 2021/1/30 16:22
*/
public static byte[] encryptPublic(byte[] plainData, PublicKey pubKey) throws Exception {
// 获取指定算法的密码器
Cipher cipher = Cipher.getInstance(ALGORITHM);
// 初始化密码器(公钥加密模型)
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
// 加密数据, 返回加密后的密文
return cipher.doFinal(plainData);
}
/**
* 私钥解密数据
*
* @param cipherData 密文
* @param priKey 私钥
* @return byte[]
* @author yilei
* @date 2021/1/30 16:24
*/
public static byte[] decryptPrivate(byte[] cipherData, PrivateKey priKey) throws Exception {
// 获取指定算法的密码器
Cipher cipher = Cipher.getInstance(ALGORITHM);
// 初始化密码器(私钥解密模型)
cipher.init(Cipher.DECRYPT_MODE, priKey);
// 解密数据, 返回解密后的明文
return cipher.doFinal(cipherData);
}
/**
* 公钥解密数据
*
* @param cipherData 密文
* @param pubKey 公钥
* @return byte[]
* @author yilei
* @date 2021/1/30 16:24
*/
public static byte[] decryptPublic(byte[] cipherData, PublicKey pubKey) throws Exception {
// 获取指定算法的密码器
Cipher cipher = Cipher.getInstance(ALGORITHM);
// 初始化密码器(私钥解密模型)
cipher.init(Cipher.DECRYPT_MODE, pubKey);
// 解密数据, 返回解密后的明文
return cipher.doFinal(cipherData);
}
/**
* 私钥加密数据
*
* @param plainData 明文
* @param priKey 私钥
* @return byte[]
* @author yilei
* @date 2021/1/30 16:22
*/
public static byte[] encryptPrivate(byte[] plainData, PrivateKey priKey) throws Exception {
// 获取指定算法的密码器
Cipher cipher = Cipher.getInstance(ALGORITHM);
// 初始化密码器(私钥加密模型)
cipher.init(Cipher.ENCRYPT_MODE, priKey);
// 加密数据, 返回加密后的密文
return cipher.doFinal(plainData);
}
public static void main(String[] args) throws Exception {
// 密钥对生成器
KeyPair keyPair = generateKeyPair();
// 公钥
PublicKey pubKey = keyPair.getPublic();
// 私钥
PrivateKey priKey = keyPair.getPrivate();
System.out.println("=============公钥加密,私钥解密(适用与客户端-服务器端模式)=================");
// 明文
String data = "RSA 非对称加密===公钥加密,私钥解密";
System.out.println("明文:" + data);
// 客户端: 用公钥加明文, 返回加密后的数据
byte[] cipherData = encryptPublic(data.getBytes(), pubKey);
// 服务端: 用私钥解密数据, 返回原文
byte[] plainData = decryptPrivate(cipherData, priKey);
// 输出查看解密后的原文
System.out.println("私钥解密后:" + new String(plainData));
System.out.println("");
System.out.println("=============私钥加密,公钥解密(适用于签名验签授权模式)=================");
// 明文
String data1 = "RSA 非对称加密=====私钥加密,公钥解密";
System.out.println("明文:" + data1);
// 授权服务端: 用私钥加密明文, 返回加密后的数据
byte[] cipherData1 = encryptPublic(data1.getBytes(), pubKey);
// 被授权的服务端: 用公钥解密数据, 返回原文
byte[] plainData1 = decryptPrivate(cipherData1, priKey);
// 输出查看解密后的原文
System.out.println("公钥解密后:" + new String(plainData1));
}
}
更多推荐



所有评论(0)