加解密算法库框架
介绍
本示例使用@ohos.security.cryptoFramework相关接口实现了对文本文件的加解密、签名验签操作。
实现场景如下:
1)软件需要加密存储本地文本文件,需要调用加解密算法库框架选择密钥文本文件,对本地文本文件进行加密,其中密钥文本文件可由加解密算法库生成。
2)软件需要解密存储本地文本文件,需要调用加解密算法库框架选择密钥文本文件,对本地文本文件进行解密,其中密钥文本文件可由加解密算法库生成。
3)软件需要对存储本地文本文件签名,调用加解密算法库框架选择密钥文本文件,对本地文本文件进行完整性签名,其中密钥文本文件可由加解密算法库生成。
4)软件需要验证存储本地文本文件的签名完整性,需要调用加解密算法库框架选择密钥文本文件与签名文件,对文件进行验签,其中密钥文本文件可由加解密算法库生成。
效果预览
使用说明
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')
});
}
}
}
以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下:
内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!
鸿蒙【北向应用开发+南向系统层开发】文档
鸿蒙【基础+实战项目】视频
鸿蒙面经
为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!