鸿蒙系统开发【加解密算法库框架】安全

加解密算法库框架

介绍

本示例使用@ohos.security.cryptoFramework相关接口实现了对文本文件的加解密、签名验签操作。

实现场景如下:

1)软件需要加密存储本地文本文件,需要调用加解密算法库框架选择密钥文本文件,对本地文本文件进行加密,其中密钥文本文件可由加解密算法库生成。

2)软件需要解密存储本地文本文件,需要调用加解密算法库框架选择密钥文本文件,对本地文本文件进行解密,其中密钥文本文件可由加解密算法库生成。

3)软件需要对存储本地文本文件签名,调用加解密算法库框架选择密钥文本文件,对本地文本文件进行完整性签名,其中密钥文本文件可由加解密算法库生成。

4)软件需要验证存储本地文本文件的签名完整性,需要调用加解密算法库框架选择密钥文本文件与签名文件,对文件进行验签,其中密钥文本文件可由加解密算法库生成。

效果预览

1

使用说明

1.点击主页面tab栏的加密,在加密界面点击打开文件,通过文件选择器选择文本文件,选择完毕自动返回加密界面, 其内容显示在文件内容文本框中, 点击选择密钥,选择密钥文件,如果没有密钥文件,可以通过在加密界面点击随机生成AES密钥,生成并通过文件选择器保存密钥文件。 选择完文本文件和密钥文件后,点击加密按钮,完成加密,并通过文件选择器保存密文文件。 下方加密内容文本框中显示加密后的消息内容。

2.点击主页面tab栏的解密,在解密界面点击打开文件,通过文件选择器选择文本文件,选择完毕自动返回解密界面, 其内容显示在文件内容文本框中, 点击选择密钥,选择和加密相同的密钥文件。 选择完文本文件和密钥文件后,点击解密按钮,完成解密,并通过文件选择器保存明文文件。 下方解密内容文本框中显示解密后的消息内容。

3.点击主页面tab栏的签名,在签名界面点击打开文件,通过文件选择器选择文本文件,选择完毕自动返回签名界面, 其内容显示在文件内容文本框中, 点击选择密钥,选择密钥文件,如果没有密钥文件,可以通过在签名界面点击随机生成RSA密钥,生成并通过文件选择器保存密钥文件,注意RSA密钥生成耗时较长。 选择完文本文件和密钥文件后,点击签名按钮,完成完整性签名,并通过文件选择器保存签名文件。

4.点击主页面tab栏的验签,在验签界面点击打开文件,通过文件选择器选择文本文件,选择完毕自动返回验签界面, 其内容显示在文件内容文本框中, 点击选择密钥,选择和签名一致的密钥文件。点击选择签名文件,通过文件选择器选择签名时保存的签名文件, 选择完文本文件、密钥文件和签名文件后,点击验签按钮,完成验签。

具体实现

  • 进行对文本文件进行加解密、签名验签的功能接口封装在CryptoOperation中,源码参考:[CryptoOperation.ts]
/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { cryptoFramework } from '@kit.CryptoArchitectureKit';
import Logger from '../util/Logger';

const TAG: string = '[Crypto_Framework]';
const BASE_16: number = 16;
const SLICE_NUMBER: number = -2;

// 字节流以16进制字符串输出
function uint8ArrayToShowStr(uint8Array: Uint8Array): string {
  let ret: string = Array.prototype.map
    .call(uint8Array, (x) => ('00' + x.toString(BASE_16)).slice(SLICE_NUMBER)).join('');
  return ret;
}

// 16进制字符串转字节流
function fromHexString(hexString: string): Uint8Array {
  let ret: Uint8Array = new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, BASE_16)));
  return ret;
}


// 字节流转字符串
function arrayBufferToString(buffer: ArrayBuffer): string {
  let ret: string = String.fromCharCode.apply(null, new Uint8Array(buffer));
  return ret;
}

// 可理解的字符串转成字节流
function stringToUint8Array(str: string): Uint8Array {
  let arr = [];
  for (let i = 0, j = str.length; i < j; ++i) {
    arr.push(str.charCodeAt(i));
  }
  let ret: Uint8Array = new Uint8Array(arr);
  return ret;
}

function genGcmParamsSpec(): cryptoFramework.GcmParamsSpec {
  let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes
  let dataIv = new Uint8Array(arr);
  let ivBlob = { data: dataIv };

  arr = [0, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes
  let dataAad = new Uint8Array(arr);
  let aadBlob = { 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 = { data: dataTag }; // GCM的authTag在加密时从doFinal结果中获取,在解密时填入init函数的params参数中

  let gcmParamsSpec = { iv: ivBlob, aad: aadBlob, authTag: tagBlob, algName: 'GcmParamsSpec' };
  return gcmParamsSpec;
}

export class CryptoOperation {
  async generateAesKey(): Promise<string> {
    let symKeyGenerator;
    let encodedKey;
    // 创建对称密钥生成器
    try {
      symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256');
    } catch (error) {
      Logger.error(TAG, 'create generator failed');
      return null;
    }

    // 通过密钥生成器随机生成对称密钥
    try {
      let symKey = await symKeyGenerator.generateSymKey();
      // 获取对称密钥的二进制数据,输出长度为256bit的字节流
      encodedKey = symKey.getEncoded();
      let data: Uint8Array = encodedKey.data;
      Logger.info('success, key bytes: ' + data);
      Logger.info('success, key hex:' + uint8ArrayToShowStr(data));
      // 将二进制数据转为16进制string。
      return uint8ArrayToShowStr(data);
    } catch (error) {
      Logger.error(TAG, 'create symKey failed');
      return null;
    }
  }

  async convertAesKey(aesKeyBlobString: string): Promise<cryptoFramework.SymKey> {
    let symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256');
    Logger.info(TAG, 'success, read key string' + aesKeyBlobString);
    Logger.info(TAG, 'success, blob key ' + fromHexString(aesKeyBlobString));
    let symKeyBlob = { data: fromHexString(aesKeyBlobString) };
    try {
      let key = await symKeyGenerator.convertKey(symKeyBlob);
      let aesKey: cryptoFramework.SymKey = key;
      return aesKey;
    } catch (error) {
      Logger.error(TAG, `convert aes key failed, ${error.code}, ${error.message}`);
      return null;
    }
  }

  async aesGcmEncrypt(globalKey, textString: string): Promise<string> {
    let cipherAlgName = 'AES256|GCM|PKCS7';
    let cipher;
    let cipherText: string;
    let globalGcmParams = genGcmParamsSpec();
    let aesEncryptJsonStr = null;
    try {
      cipher = cryptoFramework.createCipher(cipherAlgName);
      Logger.info(TAG, `cipher algName: ${cipher.algName}`);
    } catch (error) {
      Logger.error(TAG, `createCipher failed, ${error.code}, ${error.message}`);
      return aesEncryptJsonStr;
    }
    let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
    try {
      await cipher.init(mode, globalKey, globalGcmParams);
    } catch (error) {
      Logger.error(TAG, `init cipher failed, ${error.code}, ${error.message}`);
      return aesEncryptJsonStr;
    }
    let plainText = { data: stringToUint8Array(textString) };
    Logger.info(TAG, `plain text: ${plainText.data}`);
    try {
      let cipherTextBlob = await cipher.update(plainText);
      let tmpArr: Uint8Array = cipherTextBlob.data;
      cipherText = uint8ArrayToShowStr(tmpArr);
      Logger.info(TAG, `cipher text: ${cipherText}`);
    } catch (error) {
      Logger.error(TAG, `update cipher failed, ${error.code}, ${error.message}`);
      return aesEncryptJsonStr;
    }
    try {
      let authTag = await cipher.doFinal(null);
      let tmoTagArr: Uint8Array = authTag.data;
      let aesEncryptJson = ({ aesGcmTag: uint8ArrayToShowStr(tmoTagArr), encryptedText: cipherText });
      aesEncryptJsonStr = JSON.stringify(aesEncryptJson);
      Logger.info(TAG, `success, authTag blob ${authTag.data}`);
      Logger.info(TAG, `success, authTag blob.length = ${authTag.data.length}`);
      return aesEncryptJsonStr;
    } catch (error) {
      Logger.error(TAG, `doFinal cipher failed, ${error.code}, ${error.message}`);
      return aesEncryptJsonStr;
    }
  }

  async aesGcmDecrypt(globalKey, aesEncryptJsonStr: string): Promise<string> {
    let cipherAlgName = 'AES256|GCM|PKCS7';
    let decode;
    let plainTextBlob;
    let plainText: string;
    let aesEncryptJson;
    try {
      aesEncryptJson = JSON.parse(aesEncryptJsonStr);
    } catch (error) {
      Logger.error(TAG, `trans from json string failed, ${error.code}, ${error.message}`);
      return null;
    }
    let authTagStr: string = aesEncryptJson.aesGcmTag;
    let textString: string = aesEncryptJson.encryptedText;
    let globalGcmParams = genGcmParamsSpec();
    globalGcmParams.authTag = { data: fromHexString(authTagStr) };
    Logger.info(TAG, 'success, decrypt authTag string' + authTagStr);
    Logger.info(TAG, 'success, decrypt authTag blob' + globalGcmParams.authTag.data);
    Logger.info(TAG, 'success, decrypt authTag blob.length = ' + globalGcmParams.authTag.data.length);
    try {
      decode = cryptoFramework.createCipher(cipherAlgName);
    } catch (error) {
      Logger.error(TAG, `createCipher failed, ${error.code}, ${error.message}`);
      return null;
    }
    let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
    try {
      await decode.init(mode, globalKey, globalGcmParams);
    } catch (error) {
      Logger.error(TAG, `init decode failed, ${error.code}, ${error.message}`);
      return null;
    }
    let cipherText = { data: fromHexString(textString) };
    Logger.info(TAG, `success, cipher text: ${cipherText.data}`);
    try {
      plainTextBlob = await decode.update(cipherText);
      let tmpArr: Uint8Array = plainTextBlob.data;
      plainText = arrayBufferToString(tmpArr);
      Logger.info(TAG, `success, plain text: ${plainText}`);
    } catch (error) {
      Logger.error(TAG, `update decode failed, ${error.code}, ${error.message}`);
      return null;
    }
    try {
      let finalOut = await decode.doFinal(null);
    } catch (error) {
      Logger.error(TAG, `doFinal decode failed, ${error.code}, ${error.message}`);
      return null;
    }
    return plainText;
  }

  async aesConvertAndEncrypt(aesKeyBlobString: string, textString: string): Promise<string> {
    let aesEncryptJsonStr = '';
    try {
      let key = await this.convertAesKey(aesKeyBlobString);
      try {
        aesEncryptJsonStr = await this.aesGcmEncrypt(key, textString);
      } catch (error) {
        Logger.error(TAG, `encrypt error, ${error.code}, ${error.message}`);
      }
    } catch (error) {
      Logger.error(TAG, `convert key error, ${error.code}, ${error.message}`);
      return null;
    }
    return aesEncryptJsonStr;
  }

  async aesConvertAndDecrypt(aesKeyBlobString: string, textString: string): Promise<string> {
    let plainText = '';
    try {
      let key = await this.convertAesKey(aesKeyBlobString);
      try {
        plainText = await this.aesGcmDecrypt(key, textString);
      } catch (error) {
        Logger.error(TAG, `encrypt error, ${error.code}, ${error.message}`);
      }
    } catch (error) {
      Logger.error(TAG, `convert key error, ${error.code}, ${error.message}`);
      return null;
    }
    return plainText;
  }

  async generateRsaKey(): Promise<string> {
    // 创建非对称密钥生成器
    let rsaKeyGenerator;
    let jsonStr;
    // 创建对称密钥生成器
    try {
      rsaKeyGenerator = cryptoFramework.createAsyKeyGenerator('RSA3072');
    } catch (error) {
      Logger.error(TAG, 'create generator failed');
      return null;
    }
    // 通过密钥生成器随机生成非对称密钥
    try {
      // 通过密钥生成器随机生成非对称密钥
      let keyPair = await rsaKeyGenerator.generateKeyPair();
      // 获取非对称密钥的二进制数据
      let encodedPriKey = keyPair.priKey.getEncoded();
      let priKeyData: Uint8Array = encodedPriKey.data;
      let encodedPubKey = keyPair.pubKey.getEncoded();
      let pubKeyData: Uint8Array = encodedPubKey.data;
      let rsaKeyJson = ({ priKey: uint8ArrayToShowStr(priKeyData), pubKey: uint8ArrayToShowStr(pubKeyData) });
      jsonStr = JSON.stringify(rsaKeyJson);
      Logger.info(TAG, 'success, key string: ' + jsonStr.length);
      return jsonStr;
    } catch (error) {
      Logger.error(TAG, 'create symKey failed');
      return null;
    }
  }

  async convertRsaKey(rsaJsonString: string): Promise<cryptoFramework.KeyPair> {
    let rsaKeyGenerator = cryptoFramework.createAsyKeyGenerator('RSA3072');
    Logger.info(TAG, 'success, read key string' + rsaJsonString.length);
    let jsonRsaKeyBlob;
    try {
      jsonRsaKeyBlob = JSON.parse(rsaJsonString);
    } catch (error) {
      Logger.error(TAG, `trans from json string failed, ${error.code}, ${error.message}`);
      return null;
    }
    let priKeyStr: string = jsonRsaKeyBlob.priKey;
    let pubKeyStr: string = jsonRsaKeyBlob.pubKey;
    Logger.info(TAG, 'success, read rsa pri str ' + priKeyStr.length);
    Logger.info(TAG, 'success, read rsa pub str ' + pubKeyStr.length);
    let priKeyBlob = fromHexString(priKeyStr);
    let pubKeyBlob = fromHexString(pubKeyStr);
    Logger.info(TAG, 'success, read rsa pri blob key ' + priKeyBlob.length);
    Logger.info(TAG, 'success, read rsa pub blob key ' + pubKeyBlob.length);
    try {
      let key: cryptoFramework.KeyPair = await rsaKeyGenerator.convertKey({ data: pubKeyBlob }, { data: priKeyBlob });
      return key;
      Logger.info(TAG, 'success, read and convert key');
    } catch (error) {
      Logger.error(TAG, `convert rsa key failed, ${error.code}, ${err
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值