前端Vue使用AES的GCM模式加密

写了个新的前端项目,公司要求,账号密码这些必须是加密传输的;后端使用了GCM模式加密,前端是复制的一个以前项目的代码,原来是有写加密的,使用的是CryptoJS组件CTR模式加密的,但是这个组件里面没有GCM加密模式,找了半天,发现浏览器其实是自带加密的组件的window.crypto,使用这个组件就可以使用GCM模式加密,代码贴在下面,顺便java代码也贴出来了。

CryptoJS 看点进源码里面看了下只支持这几种模式
在这里插入图片描述
去官网看了下 https://cryptojs.gitbook.io/docs#hashing,也是说支持这几种,估计是浏览器都支持了,所以CryptoJS也就没有再更新了吧
在这里插入图片描述

前端加密测试

包含了完整的加密解密代码,可以拷过去直接用

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
	<title>加密小工具</title>
</head>
<body>
  <textarea rows="8" cols="40" id="content"></textarea>
  <br>
  <button onclick="encrypt1()">加密</button>
  <button onclick="decrypt1()">解密</button>
  <p>结果: <label id='result'></label></p>
</body>
<script type="text/javascript">

  // 将字符串转换为字节数组
  function stringToUint8Array(str) {
    let arr = new Uint8Array(str.length);
    for (let i = 0; i < str.length; i++) {
      arr[i] = str.charCodeAt(i);
    }
    return arr;
  }

  // 导入密钥
  async function importKey(keyStr) {
    const keyBytes = stringToUint8Array(keyStr);
    const key = await window.crypto.subtle.importKey(
      'raw',
      keyBytes,
      'AES-GCM', // 或者其他算法
      false,
      ['encrypt', 'decrypt']
    );
    return key;
  }

  // 加密函数
  async function encrypt(message, key, iv) {
    let msgBuffer = new TextEncoder().encode(message);
    let ivBytes = stringToUint8Array(iv);
    let ciphertext = await window.crypto.subtle.encrypt(
      {
        name: "AES-GCM",
        iv: ivBytes
      },
      key,
      msgBuffer
    );
    return ciphertext;
  }

  async function decrypt(base64Ciphertext, key, iv) {
    // 将 Base64 字符串转换回 ArrayBuffer
    let ciphertext = window.atob(base64Ciphertext);
    let ciphertextBuffer = new Uint8Array(ciphertext.length);
    for (let i = 0; i < ciphertext.length; i++) {
      ciphertextBuffer[i] = ciphertext.charCodeAt(i);
    }

    let ivBytes = stringToUint8Array(iv);
    let plaintext = await window.crypto.subtle.decrypt(
      {
        name: "AES-GCM",
        iv: ivBytes
      },
      key,
      ciphertextBuffer.buffer
    );

    // 将 ArrayBuffer 转换为字符串
    let decoder = new TextDecoder();
    return decoder.decode(plaintext);
  }

  let key;
  let ivStr;
  (async () => {
    const keyStr = "你的密钥";  //"29H3LCRC49SGFR0A";
    ivStr = "iv信息";   //"FBTR064AT3LCRF4E";
    key = await importKey(keyStr);

    const ciphertext = await encrypt("uIv86omN9Fp#", key, ivStr);

    console.log("Encrypted:", ciphertext);
  })();
  
  function encrypt1() {
    const txt = document.getElementById("content").value;
    encrypt(txt, key, ivStr).then((ciphertext) => {
      console.log("Encrypted:", btoa(String.fromCharCode(...new Uint8Array(ciphertext))));
      document.getElementById("result").innerText = btoa(String.fromCharCode(...new Uint8Array(ciphertext)));
    });
  }

  function decrypt1() {
    const txt = document.getElementById("content").value;
    decrypt(txt, key, ivStr).then((plaintext) => {
      console.log("Decrypted:", plaintext);
      document.getElementById("result").innerText = plaintext;
    });
  }
</script>
</html>

Java加解密代码

要先引入一个包

<dependency>
   <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk18on</artifactId>
    <version>1.77</version>
</dependency>
package com.yuanjy.sf04;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.util.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLDecoder;
import java.security.Security;
import java.util.Base64;

public class GCMTest {

    private static String key = "你的密钥"; //"29H3LCRC49SGFR0A";

    private static String ivParameter = "iv信息"; //"FBTR064AT3LCRF4E";

    private static IvParameterSpec IV;

    private static final String ALGORITHMSTR = "AES/GCM/NoPadding";

    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        System.out.println(encrypt("admin", key));
        System.out.println(decrypt("yagZI4sMNgee5R/AXhdFCPAjF1k4"));
    }

    public static String decrypt(String encrypt) throws Exception {
        return URLDecoder.decode(decrypt(encrypt, key), "UTF-8");
    }

    public static String decrypt(String encryptStr, String decryptKey) throws Exception {
        return decryptByBytes(Base64.getDecoder().decode(encryptStr), decryptKey);
    }

    public static String decryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {
        byte[] iv = ivParameter.getBytes();
        IV = new IvParameterSpec(iv);
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Security.addProvider(new BouncyCastleProvider());
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR, "BC");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"), IV);
        byte[] decryptBytes = cipher.doFinal(encryptBytes);
        return new String(decryptBytes);
    }

    public static String encrypt(String content, String encryptKey) throws Exception {
        return Base64.getEncoder().encodeToString(encryptToBytes(content, encryptKey));
    }

    public static byte[] encryptToBytes(String content, String encryptKey) throws Exception {
        byte[] iv = ivParameter.getBytes();
        IV = new IvParameterSpec(iv);
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR, "BC");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"), IV);
        return cipher.doFinal(content.getBytes("utf-8"));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三书yjy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值