HUKS对于超过100k的明文数据加解密的处理

再加解密中,如果需要加密的明文超过一定的限制(超出100k),此时用常规的加解密已经不可以满足,需要使用分段加解密去处理。

HarmonyOS
2024-05-28 21:21:48
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
kersin

使用的核心API

@ohos.security.huks

核心代码解释

private static DEF_KEY_ALIAS = "phx_def_alias";//密钥别名 
  //每次分段的长度设置 
  const MAX_UPDATE_SESSION_LENGTH = 1024; 
  //使用GCM模式需要配置tag里的的三个必要参数 
  private static AAD_LENGTH = 16; 
  private static AEAD_LENGTH = 16; 
  private static NONCE_LENGTH = 12; 
/** 
   * 分段加密 
   * 
   * @param content 明文内容 
   * @param keyAlias 秘钥别名,不传则使用默认别名 
   * @returns 密文 + aead + nonce + aad 
   */ 
  public static updateEncrypt(content: string, keyAlias?: string): Promise<string> { 
    return new Promise(async (resolve, reject) => { 
      if (!keyAlias) { 
        keyAlias = PhxAesGcmHuks.DEF_KEY_ALIAS; 
      } 
      const genProperties = PhxAesGcmHuks.GetAesGenerateProperties(); 
      const genOptions = { 
        properties: genProperties 
      } 
      await huks.generateKeyItem(keyAlias, genOptions).then(() => { 
        console.log("generateKeyItem success") 
      }).catch((err) => { 
        console.log("generateKeyItem,code:" + err.code + ", msg:" + err.message) 
        reject(err) 
      }) 
      let handle; 
      // 长度16 
      const aeadArray = stringToUint8Array(encryptNapi.OhGenRandomNapi(PhxAesGcmHuks.AEAD_LENGTH / 2)); 
      // 长度12 
      const nonceArray = stringToUint8Array(encryptNapi.OhGenRandomNapi(PhxAesGcmHuks.NONCE_LENGTH / 2)); 
      // 长度16 
      const aadArray = stringToUint8Array(encryptNapi.OhGenRandomNapi(PhxAesGcmHuks.AAD_LENGTH / 2)); 
      const startTime = Date.now(); 
      const encryptProperties = PhxAesGcmHuks.getAesGcmProperties(true, nonceArray, aeadArray,  
aadArray); 
      const options: huks.HuksOptions = { 
        properties: encryptProperties, 
        inData: new Uint8Array(0) 
      } 
      await huks.initSession(keyAlias, options).then((data) => { 
        handle = data.handle; 
      }).catch(async (err) => { 
        console.log("encrypt init, code:" + err.code + ", msg:" + err.message); 
        reject(err); 
      }) 
      //分段加解密 
      let resultTemp = new Uint8Array(0); 
      let contentTemp = content; 
      while (contentTemp.length > 0) { 
    // 超过长度会取最长 
        const contentCurr = contentTemp.substring(0, MAX_UPDATE_SESSION_LENGTH);  
    // 起始点大于长度会返回"" 
       contentTemp = contentTemp.substring(MAX_UPDATE_SESSION_LENGTH, contentTemp.length);  
        options.inData = stringToUint8Array(contentCurr); 
        await huks.updateSession(handle, options).then((data) => { 
          const mergeText = new Uint8Array(resultTemp.length + data.outData.length); 
          mergeText.set(resultTemp); 
          mergeText.set(data.outData, resultTemp.length); 
          resultTemp = mergeText; 
        }).catch(async (err) => { 
          console.log("encrypt updateSession, code:" + err.code + ", msg:" + err.message); 
          reject(err); 
        }) 
      } 
      //分段加解密时,传入finishSession的inData要设置为空的 
      options.inData = new Uint8Array(0); 
      await huks.finishSession(handle, options).then((data) => { 
        const endTime = Date.now(); 
        console.log("encrypt success, useTime:" + (endTime - startTime)); 
        const result = new Uint8Array(resultTemp.length + data.outData.length +  
nonceArray.length + aadArray.length); 
        result.set(resultTemp); 
        result.set(data.outData, resultTemp.length); 
        result.set(nonceArray, resultTemp.length + data.outData.length); 
        result.set(aadArray, resultTemp.length + data.outData.length + nonceArray.length); 
        resolve(new util.Base64Helper().encodeToStringSync(result)); 
      }).catch((err) => { 
        console.log("encrypt fail, code:" + err.code + ", msg:" + err.message); 
        reject(err); 
      }) 
    }); 
  } 
/** 
   * 
   * 分段解密 
   * 
   * @param content 密文内容 
   * @param keyAlias 秘钥别名,不传则使用默认别名 
   * @returns 明文 
   */ 
  public static updateDecrypt(content: string, keyAlias?: string): Promise<string> { 
    return new Promise(async (resolve, reject) => { 
      const enData = new util.Base64Helper().decodeSync(content); 
      const cipherData = enData.subarray(0, enData.length - PhxAesGcmHuks.AAD_LENGTH - 
 PhxAesGcmHuks.AEAD_LENGTH - PhxAesGcmHuks.NONCE_LENGTH) 
      let handle; 
      // 长度16 
      const aeadArray = enData.subarray(cipherData.length, enData.length -  
PhxAesGcmHuks.NONCE_LENGTH - PhxAesGcmHuks.AAD_LENGTH); 
      // 长度12 
      const nonceArray = enData.subarray(cipherData.length + PhxAesGcmHuks.AEAD_LENGTH, 
 enData.length - PhxAesGcmHuks.AAD_LENGTH); 
      // 长度16 
      const aadArray = enData.subarray(cipherData.length + PhxAesGcmHuks.AEAD_LENGTH +  
PhxAesGcmHuks.NONCE_LENGTH, enData.length); 
      if (!keyAlias) { 
        keyAlias = PhxAesGcmHuks.DEF_KEY_ALIAS; 
      } 
      const decryptOptions = PhxAesGcmHuks.getAesGcmProperties(false, nonceArray, aeadArray, aadArray) 
      const options = { 
        properties: decryptOptions, 
        inData: cipherData 
      } 
      await huks.initSession(keyAlias, options).then((data) => { 
        handle = data.handle; 
      }).catch((err) => { 
        console.log("decrypt init, code:" + err.code + ", msg:" + err.message) 
        reject(err) 
      }) 
      let resultTemp = new Uint8Array(0); 
      let contentTemp = cipherData; 
      while (contentTemp.length > 0) { 
        const contentCurr = contentTemp.slice(0, MAX_UPDATE_SESSION_LENGTH); // 超过长度会取最长 
        contentTemp = contentTemp.slice(MAX_UPDATE_SESSION_LENGTH, contentTemp.length);  
        options.inData = contentCurr; 
        await huks.updateSession(handle, options).then((data) => { 
          const mergeText = new Uint8Array(resultTemp.length + data.outData.length); 
          mergeText.set(resultTemp); 
          mergeText.set(data.outData, resultTemp.length); 
          resultTemp = mergeText; 
        }).catch(async (err) => { 
          console.log("encrypt updateSession, code:" + err.code + ", msg:" + err.message); 
          reject(err); 
        }) 
      } 
      options.inData = new Uint8Array(0); 
      await huks.finishSession(handle, options).then(() => { 
        const endTime = Date.now() 
        console.log(uint8ArrayToString(resultTemp)) 
        resolve(uint8ArrayToString(resultTemp)); 
      }).catch((err) => { 
        console.log("decrypt fail, code:" + err.code + ", msg:" + err.message) 
        reject(err) 
      }) 
    }); 
  } 
/** 
   * 加密 
   * 
   * @param content 明文内容 
   * @param keyAlias 秘钥别名,不传则使用默认别名 
   * @returns 密文 + aead + nonce + aad 
   */ 
  public static encrypt(content: string, keyAlias?: string): Promise<string> { 
    return new Promise(async (resolve, reject) => { 
      if (!keyAlias) { 
        keyAlias = PhxAesGcmHuks.DEF_KEY_ALIAS; 
      } 
      const genProperties = PhxAesGcmHuks.GetAesGenerateProperties(); 
      const genOptions = { 
        properties: genProperties 
      } 
      await huks.generateKeyItem(keyAlias, genOptions).then(() => { 
        console.log("generateKeyItem success") 
      }).catch((err) => { 
        console.log("generateKeyItem,code:" + err.code + ", msg:" + err.message) 
        reject(err) 
      }) 
      let handle; 
      // 长度16 
      const aeadArray = stringToUint8Array(encryptNapi.OhGenRandomNapi(PhxAesGcmHuks.AEAD_LENGTH / 2)); 
      // 长度12 
      const nonceArray = stringToUint8Array(encryptNapi.OhGenRandomNapi(PhxAesGcmHuks.NONCE_LENGTH / 2)); 
      // 长度16 
      const aadArray = stringToUint8Array(encryptNapi.OhGenRandomNapi(PhxAesGcmHuks.AAD_LENGTH / 2)); 
      const startTime = Date.now(); 
      const encryptProperties = PhxAesGcmHuks.getAesGcmProperties(true,  
nonceArray, aeadArray, aadArray); 
      const options: huks.HuksOptions = { 
        properties: encryptProperties, 
        inData: stringToUint8Array(content) 
      } 
      await huks.initSession(keyAlias, options).then((data) => { 
        handle = data.handle; 
      }).catch(async (err) => { 
        console.log("encrypt init, code:" + err.code + ", msg:" + err.message); 
        reject(err); 
      }) 
      await huks.finishSession(handle, options).then((data) => { 
        const endTime = Date.now(); 
        console.log("encrypt success, useTime:" + (endTime - startTime)); 
        const result = new Uint8Array(data.outData.length + nonceArray.length + aadArray.length); 
        result.set(data.outData); 
        result.set(nonceArray, data.outData.length) 
        result.set(aadArray, data.outData.length + nonceArray.length) 
        resolve(new util.Base64Helper().encodeToStringSync(result)) 
      }).catch((err) => { 
        console.log("encrypt fail, code:" + err.code + ", msg:" + err.message); 
        reject(err); 
      }) 
    }); 
  } 
  /** 
   * 
   * 解密 
   * 
   * @param content 密文内容 
   * @param keyAlias 秘钥别名,不传则使用默认别名 
   * @returns 明文 
   */ 
  public static decrypt(content: string, keyAlias?: string): Promise<string> { 
    return new Promise(async (resolve, reject) => { 
      const enData = new util.Base64Helper().decodeSync(content); 
      const cipherData = enData.subarray(0,  
enData.length - PhxAesGcmHuks.AAD_LENGTH - PhxAesGcmHuks.AEAD_LENGTH - PhxAesGcmHuks.NONCE_LENGTH) 
      let handle; 
      // 长度16 
      const aeadArray = enData.subarray(cipherData.length,  
enData.length - PhxAesGcmHuks.NONCE_LENGTH - PhxAesGcmHuks.AAD_LENGTH); 
      // 长度12 
      const nonceArray = enData.subarray(cipherData.length + PhxAesGcmHuks.AEAD_LENGTH,  
enData.length - PhxAesGcmHuks.AAD_LENGTH); 
      // 长度16 
      const aadArray = enData.subarray(cipherData.length + PhxAesGcmHuks.AEAD_LENGTH +  
PhxAesGcmHuks.NONCE_LENGTH, enData.length); 
      if (!keyAlias) { 
        keyAlias = PhxAesGcmHuks.DEF_KEY_ALIAS; 
      } 
      const decryptOptions = PhxAesGcmHuks.getAesGcmProperties(false, nonceArray, aeadArray, aadArray) 
      const options = { 
        properties: decryptOptions, 
        inData: cipherData 
      } 
      await huks.initSession(keyAlias, options).then((data) => { 
        handle = data.handle; 
      }).catch((err) => { 
        console.log("decrypt init, code:" + err.code + ", msg:" + err.message) 
        reject(err) 
      }) 
      await huks.finishSession(handle, options).then((data) => { 
        console.log(uint8ArrayToString(data.outData)) 
        resolve(uint8ArrayToString(data.outData)); 
      }).catch((err) => { 
        console.log("decrypt fail, code:" + err.code + ", msg:" + err.message) 
        reject(err) 
      }) 
    }); 
  } 
  /** 
   * huks gcm 加解密参数 
   */ 
  private static getAesGcmProperties(isencryptProperties: boolean, nonceStr: Uint8Array,  
aeadStr: Uint8Array, aadStr: Uint8Array) { 
    const properties = []; 
    let index = 0; 
    properties[index++] = { 
      tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 
      value: huks.HuksKeyAlg.HUKS_ALG_AES 
    }; 
    properties[index++] = { 
      tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 
      value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128 
    }; 
    properties[index++] = { 
      tag: huks.HuksTag.HUKS_TAG_PURPOSE, 
      value: isencryptProperties ? huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT :  
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 
    } 
    properties[index++] = { 
      tag: huks.HuksTag.HUKS_TAG_PADDING, 
      value: huks.HuksKeyPadding.HUKS_PADDING_NONE 
    } 
    properties[index++] = { 
      tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 
      // GCM 模式 
      value: huks.HuksCipherMode.HUKS_MODE_GCM 
    } 
    properties[index++] = { 
      tag: huks.HuksTag.HUKS_TAG_NONCE, 
      value: nonceStr 
    } 
    properties[index++] = { 
      tag: huks.HuksTag.HUKS_TAG_AE_TAG, 
      value: aeadStr 
    } 
    properties[index++] = { 
      tag: huks.HuksTag.HUKS_TAG_ASSOCIATED_DATA, 
      value: aadStr 
    } 
    return properties; 
  } 
  /** 
   * huks 生成秘钥参数 
   */ 
  public static GetAesGenerateProperties() { 
    const properties = []; 
    let index = 0; 
    properties[index++] = { 
      tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 
      value: huks.HuksKeyAlg.HUKS_ALG_AES 
    }; 
    properties[index++] = { 
      tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 
      value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 
    }; 
    properties[index++] = { 
      tag: huks.HuksTag.HUKS_TAG_PURPOSE, 
      value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | 
      huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 
    } 
    return properties; 
  }

适配的版本信息

  • IDE:DevEco Studio 4.1.3.220
  • SDK:HarmoneyOS 4.1.2.1
分享
微博
QQ
微信
回复
2024-05-29 22:29:28
相关问题
加解密问题定位指导
334浏览 • 1回复 待解决
HarmonyOS 请提供RAS加解密文档
343浏览 • 1回复 待解决
HarmonyOS 加解密 demo
432浏览 • 1回复 待解决
基于加解密算法框架规格问题
675浏览 • 1回复 待解决
如何进行不同规格AES加解密
772浏览 • 1回复 待解决
多种加密方式实现加解密
985浏览 • 1回复 待解决
加解密算法库框架使用
841浏览 • 1回复 待解决
如何使用SM4CBC模式加解密
837浏览 • 1回复 待解决
RSA导入外部密钥实现加解密
748浏览 • 1回复 待解决
HarmonyOS 有RSA加解密相关吗
384浏览 • 0回复 待解决
HarmonyOS 如何进行DES加解密
459浏览 • 1回复 待解决
SM4 CBC模式加解密,有好方案吗?
970浏览 • 1回复 待解决