AES分段加解密,分组模式采用CBC,填充方式采用PKCS7,对超大量数据进行分段加解密

AES分段加解密

HarmonyOS
2024-05-28 21:27:00
浏览
收藏 0
回答 1
回答 1
按赞同
/
按时间
宇宙无敌超英俊

本文主要介绍AES的分段加解密,分组模式采用CBC,填充方式采用PKCS7,对超大量数据进行分段加解密。

使用的核心API

AES的生成规格

AES的分段加解密开发步骤

核心代码解释

我们需要注意:在进行对称加解密操作的时候,如果开发者对各个分组模式不够熟悉,建议对每次update和doFinal的结果都判断是否为null,并在结果不为null时取出其中的数据进行拼接,形成完整的密文/明文。这是因为选择的分组模式等各项规格都可能对update和doFinal结果产生影响。update只要凑满一个新的分组就会有输出,如果没有凑满则此次update输出为null,把当前还没被加/解密的数据留着,等下一次update/doFinal传入数据的时候,拼接起来继续凑分组。

最后doFinal的时候,会把剩下的还没加/解密的数据,根据createCipher时设置的padding模式进行填充,补齐到分组的整数倍长度,再输出剩余加解密结果。

根据数据量,可以不调用update(即init完成后直接调用doFinal)或多次调用update。

算法库目前没有对update(单次或累计)的数据量设置大小限制,建议对于大数据量的对称加解密,可以采用多次update的方式传入数据。

核心代码如下:

import cryptoFramework from '@ohos.security.cryptoFramework'; 
import { BusinessError } from '@ohos.base'; 
import buffer from '@ohos.buffer'; 
  
  
  
// 字符串转成字节流 
function stringToUint8Array(str: string) { 
  return new Uint8Array(buffer.from(str, 'utf-8').buffer); 
} 
  
// 字节流转成可理解的字符串 
function uint8ArrayToString(array: Uint8Array) { 
  // 将UTF-8编码转换成Unicode编码 
  let out: string = ""; 
  let index: number = 0; 
  let len: number = array.length; 
  while (index < len) { 
    let character = array[index++]; 
    switch (character >> 4) { 
      case 0: 
      case 1: 
      case 2: 
      case 3: 
      case 4: 
      case 5: 
      case 6: 
      case 7: 
        out += String.fromCharCode(character); 
        break; 
      case 12: 
      case 13: 
        out += String.fromCharCode(((character & 0x1F) << 6) | (array[index++] & 0x3F)); 
        break; 
      case 14: 
        out += String.fromCharCode(((character & 0x0F) << 12) | ((array[index++] & 0x3F) << 6) | ((array[index++] & 0x3F) << 0)); 
        break; 
      default: 
        break; 
    } 
  } 
  return out; 
} 
  
function genIvParamsSpec() { 
  let arr = [71,67,48,86,67,57,77,86,84,53,55,72,72,85,52,68]; 
  let dataIv = new Uint8Array(arr); 
  let ivBlob: cryptoFramework.DataBlob = { data: dataIv }; 
  let ivParamsSpec: cryptoFramework.IvParamsSpec = { 
    algName: "IvParamsSpec", 
    iv: ivBlob 
  }; 
  return ivParamsSpec; 
} 
  
async function testAesMultiUpdate(plainText: string) { 
    let symAlgName = 'AES128'; 
    let length = 30; 
    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 
    // 创建 Cipher 实例。 
    let cipherAlgName = 'AES128|CBC|PKCS7'; 
    let globalCipher = cryptoFramework.createCipher(cipherAlgName); 
    let globalCipherText: cryptoFramework.DataBlob; 
    let globalKey: cryptoFramework.SymKey; 
    let globalPlainText = ''; 
    let result = new Uint8Array(); 
    let str = ""; 
    let data: cryptoFramework.DataBlob 
    let startEecrypt = 0 
    let endEecrypt = 0 
    let startDecrypt = 0 
    let endDecrypt = 0 
  
    // 使用密钥生成器随机生成 128 位对称密钥。 
    let promiseSymKey = await symKeyGenerator.generateSymKey(); 
    await globalCipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, promiseSymKey, genIvParamsSpec()); 
    let updateOutput: cryptoFramework.DataBlob; 
  
    while (plainText.length > 0) { 
      const contentCurr = plainText.substring(0, length); // 超过长度会取最长 
      plainText = plainText.substring(length, plainText.length); // 起始点大于长度会返回"" 
      let messageBlob: cryptoFramework.DataBlob = { data: stringToUint8Array(contentCurr) }; 
      updateOutput = await globalCipher.update(messageBlob); 
      if (updateOutput != null) { 
        let mergeText = new Uint8Array(result.length + updateOutput.data.length); 
        mergeText.set(result); 
        mergeText.set(updateOutput.data, result.length); 
        result = mergeText; 
      } 
    } 
  
    globalCipherText = { data: result } 
    startEecrypt = new Date().getTime() 
    data = await globalCipher.doFinal(null); 
    endEecrypt = new Date().getTime() 
    console.log("TEST==jiami" + (endEecrypt - startEecrypt)) 
    let mergeText = new Uint8Array(result.length + data.data.length); 
    mergeText.set(result); 
    mergeText.set(data.data, result.length); 
    result = mergeText; 
  
    let resultTemp = new Uint8Array(); 
    let contentTemp = result; 
    console.log("TEST==加密成功") 
    await globalCipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, promiseSymKey, genIvParamsSpec()); 
  
  
    console.log("TEST==长度" + contentTemp.length) 
  
    while (contentTemp.length > 0) { 
      const contentCurr = contentTemp.slice(0, length); // 超过长度会取最长 
      contentTemp = contentTemp.slice(length, contentTemp.length); // 起始点大于长度会返回"" 
      let messageBlob: cryptoFramework.DataBlob = { data: contentCurr }; 
      let updateOutput = await globalCipher.update(messageBlob); // 按细分市场更新。 
      if (updateOutput != null) { 
        let mergeText = new Uint8Array(resultTemp.length + updateOutput.data.length); 
        mergeText.set(resultTemp); 
        mergeText.set(updateOutput.data, resultTemp.length); 
        resultTemp = mergeText; 
      } 
    } 
  
    //明文结果 
    str = uint8ArrayToString(resultTemp) 
    startEecrypt = new Date().getTime() 
    let mingwen: cryptoFramework.DataBlob 
    mingwen = await globalCipher.doFinal(null); 
    endEecrypt = new Date().getTime() 
    console.log("TEST== jiemi:" + (endEecrypt - startEecrypt)) 
  
    if (mingwen != null) { 
      str = str + uint8ArrayToString(mingwen.data); 
    } 
    AlertDialog.show({ message: str }); 
    console.info(`decrypt output: ${str}`); 
    endEecrypt = new Date().getTime() 
    console.log("TEST== startEecrypt:" + startEecrypt) 
    console.log("TEST== endEecrypt:" + endEecrypt) 
  
  
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.

实现效果

适配的版本信息

  • IDE:DevEco    Studio 4.1.3.500
  • SDK:API11
分享
微博
QQ
微信
回复
2024-05-29 22:38:19
相关问题
SM4采用OFB模式进行加解密
1674浏览 • 1回复 待解决
AES加解密长字符串是否需要分段
797浏览 • 1回复 待解决
HarmonyOS AES/ECB/PKCS7Padding 加解密
351浏览 • 1回复 待解决
HarmonyOS AES-CBC加解密
589浏览 • 1回复 待解决
HarmonyOS 加解密方式 AES/ECB/PKCS5Padding
520浏览 • 1回复 待解决
HarmonyOS AES加解密咨询
669浏览 • 1回复 待解决
HarmonyOS AES加解密问题
649浏览 • 1回复 待解决
如何使用SM4的CBC模式加解密
1755浏览 • 1回复 待解决
如何进行不同规格的AES加解密
1364浏览 • 1回复 待解决
HarmonyOS AES加解密报错17630001
614浏览 • 1回复 待解决
SM4 CBC模式加解密,有好的方案吗?
1578浏览 • 1回复 待解决
多种加密方式实现加解密
1453浏览 • 1回复 待解决
HarmonyOS AES加解密与java无法通用
946浏览 • 1回复 待解决
HarmonyOS aes gcm加解密c/c++库
588浏览 • 1回复 待解决
HarmonyOS 加解密问题
596浏览 • 1回复 待解决
HarmonyOS AES加解密过程实在是调不通
432浏览 • 1回复 待解决
HarmonyOS 如何进行DES加解密
1165浏览 • 1回复 待解决