10、RSA加密算法

RSA

RSA加密是一种非对称加密。可以在不直接传递密钥的情况下,完成解密。这能够确保信息的安全性,避免了直接传递密钥所造成的被破解的风险。是由一对密钥来进行加解密的过程,分别称为公钥和私钥。两者之间有数学相关,该加密算法的原理就是对于极大整数做因数分解的困难性来保证安全性。通常个人保存私钥,公钥是公开的(可能同时多人持有)。

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * @描述 Rsa加密工具类
 * @创建人 yhgh
 * @创建时间 2022/01/22 11:49
 */
public class RsaUtil {


    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;
    /**
     * 加密方式名称
     */
    private static final String ALGORITHM_NAME = "RSA";

    private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder();

    private static final  Base64.Decoder BASE64_DECODER = Base64.getDecoder();


    /**
     * 获取密钥对
     */
    private static KeyPair getKeyPair() throws Exception {
        KeyPairGenerator generator = KeyPairGenerator.getInstance(ALGORITHM_NAME);
        generator.initialize(1024);
        return generator.generateKeyPair();
    }

    /**
     * 获取base64加密后密钥对
     */
    public static Map<String, String> getKeyPairMap() throws Exception {
        KeyPair keyPair = getKeyPair();
        String privateKey = new String(BASE64_ENCODER.encode(keyPair.getPrivate().getEncoded()));
        String publicKey = new String(BASE64_ENCODER.encode(keyPair.getPublic().getEncoded()));
        Map<String, String> keyMap = new HashMap<>();
        keyMap.put("privateKey", privateKey);
        keyMap.put("publicKey", publicKey);
        return keyMap;
    }

    /**
     * 获取公钥
     *
     * @param publicKey base64加密的公钥字符串
     */
    private static PublicKey getPublicKey(String publicKey) throws Exception {
        byte[] decodedKey = BASE64_DECODER.decode(publicKey.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_NAME);
        return keyFactory.generatePublic(keySpec);
    }



    /**
     * 获取私钥
     *
     * @param privateKey base64加密的私钥字符串
     */
    private static PrivateKey getPrivateKey(String privateKey) throws Exception {
        byte[] decodedKey = BASE64_DECODER.decode(privateKey.getBytes());
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_NAME);
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * RSA加密
     *
     * @param data      待加密数据
     * @param publicKeyStr 公钥
     */
    public static String encrypt(String data, String publicKeyStr) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM_NAME);
        cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKeyStr));
        int inputLen = data.getBytes().length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offset > 0) {
            if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        // 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
        // 加密后的字符串
        return new String(BASE64_ENCODER.encode(encryptedData));
    }

    /**
     * RSA解密
     *
     * @param data       待解密数据
     * @param privateKeyStr 私钥
     */
    public static String decrypt(String data, String privateKeyStr) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM_NAME);
        cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKeyStr));
        byte[] dataBytes = BASE64_DECODER.decode(data);
        int inputLen = dataBytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offset > 0) {
            if (inputLen - offset > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        // 解密后的内容
        return new String(decryptedData, StandardCharsets.UTF_8);
    }

    // 测试
    public static void main(String[] args) throws Exception{
        // 获取公钥、私钥
        Map<String, String> keyPairMap = getKeyPairMap();
        String privateKey = keyPairMap.get("privateKey");
        String publicKey = keyPairMap.get("publicKey");
        System.out.println("privateKey = " + privateKey);
        System.out.println("publicKey = " + publicKey);
        // 要加密的字符串
        String data = "admin.123";
        // 使用公钥加密
        String encrypt = encrypt(data, publicKey);
        System.out.println("encrypt = " + encrypt);
        // 使用私钥解密
        String decrypt = decrypt(encrypt, privateKey);
        System.out.println("decrypt = " + decrypt);
    }
}

前端加密

npm install jsencrypt
import JSEncrypt from 'jsencrypt'
// 创建加密对象实例
const encryptor = new JSEncrypt()
const pubKey = ''
// 设置公钥
encryptor.setPublicKey(pubKey)
// 对内容进行加密
const rsaPassWord = encryptor.encrypt('要加密的内容')