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

news2024/11/23 19:12:25

加解密算法库框架

介绍

本示例使用@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}, ${error.message}`);
      return null;
    }
  }

  async rsaSign(globalKey, textString: string): Promise<string> {
    let signer = cryptoFramework.createSign('RSA3072|PKCS1|SHA256');
    let keyPair = globalKey;
    try {
      await signer.init(keyPair.priKey);
      let signBlob = stringToUint8Array(textString);
      try {
        let signedBlob = await signer.sign({ data: signBlob });
        let tmpArr: Uint8Array = signedBlob.data;
        Logger.info(TAG, 'success,RSA sign output is' + signedBlob.data.length);
        let rsaSignedBlobString = uint8ArrayToShowStr(tmpArr);
        Logger.info(TAG, 'success,RSA sign string is' + rsaSignedBlobString);
        return rsaSignedBlobString;
      } catch (error1) {
        Logger.error(TAG, `sign text failed, ${error1.code}, ${error1.message}`);
        return null;
      }
    } catch (error) {
      Logger.error(TAG, `sign init failed, ${error.code}, ${error.message}`);
      return null;
    }
  }

  async rsaVerify(globalKey, textString: string, rsaSignedText: string): Promise<Boolean> {
    let verifyer = cryptoFramework.createVerify('RSA3072|PKCS1|SHA256');
    let keyPair = globalKey;
    let signBlob = stringToUint8Array(textString);
    let signedBlob = fromHexString(rsaSignedText);
    Logger.info('success,RSA sign input is ' + signBlob);
    Logger.info('success,RSA signed file length ' + signedBlob.length);
    try {
      await verifyer.init(keyPair.pubKey);
      try {
        let result: Boolean = await verifyer.verify({ data: signBlob }, { data: signedBlob });
        if (result === false) {
          // flag = false;
          Logger.error(TAG, 'RSA Verify result = fail');
        } else {
          Logger.info(TAG, 'success, RSA Verify result = success');
        }
        return result;
      } catch (error) {
        Logger.error(TAG, `verify dofinal failed, ${error.code}, ${error.message}`);
      }
    } catch (err) {
      Logger.error(TAG, `verify init failed, ${err.code}, ${err.message}`);
    }
    return null;
  }

  async rsaConvertAndSign(rsaJsonString: string, textString: string): Promise<string> {
    let rsaSignString;
    try {
      let key = await this.convertRsaKey(rsaJsonString);
      try {
        rsaSignString = await this.rsaSign(key, textString);
      } catch (error) {
        Logger.error(TAG, `sign error, ${error.code}, ${error.message}`);
        return null;
      }
    } catch (error) {
      Logger.error(TAG, `convert rsa key error, ${error.code}, ${error.message}`);
      return null;
    }
    return rsaSignString;
  }

  async rsaConvertAndVerify(rsaJsonString: string, textString: string, rsaSignedText: string): Promise<Boolean> {
    let rsaVerifyRes;
    try {
      let key = await this.convertRsaKey(rsaJsonString);
      try {
        rsaVerifyRes = await this.rsaVerify(key, textString, rsaSignedText);
      } catch (error) {
        Logger.error(TAG, `sign error, ${error.code}, ${error.message}`);
        return null;
      }
    } catch (error) {
      Logger.error(TAG, `convert rsa key error, ${error.code}, ${error.message}`);
      return null;
    }
    return rsaVerifyRes;
  }
}


  • 对文本文件加密:在[Encrypt.ets](文件中依次点击打开文件、选择密钥,通过filePicker选择明文文本文件和密钥文件,点击加密按钮,调用加密函数实现对文本内容进行加密,并将密文文件通过filePicker保存。 需要生成密钥文本文件时,可以点击随机生成AES密钥,通过调用cryptoFramework.symKeyGenerator生成用于加密的AES密钥,并通过filePicker保存密钥文本文件。 对消息加密的过程中采用cryptoFramework.Cipher完成加密操作。
/*
 * 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 { promptAction } from '@kit.ArkUI';
import Logger from '../util/Logger';
import { picker } from '@kit.CoreFileKit';
import { CryptoOperation } from '../cryptoframework/CryptoOperation';
import TextFileManager from '../textfilemanager/TextFileManager';

const TAG: string = '[Crypto_Framework]';

@Component
export struct Encrypt {
  @State keyFileName: string = '';
  @State keyFileUri: string = '';
  @State textFileUri: string = '';
  @State textFileName: string = '';
  @State keyString: string = '';
  @State cipherText: string = '';
  @State plainText: string = '';
  @State message: string = '';
  @State createKeyUri: string = '';
  @State encryptedFileUri: string = '';
  private CryptoOperation: CryptoOperation = new CryptoOperation();

  build() {
    Stack({ alignContent: Alignment.Center }) {
      Column() {
        GridRow() {
          GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
            Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
              List() {
                ListItem() {
                  Row() {
                    Text($r('app.string.open_file'))
                      .fontSize(16)
                      .textAlign(TextAlign.Start)
                      .lineHeight(22)

                    Blank()

                    Text(this.textFileName === '' ? $r('app.string.please_choose') : this.textFileName)
                      .fontSize(14)
                      .textAlign(TextAlign.Start)
                      .lineHeight(19)

                    Image($r('app.media.right_arrow'))
                      .height('19vp')
                      .width('10vp')
                      .margin({ left: 9, right: 9, top: 6, bottom: 6 })
                  }
                  .backgroundColor(0xFFFFFF)
                  .width('100%')
                  .height('52vp')
                  .padding({ top: 4, left: 12, right: 12 })
                }.onClick(() => {
                  this.selectTextFileAndRead();
                })

                ListItem() {
                  Row() {
                    Text($r('app.string.select_key_file'))
                      .fontSize(16)
                      .textAlign(TextAlign.Start)
                      .lineHeight(22)

                    Blank()

                    Text(this.keyFileName === '' ? $r('app.string.please_choose') : this.keyFileName)
                      .fontSize(14)
                      .textAlign(TextAlign.Start)
                      .lineHeight(19)

                    Image($r('app.media.right_arrow'))
                      .height('19vp')
                      .width('10vp')
                      .margin({ left: 9, right: 9, top: 6, bottom: 6 })
                  }
                  .backgroundColor(0xFFFFFF)
                  .width('100%')
                  .height('48vp')
                  .padding({ left: 12, right: 12 })
                }.onClick(() => {
                  this.selectAesKeyFileAndRead();
                })
              }
              .width('100%')
              .height('100%')
              .borderRadius(16)
            }
          }
        }
        .height('100vp')
        .margin({ left: 12, right: 12, bottom: 12 })

        GridRow() {
          GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
            Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
              Column() {
                Row() {
                  Text($r('app.string.text_context'))
                    .fontSize(16)
                    .textAlign(TextAlign.Start)
                    .fontWeight(500)
                    .lineHeight(22)
                }
                .padding({ left: 12, right: 12 })
                .width('100%')
                .height('48vp')

                Row() {
                  Text() {
                    Span(this.plainText)
                      .fontSize(16)
                      .fontWeight(400)
                      .fontColor('#182431')
                  }.textAlign(TextAlign.Start)
                }
                .padding({ left: 12, right: 12, bottom: 4 })
                .width('100%')
                .height('52vp')
              }
              .borderRadius(16)
              .width('100%')
              .height('100')
              .backgroundColor(0xFFFFFF)
            }
          }
        }
        .height('100vp')
        .margin({ left: 12, right: 12, bottom: 12 })

        GridRow() {
          GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
            Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
              Column() {
                Row() {
                  Text($r('app.string.encrypted_context'))
                    .fontSize(16)
                    .textAlign(TextAlign.Start)
                    .fontWeight(500)
                    .lineHeight(22)
                }
                .padding({ left: 12, right: 12 })
                .width('100%')
                .height('48vp')

                Row() {
                  Text() {
                    Span(this.cipherText)
                      .fontSize(16)
                      .fontWeight(400)
                      .fontColor('#182431')
                  }.textAlign(TextAlign.Start)
                }
                .padding({ left: 12, right: 12, bottom: 4 })
                .width('100%')
                .height('80vp')
              }
              .borderRadius(16)
              .width('100%')
              .height('100')
              .backgroundColor(0xFFFFFF)
            }
          }
        }
        .height('100vp')
        .margin({ left: 12, right: 12, bottom: 12 })

        Column() {
          GridRow() {
            GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
              Column() {
                Button() {
                  Text($r('app.string.generate_aes_key_randomly')).fontSize(16).fontWeight(500)
                    .lineHeight(22)
                    .fontColor('#FFFFFF')
                }
                .id('encryptAesGenKey')
                .borderRadius(20)
                .type(ButtonType.Capsule)
                .width('100%')
                .height('40vp')
                .margin({ bottom: 16 })
                .backgroundColor('#007DFF')
                .onClick(() => {
                  this.genAesKey();
                });

                Button() {
                  Text($r('app.string.encrypt')).fontSize(16).fontWeight(500)
                    .lineHeight(22)
                    .fontColor('#FFFFFF')
                }
                .borderRadius(20)
                .id('encryptionBtn')
                .type(ButtonType.Capsule)
                .margin({ left: 24, right: 24 })
                .width('100%')
                .height('40vp')
                .backgroundColor('#007DFF')
                .onClick(() => {
                  if (this.textFileUri === '' || this.keyFileUri === '') {
                    promptAction.showToast({
                      message: $r('app.string.null_message')
                    });
                  } else {
                    this.encryptFunc();
                  }
                });
              }
            }
          }.margin({ left: 24, right: 24 })
        }.width('100%').height('296vp').justifyContent(FlexAlign.End)
      }
      .width('100%')
      .height('100%')
    }
  }

  async selectAesKeyFileAndRead() {
    let documentSelectOptions = new picker.DocumentSelectOptions();
    documentSelectOptions.fileSuffixFilters = ['.txt'];
    documentSelectOptions.maxSelectNumber = 1;
    let uri: string = '';
    let documentViewPicker = new picker.DocumentViewPicker();
    await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
      uri = documentSelectResult[0];
      console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
    }).catch((err: Error) => {
      console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
    })
    this.keyFileUri = uri;
    await TextFileManager.readTextFile(this.keyFileUri);
    this.keyFileName = TextFileManager.getName();
    this.keyString = TextFileManager.getString();
  }

  async selectTextFileAndRead() {
    let documentSelectOptions = new picker.DocumentSelectOptions();
    documentSelectOptions.fileSuffixFilters = ['.txt'];
    documentSelectOptions.maxSelectNumber = 1;
    let uri: string = '';
    let documentViewPicker = new picker.DocumentViewPicker();
    await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
      uri = documentSelectResult[0];
      console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
    }).catch((err: Error) => {
      console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
    })
    this.textFileUri = uri;
    await TextFileManager.readTextFile(this.textFileUri);
    this.textFileName = TextFileManager.getName();
    this.plainText = TextFileManager.getString();
  }

  async createTextFileAndWrite() {
    let documentSaveOptions = new picker.DocumentSaveOptions();
    documentSaveOptions.newFileNames = ['cipherText.txt'];
    let documentPicker = new picker.DocumentViewPicker();
    let documentSaveResult = await documentPicker.save(documentSaveOptions);
    this.encryptedFileUri = documentSaveResult[0];
    await TextFileManager.writeTextFile(this.encryptedFileUri, this.cipherText);
  }

  async createKeyFileAndWrite() {
    let documentSaveOptions = new picker.DocumentSaveOptions();
    documentSaveOptions.newFileNames = ['aesKey.txt'];
    let documentPicker = new picker.DocumentViewPicker();
    let documentSaveResult = await documentPicker.save(documentSaveOptions);
    this.createKeyUri = documentSaveResult[0];
    await TextFileManager.writeTextFile(this.createKeyUri, this.keyString);
  }

  async encryptFunc() {
    if (this.plainText === '' || this.keyFileUri === '') {
      promptAction.showToast({
        message: $r('app.string.null_message')
      });
      return;
    }
    try {
      this.cipherText = await this.CryptoOperation.aesConvertAndEncrypt(this.keyString, this.plainText);
    } catch (error) {
      Logger.error(TAG, `encrypt failed, ${error}`);
      promptAction.showToast({
        message: $r('app.string.encrypt_fail')
      });
    }
    if (this.cipherText === '' || this.cipherText === undefined || this.cipherText === null) {
      promptAction.showToast({
        message: $r('app.string.encrypt_fail')
      });
      return;
    } else {
      try {
        await this.createTextFileAndWrite();
      } catch (error) {
        Logger.error(TAG, `encrypt failed, ${error}`);
      }
    }
    if (this.encryptedFileUri === '' || typeof (this.encryptedFileUri) == 'undefined') {
      promptAction.showToast({
        message: $r('app.string.encrypt_fail')
      });
    } else {
      promptAction.showToast({
        message: $r('app.string.encrypt_success')
      });
    }
  }

  async genAesKey() {
    try {
      this.keyString = await this.CryptoOperation.generateAesKey();
    } catch (error) {
      Logger.error(TAG, `gen aes key failed, ${error}`);
    }
    if (this.keyString === '' || typeof (this.keyString) == 'undefined') {
      promptAction.showToast({
        message: $r('app.string.gen_key_fail')
      });
      return;
    } else {
      try {
        await this.createKeyFileAndWrite();
      } catch (error) {
        Logger.error(TAG, `write aes key failed, ${error}`);
      }
    }
    if (this.createKeyUri === '' || typeof (this.createKeyUri) == 'undefined') {
      promptAction.showToast({
        message: $r('app.string.gen_key_fail')
      });
    } else {
      promptAction.showToast({
        message: $r('app.string.gen_key_success')
      });
    }
  }
}

  • 对文本文件解密:在[Decrypt.ets] 文件中依次点击打开文件、选择密钥,通过filePicker选择密文文本文件和密钥文件,点击解密按钮,调用解密函数实现对文本内容进行解密,并将明文文件通过filePicker保存。 对消息解密的过程中采用cryptoFramework.Cipher完成解密操作。
/*
 * 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 { promptAction } from '@kit.ArkUI';
import Logger from '../util/Logger';
import { picker } from '@kit.CoreFileKit';
import { CryptoOperation } from '../cryptoframework/CryptoOperation';
import TextFileManager from '../textfilemanager/TextFileManager';

const TAG: string = '[Crypto_Framework]';

@Component
export struct Decrypt {
  @State keyFileName: string = '';
  @State keyFileUri: string = '';
  @State textFileUri: string = '';
  @State textFileName: string = '';
  @State keyString: string = '';
  @State cipherText: string = '';
  @State plainText: string = '';
  @State message: string = '';
  @State decryptedFileUri: string = '';
  private CryptoOperation: CryptoOperation = new CryptoOperation();

  build() {
    Stack({ alignContent: Alignment.Center }) {
      Column() {
        GridRow() {
          GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
            Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
              List() {
                ListItem() {
                  Row() {
                    Text($r('app.string.open_file'))
                      .fontSize(16)
                      .textAlign(TextAlign.Start)
                      .lineHeight(22)

                    Blank()

                    Text(this.textFileName === '' ? $r('app.string.please_choose') : this.textFileName)
                      .fontSize(14)
                      .textAlign(TextAlign.Start)
                      .lineHeight(19)

                    Image($r('app.media.right_arrow'))
                      .height('19vp')
                      .width('10vp')
                      .margin({ left: 9, right: 9, top: 6, bottom: 6 })
                  }
                  .backgroundColor(0xFFFFFF)
                  .width('100%')
                  .height('52vp')
                  .padding({ top: 4, left: 12, right: 12 })
                }.onClick(() => {
                  this.selectTextFileAndRead();
                })

                ListItem() {
                  Row() {
                    Text($r('app.string.select_key_file'))
                      .fontSize(16)
                      .textAlign(TextAlign.Start)
                      .lineHeight(22)

                    Blank()

                    Text(this.keyFileName === '' ? $r('app.string.please_choose') : this.keyFileName)
                      .fontSize(14)
                      .textAlign(TextAlign.Start)
                      .lineHeight(19)

                    Image($r('app.media.right_arrow'))
                      .height('19vp')
                      .width('10vp')
                      .margin({ left: 9, right: 9, top: 6, bottom: 6 })
                  }
                  .backgroundColor(0xFFFFFF)
                  .width('100%')
                  .height('48vp')
                  .padding({ left: 12, right: 12 })
                }.onClick(() => {
                  this.selectAesKeyFileAndRead();
                })
              }
              .width('100%')
              .height('100%')
              .borderRadius(16)
            }
          }
        }
        .height('100vp')
        .margin({ left: 12, right: 12, bottom: 12 })

        GridRow() {
          GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
            Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
              Column() {
                Row() {
                  Text($r('app.string.text_context'))
                    .fontSize(16)
                    .textAlign(TextAlign.Start)
                    .fontWeight(500)
                    .lineHeight(22)
                }
                .padding({ left: 12, right: 12 })
                .width('100%')
                .height('48vp')

                Row() {
                  Text() {
                    Span(this.cipherText)
                      .fontSize(16)
                      .fontWeight(400)
                      .fontColor('#182431')
                  }.textAlign(TextAlign.Start)
                }
                .padding({ left: 12, right: 12, bottom: 4 })
                .width('100%')
                .height('52vp')
              }
              .borderRadius(16)
              .width('100%')
              .height('100')
              .backgroundColor(0xFFFFFF)
            }
          }
        }
        .height('100vp')
        .margin({ left: 12, right: 12, bottom: 12 })

        GridRow() {
          GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
            Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
              Column() {
                Row() {
                  Text($r('app.string.decrypted_context'))
                    .fontSize(16)
                    .textAlign(TextAlign.Start)
                    .fontWeight(500)
                    .lineHeight(22)
                }
                .padding({ left: 12, right: 12 })
                .width('100%')
                .height('48vp')

                Row() {
                  Text() {
                    Span(this.plainText)
                      .fontSize(16)
                      .fontWeight(400)
                      .fontColor('#182431')
                  }.textAlign(TextAlign.Start)
                }
                .padding({ left: 12, right: 12, bottom: 4 })
                .width('100%')
                .height('52vp')
              }
              .borderRadius(16)
              .width('100%')
              .height('100')
              .backgroundColor(0xFFFFFF)
            }
          }
        }
        .height('100vp')
        .margin({ left: 12, right: 12, bottom: 12 })

        Column() {
          GridRow() {
            GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
              Column() {
                Button() {
                  Text($r('app.string.decrypt')).fontSize(16).fontWeight(500)
                    .lineHeight(22)
                    .fontColor('#FFFFFF')
                }
                .borderRadius(20)
                .id('decryptionBtn')
                .type(ButtonType.Capsule)
                .margin({ left: 24, right: 24 })
                .width('100%')
                .height('40vp')
                .backgroundColor('#007DFF')
                .onClick(() => {
                  if (this.textFileUri === '' || this.keyFileUri === '') {
                    promptAction.showToast({
                      message: $r('app.string.null_message')
                    });
                  } else {
                    this.decryptFunc();
                  }
                });
              }
            }
          }.margin({ left: 24, right: 24 })
        }.width('100%').height('296vp').justifyContent(FlexAlign.End)
      }
      .width('100%')
      .height('100%')
    }
  }

  async selectAesKeyFileAndRead() {
    let documentSelectOptions = new picker.DocumentSelectOptions();
    documentSelectOptions.fileSuffixFilters = ['.txt'];
    documentSelectOptions.maxSelectNumber = 1;
    let uri: string = '';
    let documentViewPicker = new picker.DocumentViewPicker();
    await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
      uri = documentSelectResult[0];
      console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
    }).catch((err: Error) => {
      console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
    })
    this.keyFileUri = uri;
    await TextFileManager.readTextFile(this.keyFileUri);
    this.keyFileName = TextFileManager.getName();
    this.keyString = TextFileManager.getString();
  }

  async selectTextFileAndRead() {
    let documentSelectOptions = new picker.DocumentSelectOptions();
    documentSelectOptions.fileSuffixFilters = ['.txt'];
    documentSelectOptions.maxSelectNumber = 1;
    let uri: string = '';
    let documentViewPicker = new picker.DocumentViewPicker();
    await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
      uri = documentSelectResult[0];
      console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
    }).catch((err: Error) => {
      console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
    })
    this.textFileUri = uri;
    await TextFileManager.readTextFile(this.textFileUri);
    this.textFileName = TextFileManager.getName();
    this.cipherText = TextFileManager.getString();
  }

  async createTextFileAndWrite() {
    let documentSaveOptions = new picker.DocumentSaveOptions();
    documentSaveOptions.newFileNames = ['plainText.txt'];
    let documentPicker = new picker.DocumentViewPicker();
    let documentSaveResult = await documentPicker.save(documentSaveOptions);
    this.decryptedFileUri = documentSaveResult[0];
    await TextFileManager.writeTextFile(this.decryptedFileUri, this.plainText);
  }

  async decryptFunc() {
    if (this.cipherText === '' || this.keyFileUri === '') {
      promptAction.showToast({
        message: $r('app.string.null_message')
      });
      return;
    }
    try {
      this.plainText = await this.CryptoOperation.aesConvertAndDecrypt(this.keyString, this.cipherText);
    } catch (error) {
      Logger.error(TAG, `decrypt failed, ${error}`);
      promptAction.showToast({
        message: $r('app.string.decrypt_fail')
      });
      return;
    }
    if (this.plainText === '' || this.plainText === null || this.plainText === undefined) {
      promptAction.showToast({
        message: $r('app.string.decrypt_fail')
      });
      return;
    } else {
      try {
        await this.createTextFileAndWrite();
      } catch (error) {
        Logger.error(TAG, `decrypt failed, ${error}`);
      }
    }
    if (this.decryptedFileUri === '' || typeof (this.decryptedFileUri) == 'undefined') {
      promptAction.showToast({
        message: $r('app.string.decrypt_fail')
      });
    } else {
      promptAction.showToast({
        message: $r('app.string.decrypt_success')
      });
    }
  }
}

  • 对文本文件签名:在[Sign.ets] 文件中依次点击打开文件、选择密钥,通过filePicker选择待签名文本文件和密钥文件,点击签名按钮,调用签名函数实现对文本内容进行加密,并将签名文件通过filePicker保存。 需要生成密钥文本文件时,可以点击随机生成RSA密钥,通过调用cryptoFramework.asyKeyGenerator生成用于签名的RSA密钥,并通过filePicker保存密钥文本文件。 对消息签名的过程中采用cryptoFramework.Sign完成加密操作。
/*
 * 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 { promptAction } from '@kit.ArkUI';
import Logger from '../util/Logger';
import { picker } from '@kit.CoreFileKit';
import { CryptoOperation } from '../cryptoframework/CryptoOperation';
import TextFileManager from '../textfilemanager/TextFileManager';

const TAG: string = '[Crypto_Framework]';

@Component
export struct Sign {
  @State keyFileName: string = '';
  @State keyFileUri: string = '';
  @State textFileUri: string = '';
  @State textFileName: string = '';
  @State keyString: string = '';
  @State cipherText: string = '';
  @State plainText: string = '';
  @State message: string = '';
  @State signFileUri: string = '';
  @State createKeyUri: string = '';
  private CryptoOperation: CryptoOperation = new CryptoOperation();

  build() {
    Stack({ alignContent: Alignment.Center }) {
      Column() {
        GridRow() {
          GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
            Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
              List() {
                ListItem() {
                  Row() {
                    Text($r('app.string.open_file'))
                      .fontSize(16)
                      .textAlign(TextAlign.Start)
                      .lineHeight(22)

                    Blank()

                    Text(this.textFileName === '' ? $r('app.string.please_choose') : this.textFileName)
                      .fontSize(14)
                      .textAlign(TextAlign.Start)
                      .lineHeight(19)

                    Image($r('app.media.right_arrow'))
                      .height('19vp')
                      .width('10vp')
                      .margin({ left: 9, right: 9, top: 6, bottom: 6 })
                  }
                  .backgroundColor(0xFFFFFF)
                  .width('100%')
                  .height('52vp')
                  .padding({ top: 4, left: 12, right: 12 })
                }.onClick(() => {
                  this.selectTextFileAndRead();
                })

                ListItem() {
                  Row() {
                    Text($r('app.string.select_key_file'))
                      .fontSize(16)
                      .textAlign(TextAlign.Start)
                      .lineHeight(22)

                    Blank()

                    Text(this.keyFileName === '' ? $r('app.string.please_choose') : this.keyFileName)
                      .fontSize(14)
                      .textAlign(TextAlign.Start)
                      .lineHeight(19)

                    Image($r('app.media.right_arrow'))
                      .height('19vp')
                      .width('10vp')
                      .margin({ left: 9, right: 9, top: 6, bottom: 6 })
                  }
                  .backgroundColor(0xFFFFFF)
                  .width('100%')
                  .height('48vp')
                  .padding({ left: 12, right: 12 })
                }.onClick(() => {
                  this.selectRsaKeyFileAndRead();
                })
              }
              .width('100%')
              .height('100%')
              .borderRadius(16)
            }
          }
        }
        .height('100vp')
        .margin({ left: 12, right: 12, bottom: 12 })

        GridRow() {
          GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
            Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
              Column() {
                Row() {
                  Text($r('app.string.text_context'))
                    .fontSize(16)
                    .textAlign(TextAlign.Start)
                    .fontWeight(500)
                    .lineHeight(22)
                }
                .padding({ left: 12, right: 12 })
                .width('100%')
                .height('48vp')

                Row() {
                  Text() {
                    Span(this.plainText)
                      .fontSize(16)
                      .fontWeight(400)
                      .fontColor('#182431')
                  }.textAlign(TextAlign.Start)
                }
                .padding({ left: 12, right: 12, bottom: 4 })
                .width('100%')
                .height('52vp')
              }
              .borderRadius(16)
              .width('100%')
              .height('100')
              .backgroundColor(0xFFFFFF)
            }
          }
        }
        .height('100vp')
        .margin({ left: 12, right: 12, bottom: 12 })

        Column() {
          GridRow() {
            GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
              Column() {
                Button() {
                  Text($r('app.string.generate_rsa_key_randomly')).fontSize(16).fontWeight(500)
                    .lineHeight(22)
                    .fontColor('#FFFFFF')
                }
                .id('encryptRsaGenKey')
                .borderRadius(20)
                .type(ButtonType.Capsule)
                .width('100%')
                .height('40vp')
                .margin({ bottom: 16 })
                .backgroundColor('#007DFF')
                .onClick(() => {
                  this.genRsaKey();
                });

                Button() {
                  Text($r('app.string.sign')).fontSize(16).fontWeight(500)
                    .lineHeight(22)
                    .fontColor('#FFFFFF')
                }
                .borderRadius(20)
                .id('signBtn')
                .type(ButtonType.Capsule)
                .margin({ left: 24, right: 24 })
                .width('100%')
                .height('40vp')
                .backgroundColor('#007DFF')
                .onClick(() => {
                  if (this.textFileUri === '' || this.keyFileUri === '') {
                    promptAction.showToast({
                      message: $r('app.string.null_message')
                    });
                  } else {
                    this.signFunc();
                  }
                });
              }
            }
          }.margin({ left: 24, right: 24 })
        }.width('100%').height('412vp').justifyContent(FlexAlign.End)
      }
      .width('100%')
      .height('100%')
    }
  }

  async selectRsaKeyFileAndRead() {
    let documentSelectOptions = new picker.DocumentSelectOptions();
    documentSelectOptions.fileSuffixFilters = ['.txt'];
    documentSelectOptions.maxSelectNumber = 1;
    let uri: string = '';
    let documentViewPicker = new picker.DocumentViewPicker();
    await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
      uri = documentSelectResult[0];
      console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
    }).catch((err: Error) => {
      console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
    })
    this.keyFileUri = uri;
    // 获取到密钥文档文件的文件名称
    await TextFileManager.readTextFile(this.keyFileUri);
    this.keyFileName = TextFileManager.getName();
    this.keyString = TextFileManager.getString();
  }

  async selectTextFileAndRead() {
    let documentSelectOptions = new picker.DocumentSelectOptions();
    documentSelectOptions.fileSuffixFilters = ['.txt'];
    documentSelectOptions.maxSelectNumber = 1;
    let uri: string = '';
    let documentViewPicker = new picker.DocumentViewPicker();
    await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
      uri = documentSelectResult[0];
      console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
    }).catch((err: Error) => {
      console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
    })
    // 获取到文档文件的URI
    this.textFileUri = uri;
    // 获取到文档文件的文件名称
    await TextFileManager.readTextFile(this.textFileUri);
    this.textFileName = TextFileManager.getName();
    this.plainText = TextFileManager.getString();
  }

  async createTextFileAndWrite() {
    let documentSaveOptions = new picker.DocumentSaveOptions();
    documentSaveOptions.newFileNames = ['signText.txt'];
    let documentPicker = new picker.DocumentViewPicker();
    let documentSaveResult = await documentPicker.save(documentSaveOptions);
    this.signFileUri = documentSaveResult[0];
    await TextFileManager.writeTextFile(this.signFileUri, this.cipherText);
  }

  async createKeyFileAndWrite() {
    let documentSaveOptions = new picker.DocumentSaveOptions();
    documentSaveOptions.newFileNames = ['rsaKey.txt'];
    let documentPicker = new picker.DocumentViewPicker();
    try {
      let documentSaveResult = await documentPicker.save(documentSaveOptions);
      this.createKeyUri = documentSaveResult[0];
      await TextFileManager.writeTextFile(this.createKeyUri, this.keyString);
    } catch (error) {
      Logger.error(TAG, `save key failed, ${error}`);
    }

  }

  async signFunc() {
    if (this.plainText === '' || this.keyFileUri === '') {
      promptAction.showToast({
        message: $r('app.string.null_message')
      });
      return;
    }
    try {
      this.cipherText = await this.CryptoOperation.rsaConvertAndSign(this.keyString, this.plainText);
    } catch (error) {
      promptAction.showToast({
        message: $r('app.string.sign_fail')
      });
      Logger.error(TAG, `sign failed, ${error}`);
    }
    if (this.cipherText === '' || this.cipherText === null || this.cipherText === undefined) {
      promptAction.showToast({
        message: $r('app.string.sign_fail')
      });
      return;
    } else {
      await this.createTextFileAndWrite();
    }
    if (this.signFileUri === '' || typeof (this.signFileUri) == 'undefined') {
      promptAction.showToast({
        message: $r('app.string.sign_fail')
      });
    } else {
      promptAction.showToast({
        message: $r('app.string.sign_success')
      });
    }
  }

  async genRsaKey() {
    promptAction.showToast({
      message: $r('app.string.slow_rsa_key_gen')
    });
    try {
      this.keyString = await this.CryptoOperation.generateRsaKey();
    } catch (error) {
      Logger.error(TAG, `gen rsa key failed, ${error}`);
    }
    if (this.keyString === '' || typeof (this.keyString) == 'undefined') {
      promptAction.showToast({
        message: $r('app.string.gen_key_fail')
      });
      return;
    } else {
      try {
        await this.createKeyFileAndWrite();
      } catch (error) {
        Logger.error(TAG, `write rsa key failed, ${error}`);
      }
    }
    if (this.createKeyUri === '' || typeof (this.createKeyUri) == 'undefined') {
      promptAction.showToast({
        message: $r('app.string.gen_key_fail')
      });
    } else {
      promptAction.showToast({
        message: $r('app.string.gen_key_success')
      });
    }

  }
}

  • 对文本文件验签:在[Verify.ets]文件中依次点击打开文件、选择密钥、选择签名文件,通过filePicker选择密文文本文件、密钥文件和签名文件,点击验签按钮,调用验签函数实现对文本内容进行验签,并显示验签结果。 对消息验签的过程中采用cryptoFramework.Verify完成验签操作。
/*
 * 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 { promptAction } from '@kit.ArkUI';
import Logger from '../util/Logger';
import { picker } from '@kit.CoreFileKit';
import { CryptoOperation } from '../cryptoframework/CryptoOperation';
import TextFileManager from '../textfilemanager/TextFileManager';

const TAG: string = '[Crypto_Framework]';

@Component
export struct Verify {
  @State keyFileName: string = '';
  @State keyFileUri: string = '';
  @State textFileUri: string = '';
  @State textFileName: string = '';
  @State keyString: string = '';
  @State plainText: string = '';
  @State message: string = '';
  @State signFileUri: string = '';
  @State signFileName: string = '';
  @State signText: string = '';
  @State createKeyUri: string = '';
  private CryptoOperation: CryptoOperation = new CryptoOperation();

  build() {
    Stack({ alignContent: Alignment.Center }) {
      Column() {
        GridRow() {
          GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
            Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
              List() {
                ListItem() {
                  Row() {
                    Text($r('app.string.open_file'))
                      .fontSize(16)
                      .textAlign(TextAlign.Start)
                      .lineHeight(22)

                    Blank()

                    Text(this.textFileName === '' ? $r('app.string.please_choose') : this.textFileName)
                      .fontSize(14)
                      .textAlign(TextAlign.Start)
                      .lineHeight(19)

                    Image($r('app.media.right_arrow'))
                      .height('19vp')
                      .width('10vp')
                      .margin({ left: 9, right: 9, top: 6, bottom: 6 })
                  }
                  .backgroundColor(0xFFFFFF)
                  .width('100%')
                  .height('52vp')
                  .padding({ top: 4, left: 12, right: 12 })
                }.onClick(() => {
                  this.selectTextFileAndRead();
                })

                ListItem() {
                  Row() {
                    Text($r('app.string.select_key_file'))
                      .fontSize(16)
                      .textAlign(TextAlign.Start)
                      .lineHeight(22)

                    Blank()

                    Text(this.keyFileName === '' ? $r('app.string.please_choose') : this.keyFileName)
                      .fontSize(14)
                      .textAlign(TextAlign.Start)
                      .lineHeight(19)

                    Image($r('app.media.right_arrow'))
                      .height('19vp')
                      .width('10vp')
                      .margin({ left: 9, right: 9, top: 6, bottom: 6 })
                  }
                  .backgroundColor(0xFFFFFF)
                  .width('100%')
                  .height('48vp')
                  .padding({ left: 12, right: 12 })
                }.onClick(() => {
                  this.selectRsaKeyFileAndRead();
                })
              }
              .width('100%')
              .height('100%')
              .borderRadius(16)
            }
          }
        }
        .height('100vp')
        .margin({ left: 12, right: 12, bottom: 12 })

        GridRow() {
          GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
            Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
              List() {
                ListItem() {
                  Row() {
                    Text($r('app.string.select_signature_file'))
                      .fontSize(16)
                      .textAlign(TextAlign.Start)
                      .lineHeight(22)

                    Blank()

                    Text(this.signFileName === '' ? $r('app.string.please_choose') : this.signFileName)
                      .fontSize(14)
                      .textAlign(TextAlign.Start)
                      .lineHeight(19)

                    Image($r('app.media.right_arrow'))
                      .height('19vp')
                      .width('10vp')
                      .margin({ left: 9, right: 9, top: 6, bottom: 6 })
                  }
                  .backgroundColor(0xFFFFFF)
                  .width('100%')
                  .height('56vp')
                  .padding({ left: 12, right: 12, top: 4, bottom: 4 })
                }.onClick(() => {
                  this.selectSignFileAndRead();
                })
              }
              .width('100%')
              .borderRadius(16)
            }
          }
        }
        .height('56vp')
        .margin({ left: 12, right: 12, bottom: 12 })

        GridRow() {
          GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
            Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
              Column() {
                Row() {
                  Text($r('app.string.text_context'))
                    .fontSize(16)
                    .textAlign(TextAlign.Start)
                    .fontWeight(500)
                    .lineHeight(22)
                }
                .padding({ left: 12, right: 12 })
                .width('100%')
                .height('48vp')

                Row() {
                  Text() {
                    Span(this.plainText)
                      .fontSize(16)
                      .fontWeight(400)
                      .fontColor('#182431')
                  }.textAlign(TextAlign.Start)
                }
                .padding({ left: 12, right: 12, bottom: 4 })
                .width('100%')
                .height('52vp')
              }
              .borderRadius(16)
              .width('100%')
              .height('100')
              .backgroundColor(0xFFFFFF)
            }
          }
        }
        .height('100vp')
        .margin({ left: 12, right: 12, bottom: 12 })

        Column() {
          GridRow() {
            GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
              Column() {
                Button() {
                  Text($r('app.string.verify')).fontSize(16).fontWeight(500)
                    .lineHeight(22)
                    .fontColor('#FFFFFF')
                }
                .borderRadius(20)
                .id('verifyBtn')
                .type(ButtonType.Capsule)
                .margin({ left: 24, right: 24 })
                .width('100%')
                .height('40vp')
                .backgroundColor('#007DFF')
                .onClick(() => {
                  if (this.textFileUri === '' || this.keyFileUri === '' || this.signFileUri === '') {
                    promptAction.showToast({
                      message: $r('app.string.null_message')
                    });
                  } else {
                    this.verifyFunc();
                  }
                });
              }
            }
          }.margin({ left: 24, right: 24 })
        }.width('100%').height('340vp').justifyContent(FlexAlign.End)
      }
      .width('100%')
      .height('100%')
    }
  }

  async selectRsaKeyFileAndRead() {
    let documentSelectOptions = new picker.DocumentSelectOptions();
    documentSelectOptions.fileSuffixFilters = ['.txt'];
    documentSelectOptions.maxSelectNumber = 1;
    let uri: string = '';
    let documentViewPicker = new picker.DocumentViewPicker();
    await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
      uri = documentSelectResult[0];
      console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
    }).catch((err: Error) => {
      console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
    })
    // 获取到密钥文档文件的URI
    this.keyFileUri = uri;
    // 获取到密钥文档文件的文件名称
    await TextFileManager.readTextFile(this.keyFileUri);
    this.keyFileName = TextFileManager.getName();
    this.keyString = TextFileManager.getString();
  }

  async selectTextFileAndRead() {
    let documentSelectOptions = new picker.DocumentSelectOptions();
    documentSelectOptions.fileSuffixFilters = ['.txt'];
    documentSelectOptions.maxSelectNumber = 1;
    let uri: string = '';
    let documentViewPicker = new picker.DocumentViewPicker();
    await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
      uri = documentSelectResult[0];
      console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
    }).catch((err: Error) => {
      console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
    })
    // 获取到文档文件的URI
    this.textFileUri = uri;
    // 获取到文档文件的文件名称
    await TextFileManager.readTextFile(this.textFileUri);
    this.textFileName = TextFileManager.getName();
    this.plainText = TextFileManager.getString();
  }

  async selectSignFileAndRead() {
    let documentSelectOptions = new picker.DocumentSelectOptions();
    documentSelectOptions.fileSuffixFilters = ['.txt'];
    documentSelectOptions.maxSelectNumber = 1;
    let uri: string = '';
    let documentViewPicker = new picker.DocumentViewPicker();
    await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
      uri = documentSelectResult[0];
      console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
    }).catch((err: Error) => {
      console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
    })
    // 获取到文档文件的URI
    this.signFileUri = uri;
    // 获取到文档文件的文件名称
    await TextFileManager.readTextFile(this.signFileUri);
    this.signFileName = TextFileManager.getName();
    this.signText = TextFileManager.getString();
  }

  async createKeyFileAndWrite() {
    let documentSaveOptions = new picker.DocumentSaveOptions();
    documentSaveOptions.newFileNames = ['rsaKey.txt'];
    let documentPicker = new picker.DocumentViewPicker();
    try {
      let documentSaveResult = await documentPicker.save(documentSaveOptions);
      this.createKeyUri = documentSaveResult[0];
      await TextFileManager.writeTextFile(this.createKeyUri, this.keyString);
    } catch (error) {
      Logger.error(TAG, `save key failed, ${error}`);
    }

  }

  async verifyFunc() {
    let verifyRes: Boolean = false;
    if (this.plainText === '' || this.keyFileUri === '' || this.signText === '') {
      promptAction.showToast({
        message: $r('app.string.null_message')
      });
      return;
    }
    try {
      verifyRes = await this.CryptoOperation.rsaConvertAndVerify(this.keyString, this.plainText, this.signText);
    } catch (error) {
      Logger.error(TAG, `verify failed, ${error}`);
    }
    if (verifyRes != true) {
      promptAction.showToast({
        message: $r('app.string.verify_fail')
      });
      return;
    } else {
      promptAction.showToast({
        message: $r('app.string.verify_success')
      });
    }
  }
}

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
1

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

在这里插入图片描述

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1972948.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PostgreSQL11 | 触发器

本文章代码已在pgsql11.22版本上运行且通过&#xff0c;展示页由pgAdmin8.4版本提供 上一篇总结了原著的第十章有关pgsql的视图的用法&#xff0c;本篇将总结pgsql的触发器的用法。 触发器 使用触发器可以自动化完成一些在插入数据或修改数据时&#xff0c;某些需要同期同步的…

【vulnhub】Depth靶机

靶机安装 下载地址&#xff1a;https://download.vulnhub.com/depth/DepthB2R.ova 运行环境&#xff1a;VMware运行该虚拟机 信息收集 靶机IP发现 nmap 192.168.93.0/24 端口扫描 nmap -A 192.168.93.154 -p- 只开起了8080端口 进行目录扫描8080端口 dirsearch -u http…

学习记录(9):Prompt提示词技巧

依旧照例先感谢前辈们的慷慨分享 今天学习的是这篇文章↓ 原文&#xff1a;转自公主号“博金斯的AI笔记” —《4篇Prompt论文的提示词技巧, 3 个 GPTs 实例测试》 文章目录 一、提示词框架二、逻辑链&#xff08;Chain of thought&#xff09;三、思维树&#xff08;Tree of th…

华为Atlas 500 智能小站+鸿蒙AI大算力边缘计算解决方案

Atlas 500 智能小站鸿蒙大算力解决方案 技术规格 表3-1 技术规格 项目 说明 处理器 海思Hi3559A处理器 双核ARM Cortex A731.6GHz&#xff0c;32KB I-Cache&#xff0c;64KB D-Cache /512KB L2 cache双核ARM Cortex A531.2GHz&#xff0c;32KB I-Cache&#xff0c;32KB D-C…

如何确保PLC系统安全的可靠性,这几个注意事项你需要牢记

PLC&#xff08;可编程逻辑控制器&#xff09;是现代工业自动化系统中的关键组成部分。在设计 PLC 系统时&#xff0c;安全性是至关重要的考虑因素。本文将介绍 PLC 系统设计中的一些安全注意事项&#xff0c;包括电源设计、接地设计、关键数字量输入输出设计和报警设计。 一.…

阿一网络安全学院之绕过CDN发现服务器真实IP

方法一&#xff1a; 探测次级域名 方法二&#xff1a; 访问文件 使用访问错误目录获得报错信息成功 方法三&#xff1a; 去掉 www 查询 方法四&#xff1a; 使用网络测绘搜索引擎查询 和方法二获得的 IP 一样 方法五&#xff1a; 使用外国节点查询&#xff1a; 用了无数…

关于使用php的mpdf插件遇到的一些问题

一.插件版本 "mpdf/mpdf": "^8.0", 二.报错&#xff1a;Undefined index: list_style_type 这个是插件无法识别 li 标签导致&#xff0c;生成pdf是加入下面代码 <style> li { list-style-type: none; list-style-image: none; list-style-positi…

HTML-03.新浪新闻-标题-样式2

1.<span>标签 <span>是一个在开发网页时大量使用的没有语义的布局标签 特点&#xff1a;一行可以显示多个&#xff08;行内组合元素&#xff09;&#xff0c;宽度和高度默认由内容撑开 2.CSS选择器 2.1 元素选择器&#xff1a;标签名{...} 元素名称{ color:red; }…

如何在 Debian 上安装运行极狐GitLab Runner?【一】

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门面向中国程序员和企业提供企业级一体化 DevOps 平台&#xff0c;用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规&#xff0c;而且所有的操作都是在一个平台上进行&#xff0c;省事省心省钱。可以一键安装极狐GitL…

04-Fastjson反序列化漏洞

免责声明 本文仅限于学习讨论与技术知识的分享&#xff0c;不得违反当地国家的法律法规。对于传播、利用文章中提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;本文作者不为此承担任何责任&#xff0c;一旦造成后果请自行承担&…

ShardingSphere实战(5)- 读写分离

上篇博客&#xff0c;我们讲了 ShardingSphere实战&#xff08;4&#xff09;- 广播表和默认数据源 &#xff0c;这篇博客&#xff0c;我们实现一下读写分离。 一、读写分离配置 # sharding-jdbc 读写分离策略 # 给数据源起别名&#xff0c;这里名称需要和下面的一致 spring.…

【C++标准模版库】vector的介绍及使用

vector 一.vector的介绍二.vector的使用1.vector 构造函数2.vector 空间增长3.vector 增删查改4.vector 迭代器的使用1.正向迭代器2.反向迭代器 5.victor 迭代器失效问题&#xff08;重点&#xff09; 三.vector不支持 流提取与流插入四.vector存储自定义类型1.存储string2.存储…

OS_操作系统的运行环境

2024.06.11:操作系统的运行环境学习笔记 第3节 操作系统的运行环境 3.1 操作系统引导3.2 操作系统内核3.2.1 内核资源管理3.2.2 内核基本功能 3.3 CPU的双重工作模式3.3.1 CPU处于用户态&#xff08;目态&#xff09;3.3.2 CPU处于内核态&#xff08;管态&#xff09; 3.4 特权…

【mars3d】创建一个全黑的地球,太空背景色随意

关键参数&#xff1a; 1.backgroundColor 2.baseColor 3.basemaps 在basemaps没有底图的时候&#xff0c;可以直接设置地球的背景色baseColor 与此同时需要注意&#xff0c;不要showSkyBox等天空盒效果&#xff0c;不然容易看不见球在哪里&#xff0c;不好操作 链接&…

一种用于用于图像超分辨率的高效退化模型

一种用于用于图像超分辨率的高效退化模型 摘要引言退化模型设计图像降质模型简化版3.1. 模糊3.2. 下采样3.3. 噪声3.4. 随机排序 实验结果结论参考文献 摘要 为了增加数原始图像的退化丰富度&#xff0c;提高超分辨率网络的泛化能力&#xff0c;本文介绍了一种更加复杂但实用的…

秒懂C++之vector(下)

目录 前言 一.vector容器的模拟实现 1.1 基本配置 1.2 reserve 扩容 1.3 push_back 尾插 1.4 insert 插入 1.5 【】运算符 1.6 拷贝构造 1.7 运算符 1.8 resize 扩容初始化 1.9 erase 删除 1.10 迭代器构造 二.例题练习 17. 电话号码的字母组合 题目解析&#x…

pytorch学习笔记3 tensor索引和切片

dim 0 占先 切片 &#xff08;前N或者后N个&#xff09; &#xff1a;2 表示 0到2&#xff08;不包含2&#xff09;&#xff0c; 1&#xff1a;表示 1到末尾&#xff0c; -1表示最后一个元素&#xff0c;-2表示倒数第二个 0:28:2 表示从0到27隔点采样 &#xff1a;&#xff…

【反序列化漏洞】serial靶机详解

一、安装靶机 首先创建新的虚拟机。 然后选择客户机版本为Ubuntu 64位。 然后选择使用现有磁盘&#xff0c;选择下载的vmdk磁盘文件即可。剩下的都是默认 二、信息收集 发现主机192.168.204.143 访问 扫描端口nmap -A 192.168.204.143 -p-&#xff0c;发现只有ssh:22和http:8…

科普文:微服务之分布式链路追踪SkyWalking单点服务搭建

1. 概述 1.1 概念 SkyWalking 是什么&#xff1f; SkyWalking 极简入门 | Apache SkyWalking FROM Apache SkyWalking 分布式系统的应用程序性能监视工具&#xff0c;专为微服务、云原生架构和基于容器&#xff08;Docker、K8s、Mesos&#xff09;架构而设计。 提供分布式追…

【Bugku】Web系列第二更~

1.你必须让他停下 查看源代码&#xff0c;一直刷新&#xff0c;直到看见flag 2.矛盾 构造一个?num1[字母&#xff0c;随便写到最后都会被PHP转化成0] 这里利用的是PHP对数字和字符串比较的时候的一个特性&#xff0c;他会试图把字符串转化为数字&#xff0c;所以1XXX转化到最后…