You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何同步实现AES-GCM加解密?Web Crypto API及替代方案咨询

解决方案:AES-GCM同步加密适配Angular应用

一、使用现有crypto-js实现同步AES-GCM加解密

你当前的Angular应用已经在使用crypto-js,实际上该库原生支持AES-GCM模式,无需更换新库,只需调整加密配置即可,这是改动最小的方案。

示例代码

加密(同步)

import * as CryptoJS from 'crypto-js';

function encryptAesGcm(data: string, key: string): string {
  // 生成随机IV(AES-GCM要求IV长度为12字节,推荐值)
  const iv = CryptoJS.lib.WordArray.random(12);
  
  // 执行加密,指定模式为GCM
  const encrypted = CryptoJS.AES.encrypt(data, key, {
    mode: CryptoJS.mode.GCM,
    iv: iv,
    padding: CryptoJS.pad.NoPadding // GCM模式无需填充
  });
  
  // 将IV和密文拼接后返回(解密时需要用到IV)
  return iv.toString(CryptoJS.enc.Base64) + ':' + encrypted.toString();
}

解密(同步)

function decryptAesGcm(encryptedData: string, key: string): string {
  // 拆分IV和密文
  const [ivBase64, ciphertext] = encryptedData.split(':');
  const iv = CryptoJS.enc.Base64.parse(ivBase64);
  
  // 执行解密
  const decrypted = CryptoJS.AES.decrypt(ciphertext, key, {
    mode: CryptoJS.mode.GCM,
    iv: iv,
    padding: CryptoJS.pad.NoPadding
  });
  
  return decrypted.toString(CryptoJS.enc.Utf8);
}

这种方式完全沿用你现有代码的调用风格,仅需替换原AES-CBC的配置,几乎不需要修改业务调用逻辑。

二、将Web Crypto API封装为“类同步”调用方式

Web Crypto API本身是异步的,但可以通过封装让调用逻辑更贴近原有同步代码的风格,最小化改动量。

封装思路

  1. 把Web Crypto的异步操作封装到Angular服务中,对外暴露类似同步的方法(实际是返回Promise,用async/await调用)
  2. 统一处理密钥、数据的格式转换(比如字符串与ArrayBuffer的互转),让调用方无需关心底层细节

示例封装服务

import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class CryptoService {
  // 将字符串转为ArrayBuffer
  private stringToArrayBuffer(str: string): ArrayBuffer {
    return new TextEncoder().encode(str);
  }

  // 将ArrayBuffer转为Base64字符串
  private arrayBufferToBase64(buf: ArrayBuffer): string {
    return btoa(String.fromCharCode(...new Uint8Array(buf)));
  }

  // 将Base64字符串转为ArrayBuffer
  private base64ToArrayBuffer(base64: string): ArrayBuffer {
    const binary = atob(base64);
    const buf = new ArrayBuffer(binary.length);
    const view = new Uint8Array(buf);
    for (let i = 0; i < binary.length; i++) {
      view[i] = binary.charCodeAt(i);
    }
    return buf;
  }

  // 生成AES密钥(从字符串密钥转换)
  private async getKeyFromRawString(key: string): Promise<CryptoKey> {
    const keyBuffer = this.stringToArrayBuffer(key);
    return crypto.subtle.importKey(
      'raw',
      keyBuffer,
      { name: 'AES-GCM' },
      false,
      ['encrypt', 'decrypt']
    );
  }

  // 加密方法(对外暴露,调用时用await)
  async encrypt(data: string, key: string): Promise<string> {
    const cryptoKey = await this.getKeyFromRawString(key);
    const iv = crypto.getRandomValues(new Uint8Array(12)); // 12字节IV
    const dataBuffer = this.stringToArrayBuffer(data);
    
    const encryptedBuffer = await crypto.subtle.encrypt(
      { name: 'AES-GCM', iv: iv },
      cryptoKey,
      dataBuffer
    );

    // 拼接IV和密文(Base64格式)
    const ivBase64 = this.arrayBufferToBase64(iv);
    const ciphertextBase64 = this.arrayBufferToBase64(encryptedBuffer);
    return `${ivBase64}:${ciphertextBase64}`;
  }

  // 解密方法(对外暴露,调用时用await)
  async decrypt(encryptedData: string, key: string): Promise<string> {
    const [ivBase64, ciphertextBase64] = encryptedData.split(':');
    const iv = this.base64ToArrayBuffer(ivBase64);
    const ciphertextBuffer = this.base64ToArrayBuffer(ciphertextBase64);
    
    const cryptoKey = await this.getKeyFromRawString(key);
    const decryptedBuffer = await crypto.subtle.decrypt(
      { name: 'AES-GCM', iv: iv },
      cryptoKey,
      ciphertextBuffer
    );

    return new TextDecoder().decode(decryptedBuffer);
  }
}

业务代码调用示例

原来的同步调用代码:

const encrypted = CryptoJS.AES.encrypt(data, key, cbcOptions).toString();

现在只需改为:

// 在async函数中调用
const encrypted = await this.cryptoService.encrypt(data, key);

如果原有代码在非异步上下文(比如组件的构造函数),可以用IIFE包裹:

(async () => {
  const encrypted = await this.cryptoService.encrypt(data, key);
  // 后续业务逻辑
})();

这种方式仅需修改加密解密的调用处,业务逻辑基本无需调整,能最大程度保证应用稳定性。


内容的提问来源于stack exchange,提问作者user3860630

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 04:15:37