Harmony应用 ArkTs AES 加密方法之GCM对称加密

加解密介绍

在数据存储或传输场景中,可以使用加解密操作用于保证数据的机密性,防止敏感数据泄露。

使用加解密操作中,典型的场景有:

  1. 使用对称密钥的加解密操作。

  2. 使用非对称密钥的加解密操作。

  3. 使用RSA(PKCS1_OAEP填充模式)时,获取、设置CipherSpecItem参数。

加解密算法规格

使用AES对称密钥(GCM模式)加解密(ArkTS)

对应的算法规格请查看对称密钥加解密算法规格:AES

加密

  1. 调用cryptoFramework.createSymKeyGeneratorSymKeyGenerator.generateSymKey,生成密钥算法为AES、密钥长度为128位的对称密钥(SymKey)。

    如何生成AES对称密钥,开发者可参考下文示例,并结合对称密钥生成和转换规格:AES随机生成对称密钥理解,参考文档与当前示例可能存在入参差异,请在阅读时注意区分。

  2. 调用cryptoFramework.createCipher,指定字符串参数'AES128|GCM|PKCS7',创建对称密钥类型为AES128、分组模式为GCM、填充模式为PKCS7的Cipher实例,用于完成加解密操作。

  3. 调用Cipher.init,设置模式为加密(CryptoMode.ENCRYPT_MODE),指定加密密钥(SymKey)和GCM模式对应的加密参数(GcmParamsSpec),初始化加密Cipher实例。

  4. 调用Cipher.update,更新数据(明文)。

    当前单次update长度没有限制,开发者可以根据数据量判断如何调用update。

    • 当数据量较小时,可以在init完成后直接调用doFinal。
    • 当数据量较大时,可以多次调用update,即分段加解密。
  5. 调用Cipher.doFinal,获取加密后的数据。

    • 由于已使用update传入数据,此处data传入null。
    • doFinal输出结果可能为null,在访问具体数据前,需要先判断结果是否为null,避免产生异常。
  6. 读取GcmParamsSpec.authTag作为解密的认证信息。

    在GCM模式下,需要从加密后的数据中取出末尾16字节,作为解密时初始化的认证信息。示例中authTag恰好为16字节。

解密

  1. 调用Cipher.init,设置模式为解密(CryptoMode.DECRYPT_MODE),指定解密密钥(SymKey)和GCM模式对应的解密参数(GcmParamsSpec),初始化解密Cipher实例。

  2. 调用Cipher.update,更新数据(密文)。

  3. 调用Cipher.doFinal,获取解密后的数据。

  • 异步方法示例:

    TypeScript 复制代码
    import { cryptoFramework } from '@kit.CryptoArchitectureKit';
    import { buffer } from '@kit.ArkTS';
    
    function genGcmParamsSpec() {
      let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes
      let dataIv = new Uint8Array(arr);
      let ivBlob: cryptoFramework.DataBlob = { data: dataIv };
      arr = [0, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes
      let dataAad = new Uint8Array(arr);
      let aadBlob: cryptoFramework.DataBlob = { data: dataAad };
      arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes
      let dataTag = new Uint8Array(arr);
      let tagBlob: cryptoFramework.DataBlob = {
        data: dataTag
      }; 
      // GCM的authTag在加密时从doFinal结果中获取,在解密时填入init函数的params参数中
      let gcmParamsSpec: cryptoFramework.GcmParamsSpec = {
        iv: ivBlob,
        aad: aadBlob,
        authTag: tagBlob,
        algName: "GcmParamsSpec"
      };
      return gcmParamsSpec;
    }
    
    let gcmParams = genGcmParamsSpec();
    
    // 加密消息
    async function encryptMessagePromise(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) {
      let cipher = cryptoFramework.createCipher('AES128|GCM|PKCS7');
      await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, gcmParams);
      let encryptUpdate = await cipher.update(plainText);
      // gcm模式加密doFinal时传入空,获得tag数据,并更新至gcmParams对象中。
      gcmParams.authTag = await cipher.doFinal(null);
      return encryptUpdate;
    }
    // 解密消息
    async function decryptMessagePromise(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) {
      let decoder = cryptoFramework.createCipher('AES128|GCM|PKCS7');
      await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, gcmParams);
      let decryptUpdate = await decoder.update(cipherText);
      // gcm模式解密doFinal时传入空,验证init时传入的tag数据,如果验证失败会抛出异常。
      let decryptData = await decoder.doFinal(null);
      if (decryptData == null) {
        console.info('GCM decrypt success, decryptData is null');
      }
      return decryptUpdate;
    }
    async function genSymKeyByData(symKeyData: Uint8Array) {
      let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
      let aesGenerator = cryptoFramework.createSymKeyGenerator('AES128');
      let symKey = await aesGenerator.convertKey(symKeyBlob);
      console.info('convertKey success');
      return symKey;
    }
    async function main() {
      let keyData = new Uint8Array([83, 217, 231, 76, 28, 113, 23, 219, 250, 71, 209, 210, 205, 97, 32, 159]);
      let symKey = await genSymKeyByData(keyData);
      let message = "This is a test";
      let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) };
      let encryptText = await encryptMessagePromise(symKey, plainText);
      let decryptText = await decryptMessagePromise(symKey, encryptText);
      if (plainText.data.toString() === decryptText.data.toString()) {
        console.info('decrypt ok');
        console.info('decrypt plainText: ' + buffer.from(decryptText.data).toString('utf-8'));
      } else {
        console.error('decrypt failed');
      }
    }
  • 同步方法示例:

    TypeScript 复制代码
    import { cryptoFramework } from '@kit.CryptoArchitectureKit';
    import { buffer } from '@kit.ArkTS';
    
    
    
    function genGcmParamsSpec() {
      let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes
      let dataIv = new Uint8Array(arr);
      let ivBlob: cryptoFramework.DataBlob = { data: dataIv };
      arr = [0, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes
      let dataAad = new Uint8Array(arr);
      let aadBlob: cryptoFramework.DataBlob = { data: dataAad };
      arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes
      let dataTag = new Uint8Array(arr);
      let tagBlob: cryptoFramework.DataBlob = {
        data: dataTag
      };
      // GCM的authTag在加密时从doFinal结果中获取,在解密时填入init函数的params参数中
      let gcmParamsSpec: cryptoFramework.GcmParamsSpec = {
        iv: ivBlob,
        aad: aadBlob,
        authTag: tagBlob,
        algName: "GcmParamsSpec"
      };
      return gcmParamsSpec;
    }
    
    let gcmParams = genGcmParamsSpec();
    
    // 加密消息
    function encryptMessage(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) {
      let cipher = cryptoFramework.createCipher('AES128|GCM|PKCS7');
      cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, gcmParams);
      let encryptUpdate = cipher.updateSync(plainText);
      // gcm模式加密doFinal时传入空,获得tag数据,并更新至gcmParams对象中。
      gcmParams.authTag = cipher.doFinalSync(null);
      return encryptUpdate;
    }
    // 解密消息
    function decryptMessage(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) {
      let decoder = cryptoFramework.createCipher('AES128|GCM|PKCS7');
      decoder.initSync(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, gcmParams);
      let decryptUpdate = decoder.updateSync(cipherText);
      // gcm模式解密doFinal时传入空,验证init时传入的tag数据,如果验证失败会抛出异常。
      let decryptData = decoder.doFinalSync(null);
      if (decryptData == null) {
        console.info('GCM decrypt success, decryptData is null');
      }
      return decryptUpdate;
    }
    async function genSymKeyByData(symKeyData: Uint8Array) {
      let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
      let aesGenerator = cryptoFramework.createSymKeyGenerator('AES128');
      let symKey = await aesGenerator.convertKey(symKeyBlob);
      console.info('convertKey success');
      return symKey;
    }
    async function main() {
      let keyData = new Uint8Array([83, 217, 231, 76, 28, 113, 23, 219, 250, 71, 209, 210, 205, 97, 32, 159]);
      let symKey = await genSymKeyByData(keyData);
      let message = "This is a test";
      let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) };
      let encryptText = encryptMessage(symKey, plainText);
      let decryptText = decryptMessage(symKey, encryptText);
      if (plainText.data.toString() === decryptText.data.toString()) {
        console.info('decrypt ok');
        console.info('decrypt plainText: ' + buffer.from(decryptText.data).toString('utf-8'));
      } else {
        console.error('decrypt failed');
      }
    }

原文档参考:文档中心

相关推荐
goto_w1 小时前
uniapp上使用webview与浏览器交互,支持三端(android、iOS、harmonyos next)
android·vue.js·ios·uni-app·harmonyos
别说我什么都不会16 小时前
ohos.net.http请求HttpResponse header中set-ccokie值被转成array类型
网络协议·harmonyos
码是生活17 小时前
鸿蒙开发排坑:解决 resourceManager.getRawFileContent() 获取文件内容为空问题
前端·harmonyos
鸿蒙场景化示例代码技术工程师17 小时前
基于Canvas实现选座功能鸿蒙示例代码
华为·harmonyos
小脑斧爱吃鱼鱼18 小时前
鸿蒙项目笔记(1)
笔记·学习·harmonyos
鸿蒙布道师19 小时前
鸿蒙NEXT开发对象工具类(TS)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
zhang10620919 小时前
HarmonyOS 基础组件和基础布局的介绍
harmonyos·基础组件·基础布局
马剑威(威哥爱编程)19 小时前
在HarmonyOS NEXT 开发中,如何指定一个号码,拉起系统拨号页面
华为·harmonyos·arkts
GeniuswongAir20 小时前
Flutter极速接入IM聊天功能并支持鸿蒙
flutter·华为·harmonyos
90后的晨仔1 天前
鸿蒙ArkUI框架中的状态管理
harmonyos