非对称加密算法--RSA 爱被打了一巴掌 2022-10-24 13:25 160阅读 0赞 **一、概念** 非对称加密有一对密钥:`公钥 (publickey) 和私钥 (privatekey)`,因为加密和解密用的是不同的密钥,所以称为非对称加密。 > 公钥加密,私钥解密 > 私钥加密,公钥解密 **二、特点** * 相对于对称加密,加密速度慢,效率低 * 相对于对此加密,安全性更高 * 适合加密少量数据 **三、非对称加密算法** * RSA(最常用) * ECC * Diffie-Hellman * DSA **四、应用场景** **4.1、信息加密** ![在这里插入图片描述][20210129211435745.png] **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)); } } [项目源码][Link 1] [20210129211435745.png]: /images/20221024/e772b85c2d5c42338b176213a96066dc.png [Link 1]: https://github.com/yilei111/license.git
还没有评论,来说两句吧...