文章目录

  • 前言
  • 一、什么是对称加密和非对称加密?
  • 1.1、对称加密介绍
  • 1.2、非对称加密介绍
  • 二、RSA非对称加密前后端实现
  • 2.1、前端实现rsa
  • 2.2、后端实现rsa解密
  • 三、AES加密前后端实现
  • 3.1、AES前端实现
  • 3.2、AES后端解密实现(2种方式)


前言

项目中正好遇到给私密参数加密的步骤,特意学习了非对称加密和对称加密的2个个例。


一、什么是对称加密和非对称加密?

1.1、对称加密介绍

对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key)。

对称加密通常使用的是相对较小的密钥,一般小于256 bit。因为密钥越大,加密越强,但加密与解密的过程越慢。

对称加密的一大缺点是密钥的管理与分配,换句话说,如何把密钥发送到需要解密你的消息的人的手里是一个问题。在发送密钥的过程中,密钥有很大的风险会被黑客们拦截。现实中通常的做法是将对称加密的密钥进行非对称加密,然后传送给需要它的人。

对称加密,加密速度非常快,适合经常发送数据的场合。缺点是密钥的传输比较麻烦,常见的aes。

1.2、非对称加密介绍

非对称加密为数据的加密与解密提供了一个非常安全的方法,它使用了一对密钥,公钥(public key)和私钥(private key)。私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。非对称加密使用这对密钥中的一个进行加密,而解密则需要另一个密钥,公钥加密,私钥解密。    非对称算法,加密解密的速度比较慢,适合偶尔发送数据的场合。优点是密钥传输方便。常见的非对称加密算法为RSA、ECC和EIGamal

AES加密原理RAS加密原理

二、RSA非对称加密前后端实现

2.1、前端实现rsa

1、安装jsencrypt,执行以下命令

npm install jsencrypt --save-dev

2 、安装encryptlong,执行以下命令

npm i encryptlong -S

3、生成公钥私钥 准备publicKey(公钥)&& privateKey(私钥)在线生成公钥私钥网址

4、前端代码实现

/* 产引入jsencrypt实现数据RSA加密 */
import JSEncrypt from 'jsencrypt' // 处理长文本数据时报错 jsencrypt.js Message too long for RSA
/* 产引入encryptlong实现数据RSA加密 */
import Encrypt from 'encryptlong' // encryptlong是基于jsencrypt扩展的长文本分段加解密功能。
 
// 密钥对生成 http://web.chacuo.net/netrsakeypair
 
// 公钥key
const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANL378k3RiZHWx5AfJqdH9xRNBmD9wGD\n' +
  '2iRe41HdTNF8RUhNnHit5NpMNtGL0NPTSSpPjjI1kJfVorRvaQerUgkCAwEAAQ=='
// 私钥key
const privateKey = 'MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8\n' +
  'mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9p\n' +
  'B6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue\n' +
  '/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZ\n' +
  'UBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6\n' +
  'vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha\n' +
  '4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3\n' +
  'tTbklZkD2A=='
 
export default {
  /* JSEncrypt加密 */
  rsaPublicData(data) {
    var jsencrypt = new JSEncrypt()
    jsencrypt.setPublicKey(publicKey)
    // 如果是对象/数组的话,需要先JSON.stringify转换成字符串
    var result = jsencrypt.encrypt(data)
    return result
  },
  /* JSEncrypt解密 */
  rsaPrivateData(data) {
    var jsencrypt = new JSEncrypt()
    jsencrypt.setPrivateKey(privateKey)
    // 如果是对象/数组的话,需要先JSON.stringify转换成字符串
    var result = jsencrypt.encrypt(data)
    return result
  },
  /* 加密 */
  encrypt(data) {
    const PUBLIC_KEY = publicKey
    var encryptor = new Encrypt()
    encryptor.setPublicKey(PUBLIC_KEY)
    // 如果是对象/数组的话,需要先JSON.stringify转换成字符串
    const result = encryptor.encryptLong(data)
    return result
  },
  /* 解密 - PRIVATE_KEY - 验证 */
  decrypt(data) {
    const PRIVATE_KEY = privateKey
    var encryptor = new Encrypt()
    encryptor.setPrivateKey(PRIVATE_KEY)
    // 如果是对象/数组的话,需要先JSON.stringify转换成字符串
    var result = encryptor.decryptLong(data)
    return result
  }
}

4、全局引用

import Rsa from "@/utils/rsa.js"
Vue.prototype.Rsa = Rsa //

5、在*.vue 页面使用RSA加解,全局使用

this.Rsa.方法名

参考前端实现

2.2、后端实现rsa解密

1、引入hutool依赖

<!-- 工具类 参考https://hutool.cn/docs-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.3.10</version>
        </dependency>

2、方法

private String decodeStr(String encodeStr) {
        try {
            String privateKey = ResourceUtil.readUtf8Str(PRIVATE_KEY_LOCATION);
            RSA rsa = new RSA(privateKey, null);
            byte[] aByte = SecureUtil.decode(encodeStr);
            byte[] decrypt = rsa.decrypt(aByte, KeyType.PrivateKey);
            return StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8);
        } catch (Exception e) {
            logger.error("RSA私钥解密失败!", e);
            throw new BadCredentialsException(encodeStr);
        }
    }

3、hutool加密解密使用参考

hutools地址

aes对称加密算法流程图 aes加密 对称 非对称_安全

三、AES加密前后端实现

3.1、AES前端实现

1、下载依赖

下载crypto-js
npm install crypto-js --save

2、代码具体使用

import CryptoJS from 'crypto-js'

const key = 'f4k9f5w7f8g4er26' //前后端使用同意秘钥
// 偏移量 16位(不可随意修改,否则前后端加密解密可能失败)
const iv = '0000000000000000'

export function encrypt(data) {
  return CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(data), CryptoJS.enc.Utf8.parse(key), {
    iv: CryptoJS.enc.Utf8.parse(iv),
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7
  })
    .toString()
}
export function decrypt(data) {
  const decrypted = CryptoJS.AES.decrypt(data, CryptoJS.enc.Utf8.parse(key), {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7
  })
  return decrypted.toString(CryptoJS.enc.Utf8).toString()
}

3、全局引用同上rsa

3.2、AES后端解密实现(2种方式)

1、使用hutool工具类(使用hutool相对更加方便)

aes对称加密算法流程图 aes加密 对称 非对称_非对称加密_02

String content = "test中文";

//随机生成密钥
byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();

//构建
SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);

//加密
byte[] encrypt = aes.encrypt(content);
//解密
byte[] decrypt = aes.decrypt(encrypt);

//加密为16进制表示
String encryptHex = aes.encryptHex(content);
//解密为字符串
String decryptStr = aes.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);

2、使用commons-code依赖的工具 引入依赖

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.15</version>
</dependency>

aes工具类

public class Encrypt {

    //--------------AES---------------
    private static final String KEY = "f4k9f5w7f8g4er26";  // 密匙,必须16位
    private static final String ENCODING = "UTF-8"; // 编码
    private static final String ALGORITHM = "AES"; //算法
    private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding"; // 默认的加密算法,ECB模式

    /**
     *  AES加密
     * @param data
     * @return String
     */
    public static String AESencrypt(String data) throws Exception
    {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE,new SecretKeySpec(KEY.getBytes(),"AES"));
        byte[] b = cipher.doFinal(data.getBytes("utf-8"));
        //采用base64算法进行转码,避免出现中文乱码
        return Base64.encodeBase64String(b);
    }

    /**
     * AES解密
     * @param data
     * @return String
     */
    public static String AESdecrypt(String data) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(KEY.getBytes(), "AES"));
        byte[] b = cipher.doFinal(Base64.decodeBase64(data));
        //采用base64算法进行转码,避免出现中文乱码
        return new String(b);
    }
    public static void main(String[] args) throws Exception {
        String mi = Encrypt.AESencrypt("111111");
        System.out.println(mi);
    }

}