一种新的加密前后端的数据的方式

时之世 发布于 2024-09-06 372 次阅读 预计阅读时间: 4 分钟 最后更新于 2024-12-16 791 字 无~


AI 摘要

一种新的加密前后端的数据的方式介绍了在 React 前端和 Springboot 后端中使用 AES 和 RSA 加密算法保护数据的方法。首先,在 React 组件中,展示了对称加密的代码和非对称加密的代码。对称加密使用了 AES 算法,通过 Base64 编码的密钥进行加密和解密操作;非对称加密则是使用了 RSA 算法,生成密钥对并对消息进行加密和解密。 接着,在 Springboot 后端中,展示了对称加密的代码。通过 AES 算法生成密钥,并将密钥转换为 Base64 编码的字符串用于加密文本。加密过程包括将密钥解码并初始化加密器,最终返回加密后的字符串。这种新的加密方式保障了前后端数据的安全传输和存储。

如图所示,这里就不写 Redis 了,只展示 React 前端及 Springboot 后端加密代码


一、首先是 React 组件

AES 对称加密

import CryptoJS from 'crypto-js';


function validateKey(key) {
    const keyBytes = CryptoJS.enc.Base64.parse(key);
    const keyLength = keyBytes.sigBytes;
    if (keyLength !== 32) {
        throw new Error('Invalid key length. Key must be 32 bytes long.');
    }
    console.log(keyBytes)
    return keyBytes;
}
/**
 * 加密
 * @param {string} message - 需要加密的消息
 * @param {string} key - 加密密钥 (Base64 编码)
 */
function AESEncrypt(message, key) {
    const keyBytes = validateKey(key);
    const encrypted = CryptoJS.AES.encrypt(message, keyBytes, {
        mode: CryptoJS.mode.ECB1,
        padding: CryptoJS.pad.Pkcs7
    });
    console.log('Encrypted:', encrypted.toString());
    return encrypted.toString();
}
/**
 * 解密
 * @param {string} encryptedMessage - 加密后的消息
 * @param {string} key - 解密密钥 (Base64 编码)
 */
function AESDecrypt(encryptedMessage, key) {
    try {
        const wordArrayKey = validateKey(key);
        const decrypted = CryptoJS.AES.decrypt(encryptedMessage, wordArrayKey,{
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
        });
        return decrypted.toString(CryptoJS.enc.Utf8);
    } catch (error) {
        console.error('Decryption error:', error);
        return null;
    }
}

export { AESEncrypt, AESDecrypt };

RSA 非对称加密

import JSEncrypt from 'jsencrypt';

//生成 RSA 密钥对
function generateRSAKeyPair() {
    const encrypt = new JSEncrypt();
    encrypt.getKey();
    const privateKey = encrypt.getprivateKey();
    const publicKey = encrypt.getpublicKey();
    return { publicKey: publicKey, privateKey: privateKey };
}


// 公钥加密
function RSAEncrypt(text, publicKey) {
    const encrypt = new JSEncrypt();
    encrypt.setpublicKey(publicKey);
    const encrypted = encrypt.encrypt(text);
    return encrypted;
}

// 私钥解密
function RSADecrypt(text, privateKey) {
    const decrypt = new JSEncrypt();
    decrypt.setprivateKey(privateKey);
    const decrypted = decrypt.decrypt(text);
    return decrypted;
}

export { generateRSAKeyPair, RSAEncrypt, RSADecrypt }

二、接着是 Springboot 后端

AES 对称加密

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * 对称加密
 */

public class AESUtils {

    /**
     * 生成 AES 密钥
     *
     * @return 生成的 AES 密钥
     * @throws NoSuchAlgorithmException 如果没有提供 AES 算法实现
     */
    public static SecretKey generateAESKey() throws NoSuchAlgorithmException {
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(256); // 生成 256 位的密钥
        return keyGen.generateKey();
    }



    /**
     * 将 SecretKey 转换为 Base64 编码的字符串
     *
     * @param secretKey 要转换的 SecretKey
     * @return 转换后的 Base64 编码字符串
     */
    public static String getSecretKeyString(SecretKey secretKey) {
        return Base64.getEncoder().encodeToString(secretKey.getEncoded());
    }

    /**
     * 使用 AES 算法加密文本
     *
     * @param text 要加密的文本
     * @param secretKeyStr Base64 编码的 AES 密钥字符串
     * @return 加密后的字符串
     * @throws Exception 如果加密过程中发生错误
     */
    public static String aesEncrypt(String text, String secretKeyStr) throws Exception {
        byte[] decodedKey = Base64.getDecoder().decode(secretKeyStr.getBytes());
        SecretKeySpec secretKeySpec = new SecretKeySpec(decodedKey, "AES");

        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);

        byte[] encryptedBytes = cipher.doFinal(text.getBytes());
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    /**
     * 使用 AES 算法解密文本
     *
     * @param encryptedText Base64 编码的加密文本
     * @param secretKeyStr Base64 编码的 AES 密钥字符串
     * @return 解密后的字符串
     * @throws Exception 如果解密过程中发生错误
     */
    public static String aesDecrypt(String encryptedText, String secretKeyStr) throws Exception {
        byte[] decodedKey = Base64.getDecoder().decode(secretKeyStr);
        SecretKeySpec secretKeySpec = new SecretKeySpec(decodedKey, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);

        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        return new String(decryptedBytes,StandardCharsets.UTF_8);
    }


}

RSA 非对称加密

package com.example.SuperChain.util;

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RSAUtils {

    public static String rsaEncrypt(String text, String publicKeyStr) throws Exception {
        // 去掉 PEM 格式的头尾注释行和换行符
        String cleanedPublicKeyStr = publicKeyStr
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "")
                .replaceAll("\\s+", ""); // 移除所有空格和换行符2

        byte[] encodedKey = Base64.getDecoder().decode(cleanedPublicKeyStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);

        // 加密操作
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        byte[] encryptedBytes = cipher.doFinal(text.getBytes());
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }
}

三、注意

在进行加解密前,数据必须转换为 String 字符串形式


  1. 这里与其他的高亮文本对应,这些前后端加解密设置无论怎样改,都必须保证一致 ↩︎
  2. 这是由于前端生成的公钥为-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIOtoV7nNGe6acqP3KySw/mNZG\nx77j5Q9fD102aVifcag5SMv8JW7V/8t+5tNrmeFuP4fRu3WC+/pJBGCjpI7KDAnO\nKfIrHfK6tKTzmlweiwDcnCY9UWVXz43b186NMn8r1aw/m1TrLzrwegGbtOR8oJ+g\n5U6jO6LnRhEVKYs83wIDAQAB\n-----END PUBLIC KEY-----的格式,所以需要去除头尾信息和换行符 ↩︎