0


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

加解密算法库框架

介绍

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

实现场景如下:

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

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

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

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

效果预览

1

使用说明

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

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

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

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

具体实现

  • 进行对文本文件进行加解密、签名验签的功能接口封装在CryptoOperation中,源码参考:[CryptoOperation.ts]
  1. /*
  2. * Copyright (c) 2023 Huawei Device Co., Ltd.
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. import { cryptoFramework } from '@kit.CryptoArchitectureKit';
  16. import Logger from '../util/Logger';
  17. const TAG: string = '[Crypto_Framework]';
  18. const BASE_16: number = 16;
  19. const SLICE_NUMBER: number = -2;
  20. // 字节流以16进制字符串输出
  21. function uint8ArrayToShowStr(uint8Array: Uint8Array): string {
  22. let ret: string = Array.prototype.map
  23. .call(uint8Array, (x) => ('00' + x.toString(BASE_16)).slice(SLICE_NUMBER)).join('');
  24. return ret;
  25. }
  26. // 16进制字符串转字节流
  27. function fromHexString(hexString: string): Uint8Array {
  28. let ret: Uint8Array = new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, BASE_16)));
  29. return ret;
  30. }
  31. // 字节流转字符串
  32. function arrayBufferToString(buffer: ArrayBuffer): string {
  33. let ret: string = String.fromCharCode.apply(null, new Uint8Array(buffer));
  34. return ret;
  35. }
  36. // 可理解的字符串转成字节流
  37. function stringToUint8Array(str: string): Uint8Array {
  38. let arr = [];
  39. for (let i = 0, j = str.length; i < j; ++i) {
  40. arr.push(str.charCodeAt(i));
  41. }
  42. let ret: Uint8Array = new Uint8Array(arr);
  43. return ret;
  44. }
  45. function genGcmParamsSpec(): cryptoFramework.GcmParamsSpec {
  46. let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes
  47. let dataIv = new Uint8Array(arr);
  48. let ivBlob = { data: dataIv };
  49. arr = [0, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes
  50. let dataAad = new Uint8Array(arr);
  51. let aadBlob = { data: dataAad };
  52. arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes
  53. let dataTag = new Uint8Array(arr);
  54. let tagBlob = { data: dataTag }; // GCM的authTag在加密时从doFinal结果中获取,在解密时填入init函数的params参数中
  55. let gcmParamsSpec = { iv: ivBlob, aad: aadBlob, authTag: tagBlob, algName: 'GcmParamsSpec' };
  56. return gcmParamsSpec;
  57. }
  58. export class CryptoOperation {
  59. async generateAesKey(): Promise<string> {
  60. let symKeyGenerator;
  61. let encodedKey;
  62. // 创建对称密钥生成器
  63. try {
  64. symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256');
  65. } catch (error) {
  66. Logger.error(TAG, 'create generator failed');
  67. return null;
  68. }
  69. // 通过密钥生成器随机生成对称密钥
  70. try {
  71. let symKey = await symKeyGenerator.generateSymKey();
  72. // 获取对称密钥的二进制数据,输出长度为256bit的字节流
  73. encodedKey = symKey.getEncoded();
  74. let data: Uint8Array = encodedKey.data;
  75. Logger.info('success, key bytes: ' + data);
  76. Logger.info('success, key hex:' + uint8ArrayToShowStr(data));
  77. // 将二进制数据转为16进制string。
  78. return uint8ArrayToShowStr(data);
  79. } catch (error) {
  80. Logger.error(TAG, 'create symKey failed');
  81. return null;
  82. }
  83. }
  84. async convertAesKey(aesKeyBlobString: string): Promise<cryptoFramework.SymKey> {
  85. let symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256');
  86. Logger.info(TAG, 'success, read key string' + aesKeyBlobString);
  87. Logger.info(TAG, 'success, blob key ' + fromHexString(aesKeyBlobString));
  88. let symKeyBlob = { data: fromHexString(aesKeyBlobString) };
  89. try {
  90. let key = await symKeyGenerator.convertKey(symKeyBlob);
  91. let aesKey: cryptoFramework.SymKey = key;
  92. return aesKey;
  93. } catch (error) {
  94. Logger.error(TAG, `convert aes key failed, ${error.code}, ${error.message}`);
  95. return null;
  96. }
  97. }
  98. async aesGcmEncrypt(globalKey, textString: string): Promise<string> {
  99. let cipherAlgName = 'AES256|GCM|PKCS7';
  100. let cipher;
  101. let cipherText: string;
  102. let globalGcmParams = genGcmParamsSpec();
  103. let aesEncryptJsonStr = null;
  104. try {
  105. cipher = cryptoFramework.createCipher(cipherAlgName);
  106. Logger.info(TAG, `cipher algName: ${cipher.algName}`);
  107. } catch (error) {
  108. Logger.error(TAG, `createCipher failed, ${error.code}, ${error.message}`);
  109. return aesEncryptJsonStr;
  110. }
  111. let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
  112. try {
  113. await cipher.init(mode, globalKey, globalGcmParams);
  114. } catch (error) {
  115. Logger.error(TAG, `init cipher failed, ${error.code}, ${error.message}`);
  116. return aesEncryptJsonStr;
  117. }
  118. let plainText = { data: stringToUint8Array(textString) };
  119. Logger.info(TAG, `plain text: ${plainText.data}`);
  120. try {
  121. let cipherTextBlob = await cipher.update(plainText);
  122. let tmpArr: Uint8Array = cipherTextBlob.data;
  123. cipherText = uint8ArrayToShowStr(tmpArr);
  124. Logger.info(TAG, `cipher text: ${cipherText}`);
  125. } catch (error) {
  126. Logger.error(TAG, `update cipher failed, ${error.code}, ${error.message}`);
  127. return aesEncryptJsonStr;
  128. }
  129. try {
  130. let authTag = await cipher.doFinal(null);
  131. let tmoTagArr: Uint8Array = authTag.data;
  132. let aesEncryptJson = ({ aesGcmTag: uint8ArrayToShowStr(tmoTagArr), encryptedText: cipherText });
  133. aesEncryptJsonStr = JSON.stringify(aesEncryptJson);
  134. Logger.info(TAG, `success, authTag blob ${authTag.data}`);
  135. Logger.info(TAG, `success, authTag blob.length = ${authTag.data.length}`);
  136. return aesEncryptJsonStr;
  137. } catch (error) {
  138. Logger.error(TAG, `doFinal cipher failed, ${error.code}, ${error.message}`);
  139. return aesEncryptJsonStr;
  140. }
  141. }
  142. async aesGcmDecrypt(globalKey, aesEncryptJsonStr: string): Promise<string> {
  143. let cipherAlgName = 'AES256|GCM|PKCS7';
  144. let decode;
  145. let plainTextBlob;
  146. let plainText: string;
  147. let aesEncryptJson;
  148. try {
  149. aesEncryptJson = JSON.parse(aesEncryptJsonStr);
  150. } catch (error) {
  151. Logger.error(TAG, `trans from json string failed, ${error.code}, ${error.message}`);
  152. return null;
  153. }
  154. let authTagStr: string = aesEncryptJson.aesGcmTag;
  155. let textString: string = aesEncryptJson.encryptedText;
  156. let globalGcmParams = genGcmParamsSpec();
  157. globalGcmParams.authTag = { data: fromHexString(authTagStr) };
  158. Logger.info(TAG, 'success, decrypt authTag string' + authTagStr);
  159. Logger.info(TAG, 'success, decrypt authTag blob' + globalGcmParams.authTag.data);
  160. Logger.info(TAG, 'success, decrypt authTag blob.length = ' + globalGcmParams.authTag.data.length);
  161. try {
  162. decode = cryptoFramework.createCipher(cipherAlgName);
  163. } catch (error) {
  164. Logger.error(TAG, `createCipher failed, ${error.code}, ${error.message}`);
  165. return null;
  166. }
  167. let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
  168. try {
  169. await decode.init(mode, globalKey, globalGcmParams);
  170. } catch (error) {
  171. Logger.error(TAG, `init decode failed, ${error.code}, ${error.message}`);
  172. return null;
  173. }
  174. let cipherText = { data: fromHexString(textString) };
  175. Logger.info(TAG, `success, cipher text: ${cipherText.data}`);
  176. try {
  177. plainTextBlob = await decode.update(cipherText);
  178. let tmpArr: Uint8Array = plainTextBlob.data;
  179. plainText = arrayBufferToString(tmpArr);
  180. Logger.info(TAG, `success, plain text: ${plainText}`);
  181. } catch (error) {
  182. Logger.error(TAG, `update decode failed, ${error.code}, ${error.message}`);
  183. return null;
  184. }
  185. try {
  186. let finalOut = await decode.doFinal(null);
  187. } catch (error) {
  188. Logger.error(TAG, `doFinal decode failed, ${error.code}, ${error.message}`);
  189. return null;
  190. }
  191. return plainText;
  192. }
  193. async aesConvertAndEncrypt(aesKeyBlobString: string, textString: string): Promise<string> {
  194. let aesEncryptJsonStr = '';
  195. try {
  196. let key = await this.convertAesKey(aesKeyBlobString);
  197. try {
  198. aesEncryptJsonStr = await this.aesGcmEncrypt(key, textString);
  199. } catch (error) {
  200. Logger.error(TAG, `encrypt error, ${error.code}, ${error.message}`);
  201. }
  202. } catch (error) {
  203. Logger.error(TAG, `convert key error, ${error.code}, ${error.message}`);
  204. return null;
  205. }
  206. return aesEncryptJsonStr;
  207. }
  208. async aesConvertAndDecrypt(aesKeyBlobString: string, textString: string): Promise<string> {
  209. let plainText = '';
  210. try {
  211. let key = await this.convertAesKey(aesKeyBlobString);
  212. try {
  213. plainText = await this.aesGcmDecrypt(key, textString);
  214. } catch (error) {
  215. Logger.error(TAG, `encrypt error, ${error.code}, ${error.message}`);
  216. }
  217. } catch (error) {
  218. Logger.error(TAG, `convert key error, ${error.code}, ${error.message}`);
  219. return null;
  220. }
  221. return plainText;
  222. }
  223. async generateRsaKey(): Promise<string> {
  224. // 创建非对称密钥生成器
  225. let rsaKeyGenerator;
  226. let jsonStr;
  227. // 创建对称密钥生成器
  228. try {
  229. rsaKeyGenerator = cryptoFramework.createAsyKeyGenerator('RSA3072');
  230. } catch (error) {
  231. Logger.error(TAG, 'create generator failed');
  232. return null;
  233. }
  234. // 通过密钥生成器随机生成非对称密钥
  235. try {
  236. // 通过密钥生成器随机生成非对称密钥
  237. let keyPair = await rsaKeyGenerator.generateKeyPair();
  238. // 获取非对称密钥的二进制数据
  239. let encodedPriKey = keyPair.priKey.getEncoded();
  240. let priKeyData: Uint8Array = encodedPriKey.data;
  241. let encodedPubKey = keyPair.pubKey.getEncoded();
  242. let pubKeyData: Uint8Array = encodedPubKey.data;
  243. let rsaKeyJson = ({ priKey: uint8ArrayToShowStr(priKeyData), pubKey: uint8ArrayToShowStr(pubKeyData) });
  244. jsonStr = JSON.stringify(rsaKeyJson);
  245. Logger.info(TAG, 'success, key string: ' + jsonStr.length);
  246. return jsonStr;
  247. } catch (error) {
  248. Logger.error(TAG, 'create symKey failed');
  249. return null;
  250. }
  251. }
  252. async convertRsaKey(rsaJsonString: string): Promise<cryptoFramework.KeyPair> {
  253. let rsaKeyGenerator = cryptoFramework.createAsyKeyGenerator('RSA3072');
  254. Logger.info(TAG, 'success, read key string' + rsaJsonString.length);
  255. let jsonRsaKeyBlob;
  256. try {
  257. jsonRsaKeyBlob = JSON.parse(rsaJsonString);
  258. } catch (error) {
  259. Logger.error(TAG, `trans from json string failed, ${error.code}, ${error.message}`);
  260. return null;
  261. }
  262. let priKeyStr: string = jsonRsaKeyBlob.priKey;
  263. let pubKeyStr: string = jsonRsaKeyBlob.pubKey;
  264. Logger.info(TAG, 'success, read rsa pri str ' + priKeyStr.length);
  265. Logger.info(TAG, 'success, read rsa pub str ' + pubKeyStr.length);
  266. let priKeyBlob = fromHexString(priKeyStr);
  267. let pubKeyBlob = fromHexString(pubKeyStr);
  268. Logger.info(TAG, 'success, read rsa pri blob key ' + priKeyBlob.length);
  269. Logger.info(TAG, 'success, read rsa pub blob key ' + pubKeyBlob.length);
  270. try {
  271. let key: cryptoFramework.KeyPair = await rsaKeyGenerator.convertKey({ data: pubKeyBlob }, { data: priKeyBlob });
  272. return key;
  273. Logger.info(TAG, 'success, read and convert key');
  274. } catch (error) {
  275. Logger.error(TAG, `convert rsa key failed, ${error.code}, ${error.message}`);
  276. return null;
  277. }
  278. }
  279. async rsaSign(globalKey, textString: string): Promise<string> {
  280. let signer = cryptoFramework.createSign('RSA3072|PKCS1|SHA256');
  281. let keyPair = globalKey;
  282. try {
  283. await signer.init(keyPair.priKey);
  284. let signBlob = stringToUint8Array(textString);
  285. try {
  286. let signedBlob = await signer.sign({ data: signBlob });
  287. let tmpArr: Uint8Array = signedBlob.data;
  288. Logger.info(TAG, 'success,RSA sign output is' + signedBlob.data.length);
  289. let rsaSignedBlobString = uint8ArrayToShowStr(tmpArr);
  290. Logger.info(TAG, 'success,RSA sign string is' + rsaSignedBlobString);
  291. return rsaSignedBlobString;
  292. } catch (error1) {
  293. Logger.error(TAG, `sign text failed, ${error1.code}, ${error1.message}`);
  294. return null;
  295. }
  296. } catch (error) {
  297. Logger.error(TAG, `sign init failed, ${error.code}, ${error.message}`);
  298. return null;
  299. }
  300. }
  301. async rsaVerify(globalKey, textString: string, rsaSignedText: string): Promise<Boolean> {
  302. let verifyer = cryptoFramework.createVerify('RSA3072|PKCS1|SHA256');
  303. let keyPair = globalKey;
  304. let signBlob = stringToUint8Array(textString);
  305. let signedBlob = fromHexString(rsaSignedText);
  306. Logger.info('success,RSA sign input is ' + signBlob);
  307. Logger.info('success,RSA signed file length ' + signedBlob.length);
  308. try {
  309. await verifyer.init(keyPair.pubKey);
  310. try {
  311. let result: Boolean = await verifyer.verify({ data: signBlob }, { data: signedBlob });
  312. if (result === false) {
  313. // flag = false;
  314. Logger.error(TAG, 'RSA Verify result = fail');
  315. } else {
  316. Logger.info(TAG, 'success, RSA Verify result = success');
  317. }
  318. return result;
  319. } catch (error) {
  320. Logger.error(TAG, `verify dofinal failed, ${error.code}, ${error.message}`);
  321. }
  322. } catch (err) {
  323. Logger.error(TAG, `verify init failed, ${err.code}, ${err.message}`);
  324. }
  325. return null;
  326. }
  327. async rsaConvertAndSign(rsaJsonString: string, textString: string): Promise<string> {
  328. let rsaSignString;
  329. try {
  330. let key = await this.convertRsaKey(rsaJsonString);
  331. try {
  332. rsaSignString = await this.rsaSign(key, textString);
  333. } catch (error) {
  334. Logger.error(TAG, `sign error, ${error.code}, ${error.message}`);
  335. return null;
  336. }
  337. } catch (error) {
  338. Logger.error(TAG, `convert rsa key error, ${error.code}, ${error.message}`);
  339. return null;
  340. }
  341. return rsaSignString;
  342. }
  343. async rsaConvertAndVerify(rsaJsonString: string, textString: string, rsaSignedText: string): Promise<Boolean> {
  344. let rsaVerifyRes;
  345. try {
  346. let key = await this.convertRsaKey(rsaJsonString);
  347. try {
  348. rsaVerifyRes = await this.rsaVerify(key, textString, rsaSignedText);
  349. } catch (error) {
  350. Logger.error(TAG, `sign error, ${error.code}, ${error.message}`);
  351. return null;
  352. }
  353. } catch (error) {
  354. Logger.error(TAG, `convert rsa key error, ${error.code}, ${error.message}`);
  355. return null;
  356. }
  357. return rsaVerifyRes;
  358. }
  359. }
  • 对文本文件加密:在[Encrypt.ets](文件中依次点击打开文件、选择密钥,通过filePicker选择明文文本文件和密钥文件,点击加密按钮,调用加密函数实现对文本内容进行加密,并将密文文件通过filePicker保存。 需要生成密钥文本文件时,可以点击随机生成AES密钥,通过调用cryptoFramework.symKeyGenerator生成用于加密的AES密钥,并通过filePicker保存密钥文本文件。 对消息加密的过程中采用cryptoFramework.Cipher完成加密操作。
  1. /*
  2. * Copyright (c) 2023 Huawei Device Co., Ltd.
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. import { promptAction } from '@kit.ArkUI';
  16. import Logger from '../util/Logger';
  17. import { picker } from '@kit.CoreFileKit';
  18. import { CryptoOperation } from '../cryptoframework/CryptoOperation';
  19. import TextFileManager from '../textfilemanager/TextFileManager';
  20. const TAG: string = '[Crypto_Framework]';
  21. @Component
  22. export struct Encrypt {
  23. @State keyFileName: string = '';
  24. @State keyFileUri: string = '';
  25. @State textFileUri: string = '';
  26. @State textFileName: string = '';
  27. @State keyString: string = '';
  28. @State cipherText: string = '';
  29. @State plainText: string = '';
  30. @State message: string = '';
  31. @State createKeyUri: string = '';
  32. @State encryptedFileUri: string = '';
  33. private CryptoOperation: CryptoOperation = new CryptoOperation();
  34. build() {
  35. Stack({ alignContent: Alignment.Center }) {
  36. Column() {
  37. GridRow() {
  38. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  39. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  40. List() {
  41. ListItem() {
  42. Row() {
  43. Text($r('app.string.open_file'))
  44. .fontSize(16)
  45. .textAlign(TextAlign.Start)
  46. .lineHeight(22)
  47. Blank()
  48. Text(this.textFileName === '' ? $r('app.string.please_choose') : this.textFileName)
  49. .fontSize(14)
  50. .textAlign(TextAlign.Start)
  51. .lineHeight(19)
  52. Image($r('app.media.right_arrow'))
  53. .height('19vp')
  54. .width('10vp')
  55. .margin({ left: 9, right: 9, top: 6, bottom: 6 })
  56. }
  57. .backgroundColor(0xFFFFFF)
  58. .width('100%')
  59. .height('52vp')
  60. .padding({ top: 4, left: 12, right: 12 })
  61. }.onClick(() => {
  62. this.selectTextFileAndRead();
  63. })
  64. ListItem() {
  65. Row() {
  66. Text($r('app.string.select_key_file'))
  67. .fontSize(16)
  68. .textAlign(TextAlign.Start)
  69. .lineHeight(22)
  70. Blank()
  71. Text(this.keyFileName === '' ? $r('app.string.please_choose') : this.keyFileName)
  72. .fontSize(14)
  73. .textAlign(TextAlign.Start)
  74. .lineHeight(19)
  75. Image($r('app.media.right_arrow'))
  76. .height('19vp')
  77. .width('10vp')
  78. .margin({ left: 9, right: 9, top: 6, bottom: 6 })
  79. }
  80. .backgroundColor(0xFFFFFF)
  81. .width('100%')
  82. .height('48vp')
  83. .padding({ left: 12, right: 12 })
  84. }.onClick(() => {
  85. this.selectAesKeyFileAndRead();
  86. })
  87. }
  88. .width('100%')
  89. .height('100%')
  90. .borderRadius(16)
  91. }
  92. }
  93. }
  94. .height('100vp')
  95. .margin({ left: 12, right: 12, bottom: 12 })
  96. GridRow() {
  97. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  98. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  99. Column() {
  100. Row() {
  101. Text($r('app.string.text_context'))
  102. .fontSize(16)
  103. .textAlign(TextAlign.Start)
  104. .fontWeight(500)
  105. .lineHeight(22)
  106. }
  107. .padding({ left: 12, right: 12 })
  108. .width('100%')
  109. .height('48vp')
  110. Row() {
  111. Text() {
  112. Span(this.plainText)
  113. .fontSize(16)
  114. .fontWeight(400)
  115. .fontColor('#182431')
  116. }.textAlign(TextAlign.Start)
  117. }
  118. .padding({ left: 12, right: 12, bottom: 4 })
  119. .width('100%')
  120. .height('52vp')
  121. }
  122. .borderRadius(16)
  123. .width('100%')
  124. .height('100')
  125. .backgroundColor(0xFFFFFF)
  126. }
  127. }
  128. }
  129. .height('100vp')
  130. .margin({ left: 12, right: 12, bottom: 12 })
  131. GridRow() {
  132. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  133. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  134. Column() {
  135. Row() {
  136. Text($r('app.string.encrypted_context'))
  137. .fontSize(16)
  138. .textAlign(TextAlign.Start)
  139. .fontWeight(500)
  140. .lineHeight(22)
  141. }
  142. .padding({ left: 12, right: 12 })
  143. .width('100%')
  144. .height('48vp')
  145. Row() {
  146. Text() {
  147. Span(this.cipherText)
  148. .fontSize(16)
  149. .fontWeight(400)
  150. .fontColor('#182431')
  151. }.textAlign(TextAlign.Start)
  152. }
  153. .padding({ left: 12, right: 12, bottom: 4 })
  154. .width('100%')
  155. .height('80vp')
  156. }
  157. .borderRadius(16)
  158. .width('100%')
  159. .height('100')
  160. .backgroundColor(0xFFFFFF)
  161. }
  162. }
  163. }
  164. .height('100vp')
  165. .margin({ left: 12, right: 12, bottom: 12 })
  166. Column() {
  167. GridRow() {
  168. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  169. Column() {
  170. Button() {
  171. Text($r('app.string.generate_aes_key_randomly')).fontSize(16).fontWeight(500)
  172. .lineHeight(22)
  173. .fontColor('#FFFFFF')
  174. }
  175. .id('encryptAesGenKey')
  176. .borderRadius(20)
  177. .type(ButtonType.Capsule)
  178. .width('100%')
  179. .height('40vp')
  180. .margin({ bottom: 16 })
  181. .backgroundColor('#007DFF')
  182. .onClick(() => {
  183. this.genAesKey();
  184. });
  185. Button() {
  186. Text($r('app.string.encrypt')).fontSize(16).fontWeight(500)
  187. .lineHeight(22)
  188. .fontColor('#FFFFFF')
  189. }
  190. .borderRadius(20)
  191. .id('encryptionBtn')
  192. .type(ButtonType.Capsule)
  193. .margin({ left: 24, right: 24 })
  194. .width('100%')
  195. .height('40vp')
  196. .backgroundColor('#007DFF')
  197. .onClick(() => {
  198. if (this.textFileUri === '' || this.keyFileUri === '') {
  199. promptAction.showToast({
  200. message: $r('app.string.null_message')
  201. });
  202. } else {
  203. this.encryptFunc();
  204. }
  205. });
  206. }
  207. }
  208. }.margin({ left: 24, right: 24 })
  209. }.width('100%').height('296vp').justifyContent(FlexAlign.End)
  210. }
  211. .width('100%')
  212. .height('100%')
  213. }
  214. }
  215. async selectAesKeyFileAndRead() {
  216. let documentSelectOptions = new picker.DocumentSelectOptions();
  217. documentSelectOptions.fileSuffixFilters = ['.txt'];
  218. documentSelectOptions.maxSelectNumber = 1;
  219. let uri: string = '';
  220. let documentViewPicker = new picker.DocumentViewPicker();
  221. await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
  222. uri = documentSelectResult[0];
  223. console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
  224. }).catch((err: Error) => {
  225. console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
  226. })
  227. this.keyFileUri = uri;
  228. await TextFileManager.readTextFile(this.keyFileUri);
  229. this.keyFileName = TextFileManager.getName();
  230. this.keyString = TextFileManager.getString();
  231. }
  232. async selectTextFileAndRead() {
  233. let documentSelectOptions = new picker.DocumentSelectOptions();
  234. documentSelectOptions.fileSuffixFilters = ['.txt'];
  235. documentSelectOptions.maxSelectNumber = 1;
  236. let uri: string = '';
  237. let documentViewPicker = new picker.DocumentViewPicker();
  238. await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
  239. uri = documentSelectResult[0];
  240. console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
  241. }).catch((err: Error) => {
  242. console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
  243. })
  244. this.textFileUri = uri;
  245. await TextFileManager.readTextFile(this.textFileUri);
  246. this.textFileName = TextFileManager.getName();
  247. this.plainText = TextFileManager.getString();
  248. }
  249. async createTextFileAndWrite() {
  250. let documentSaveOptions = new picker.DocumentSaveOptions();
  251. documentSaveOptions.newFileNames = ['cipherText.txt'];
  252. let documentPicker = new picker.DocumentViewPicker();
  253. let documentSaveResult = await documentPicker.save(documentSaveOptions);
  254. this.encryptedFileUri = documentSaveResult[0];
  255. await TextFileManager.writeTextFile(this.encryptedFileUri, this.cipherText);
  256. }
  257. async createKeyFileAndWrite() {
  258. let documentSaveOptions = new picker.DocumentSaveOptions();
  259. documentSaveOptions.newFileNames = ['aesKey.txt'];
  260. let documentPicker = new picker.DocumentViewPicker();
  261. let documentSaveResult = await documentPicker.save(documentSaveOptions);
  262. this.createKeyUri = documentSaveResult[0];
  263. await TextFileManager.writeTextFile(this.createKeyUri, this.keyString);
  264. }
  265. async encryptFunc() {
  266. if (this.plainText === '' || this.keyFileUri === '') {
  267. promptAction.showToast({
  268. message: $r('app.string.null_message')
  269. });
  270. return;
  271. }
  272. try {
  273. this.cipherText = await this.CryptoOperation.aesConvertAndEncrypt(this.keyString, this.plainText);
  274. } catch (error) {
  275. Logger.error(TAG, `encrypt failed, ${error}`);
  276. promptAction.showToast({
  277. message: $r('app.string.encrypt_fail')
  278. });
  279. }
  280. if (this.cipherText === '' || this.cipherText === undefined || this.cipherText === null) {
  281. promptAction.showToast({
  282. message: $r('app.string.encrypt_fail')
  283. });
  284. return;
  285. } else {
  286. try {
  287. await this.createTextFileAndWrite();
  288. } catch (error) {
  289. Logger.error(TAG, `encrypt failed, ${error}`);
  290. }
  291. }
  292. if (this.encryptedFileUri === '' || typeof (this.encryptedFileUri) == 'undefined') {
  293. promptAction.showToast({
  294. message: $r('app.string.encrypt_fail')
  295. });
  296. } else {
  297. promptAction.showToast({
  298. message: $r('app.string.encrypt_success')
  299. });
  300. }
  301. }
  302. async genAesKey() {
  303. try {
  304. this.keyString = await this.CryptoOperation.generateAesKey();
  305. } catch (error) {
  306. Logger.error(TAG, `gen aes key failed, ${error}`);
  307. }
  308. if (this.keyString === '' || typeof (this.keyString) == 'undefined') {
  309. promptAction.showToast({
  310. message: $r('app.string.gen_key_fail')
  311. });
  312. return;
  313. } else {
  314. try {
  315. await this.createKeyFileAndWrite();
  316. } catch (error) {
  317. Logger.error(TAG, `write aes key failed, ${error}`);
  318. }
  319. }
  320. if (this.createKeyUri === '' || typeof (this.createKeyUri) == 'undefined') {
  321. promptAction.showToast({
  322. message: $r('app.string.gen_key_fail')
  323. });
  324. } else {
  325. promptAction.showToast({
  326. message: $r('app.string.gen_key_success')
  327. });
  328. }
  329. }
  330. }
  • 对文本文件解密:在[Decrypt.ets] 文件中依次点击打开文件、选择密钥,通过filePicker选择密文文本文件和密钥文件,点击解密按钮,调用解密函数实现对文本内容进行解密,并将明文文件通过filePicker保存。 对消息解密的过程中采用cryptoFramework.Cipher完成解密操作。
  1. /*
  2. * Copyright (c) 2023 Huawei Device Co., Ltd.
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. import { promptAction } from '@kit.ArkUI';
  16. import Logger from '../util/Logger';
  17. import { picker } from '@kit.CoreFileKit';
  18. import { CryptoOperation } from '../cryptoframework/CryptoOperation';
  19. import TextFileManager from '../textfilemanager/TextFileManager';
  20. const TAG: string = '[Crypto_Framework]';
  21. @Component
  22. export struct Decrypt {
  23. @State keyFileName: string = '';
  24. @State keyFileUri: string = '';
  25. @State textFileUri: string = '';
  26. @State textFileName: string = '';
  27. @State keyString: string = '';
  28. @State cipherText: string = '';
  29. @State plainText: string = '';
  30. @State message: string = '';
  31. @State decryptedFileUri: string = '';
  32. private CryptoOperation: CryptoOperation = new CryptoOperation();
  33. build() {
  34. Stack({ alignContent: Alignment.Center }) {
  35. Column() {
  36. GridRow() {
  37. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  38. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  39. List() {
  40. ListItem() {
  41. Row() {
  42. Text($r('app.string.open_file'))
  43. .fontSize(16)
  44. .textAlign(TextAlign.Start)
  45. .lineHeight(22)
  46. Blank()
  47. Text(this.textFileName === '' ? $r('app.string.please_choose') : this.textFileName)
  48. .fontSize(14)
  49. .textAlign(TextAlign.Start)
  50. .lineHeight(19)
  51. Image($r('app.media.right_arrow'))
  52. .height('19vp')
  53. .width('10vp')
  54. .margin({ left: 9, right: 9, top: 6, bottom: 6 })
  55. }
  56. .backgroundColor(0xFFFFFF)
  57. .width('100%')
  58. .height('52vp')
  59. .padding({ top: 4, left: 12, right: 12 })
  60. }.onClick(() => {
  61. this.selectTextFileAndRead();
  62. })
  63. ListItem() {
  64. Row() {
  65. Text($r('app.string.select_key_file'))
  66. .fontSize(16)
  67. .textAlign(TextAlign.Start)
  68. .lineHeight(22)
  69. Blank()
  70. Text(this.keyFileName === '' ? $r('app.string.please_choose') : this.keyFileName)
  71. .fontSize(14)
  72. .textAlign(TextAlign.Start)
  73. .lineHeight(19)
  74. Image($r('app.media.right_arrow'))
  75. .height('19vp')
  76. .width('10vp')
  77. .margin({ left: 9, right: 9, top: 6, bottom: 6 })
  78. }
  79. .backgroundColor(0xFFFFFF)
  80. .width('100%')
  81. .height('48vp')
  82. .padding({ left: 12, right: 12 })
  83. }.onClick(() => {
  84. this.selectAesKeyFileAndRead();
  85. })
  86. }
  87. .width('100%')
  88. .height('100%')
  89. .borderRadius(16)
  90. }
  91. }
  92. }
  93. .height('100vp')
  94. .margin({ left: 12, right: 12, bottom: 12 })
  95. GridRow() {
  96. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  97. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  98. Column() {
  99. Row() {
  100. Text($r('app.string.text_context'))
  101. .fontSize(16)
  102. .textAlign(TextAlign.Start)
  103. .fontWeight(500)
  104. .lineHeight(22)
  105. }
  106. .padding({ left: 12, right: 12 })
  107. .width('100%')
  108. .height('48vp')
  109. Row() {
  110. Text() {
  111. Span(this.cipherText)
  112. .fontSize(16)
  113. .fontWeight(400)
  114. .fontColor('#182431')
  115. }.textAlign(TextAlign.Start)
  116. }
  117. .padding({ left: 12, right: 12, bottom: 4 })
  118. .width('100%')
  119. .height('52vp')
  120. }
  121. .borderRadius(16)
  122. .width('100%')
  123. .height('100')
  124. .backgroundColor(0xFFFFFF)
  125. }
  126. }
  127. }
  128. .height('100vp')
  129. .margin({ left: 12, right: 12, bottom: 12 })
  130. GridRow() {
  131. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  132. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  133. Column() {
  134. Row() {
  135. Text($r('app.string.decrypted_context'))
  136. .fontSize(16)
  137. .textAlign(TextAlign.Start)
  138. .fontWeight(500)
  139. .lineHeight(22)
  140. }
  141. .padding({ left: 12, right: 12 })
  142. .width('100%')
  143. .height('48vp')
  144. Row() {
  145. Text() {
  146. Span(this.plainText)
  147. .fontSize(16)
  148. .fontWeight(400)
  149. .fontColor('#182431')
  150. }.textAlign(TextAlign.Start)
  151. }
  152. .padding({ left: 12, right: 12, bottom: 4 })
  153. .width('100%')
  154. .height('52vp')
  155. }
  156. .borderRadius(16)
  157. .width('100%')
  158. .height('100')
  159. .backgroundColor(0xFFFFFF)
  160. }
  161. }
  162. }
  163. .height('100vp')
  164. .margin({ left: 12, right: 12, bottom: 12 })
  165. Column() {
  166. GridRow() {
  167. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  168. Column() {
  169. Button() {
  170. Text($r('app.string.decrypt')).fontSize(16).fontWeight(500)
  171. .lineHeight(22)
  172. .fontColor('#FFFFFF')
  173. }
  174. .borderRadius(20)
  175. .id('decryptionBtn')
  176. .type(ButtonType.Capsule)
  177. .margin({ left: 24, right: 24 })
  178. .width('100%')
  179. .height('40vp')
  180. .backgroundColor('#007DFF')
  181. .onClick(() => {
  182. if (this.textFileUri === '' || this.keyFileUri === '') {
  183. promptAction.showToast({
  184. message: $r('app.string.null_message')
  185. });
  186. } else {
  187. this.decryptFunc();
  188. }
  189. });
  190. }
  191. }
  192. }.margin({ left: 24, right: 24 })
  193. }.width('100%').height('296vp').justifyContent(FlexAlign.End)
  194. }
  195. .width('100%')
  196. .height('100%')
  197. }
  198. }
  199. async selectAesKeyFileAndRead() {
  200. let documentSelectOptions = new picker.DocumentSelectOptions();
  201. documentSelectOptions.fileSuffixFilters = ['.txt'];
  202. documentSelectOptions.maxSelectNumber = 1;
  203. let uri: string = '';
  204. let documentViewPicker = new picker.DocumentViewPicker();
  205. await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
  206. uri = documentSelectResult[0];
  207. console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
  208. }).catch((err: Error) => {
  209. console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
  210. })
  211. this.keyFileUri = uri;
  212. await TextFileManager.readTextFile(this.keyFileUri);
  213. this.keyFileName = TextFileManager.getName();
  214. this.keyString = TextFileManager.getString();
  215. }
  216. async selectTextFileAndRead() {
  217. let documentSelectOptions = new picker.DocumentSelectOptions();
  218. documentSelectOptions.fileSuffixFilters = ['.txt'];
  219. documentSelectOptions.maxSelectNumber = 1;
  220. let uri: string = '';
  221. let documentViewPicker = new picker.DocumentViewPicker();
  222. await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
  223. uri = documentSelectResult[0];
  224. console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
  225. }).catch((err: Error) => {
  226. console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
  227. })
  228. this.textFileUri = uri;
  229. await TextFileManager.readTextFile(this.textFileUri);
  230. this.textFileName = TextFileManager.getName();
  231. this.cipherText = TextFileManager.getString();
  232. }
  233. async createTextFileAndWrite() {
  234. let documentSaveOptions = new picker.DocumentSaveOptions();
  235. documentSaveOptions.newFileNames = ['plainText.txt'];
  236. let documentPicker = new picker.DocumentViewPicker();
  237. let documentSaveResult = await documentPicker.save(documentSaveOptions);
  238. this.decryptedFileUri = documentSaveResult[0];
  239. await TextFileManager.writeTextFile(this.decryptedFileUri, this.plainText);
  240. }
  241. async decryptFunc() {
  242. if (this.cipherText === '' || this.keyFileUri === '') {
  243. promptAction.showToast({
  244. message: $r('app.string.null_message')
  245. });
  246. return;
  247. }
  248. try {
  249. this.plainText = await this.CryptoOperation.aesConvertAndDecrypt(this.keyString, this.cipherText);
  250. } catch (error) {
  251. Logger.error(TAG, `decrypt failed, ${error}`);
  252. promptAction.showToast({
  253. message: $r('app.string.decrypt_fail')
  254. });
  255. return;
  256. }
  257. if (this.plainText === '' || this.plainText === null || this.plainText === undefined) {
  258. promptAction.showToast({
  259. message: $r('app.string.decrypt_fail')
  260. });
  261. return;
  262. } else {
  263. try {
  264. await this.createTextFileAndWrite();
  265. } catch (error) {
  266. Logger.error(TAG, `decrypt failed, ${error}`);
  267. }
  268. }
  269. if (this.decryptedFileUri === '' || typeof (this.decryptedFileUri) == 'undefined') {
  270. promptAction.showToast({
  271. message: $r('app.string.decrypt_fail')
  272. });
  273. } else {
  274. promptAction.showToast({
  275. message: $r('app.string.decrypt_success')
  276. });
  277. }
  278. }
  279. }
  • 对文本文件签名:在[Sign.ets] 文件中依次点击打开文件、选择密钥,通过filePicker选择待签名文本文件和密钥文件,点击签名按钮,调用签名函数实现对文本内容进行加密,并将签名文件通过filePicker保存。 需要生成密钥文本文件时,可以点击随机生成RSA密钥,通过调用cryptoFramework.asyKeyGenerator生成用于签名的RSA密钥,并通过filePicker保存密钥文本文件。 对消息签名的过程中采用cryptoFramework.Sign完成加密操作。
  1. /*
  2. * Copyright (c) 2023 Huawei Device Co., Ltd.
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. import { promptAction } from '@kit.ArkUI';
  16. import Logger from '../util/Logger';
  17. import { picker } from '@kit.CoreFileKit';
  18. import { CryptoOperation } from '../cryptoframework/CryptoOperation';
  19. import TextFileManager from '../textfilemanager/TextFileManager';
  20. const TAG: string = '[Crypto_Framework]';
  21. @Component
  22. export struct Sign {
  23. @State keyFileName: string = '';
  24. @State keyFileUri: string = '';
  25. @State textFileUri: string = '';
  26. @State textFileName: string = '';
  27. @State keyString: string = '';
  28. @State cipherText: string = '';
  29. @State plainText: string = '';
  30. @State message: string = '';
  31. @State signFileUri: string = '';
  32. @State createKeyUri: string = '';
  33. private CryptoOperation: CryptoOperation = new CryptoOperation();
  34. build() {
  35. Stack({ alignContent: Alignment.Center }) {
  36. Column() {
  37. GridRow() {
  38. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  39. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  40. List() {
  41. ListItem() {
  42. Row() {
  43. Text($r('app.string.open_file'))
  44. .fontSize(16)
  45. .textAlign(TextAlign.Start)
  46. .lineHeight(22)
  47. Blank()
  48. Text(this.textFileName === '' ? $r('app.string.please_choose') : this.textFileName)
  49. .fontSize(14)
  50. .textAlign(TextAlign.Start)
  51. .lineHeight(19)
  52. Image($r('app.media.right_arrow'))
  53. .height('19vp')
  54. .width('10vp')
  55. .margin({ left: 9, right: 9, top: 6, bottom: 6 })
  56. }
  57. .backgroundColor(0xFFFFFF)
  58. .width('100%')
  59. .height('52vp')
  60. .padding({ top: 4, left: 12, right: 12 })
  61. }.onClick(() => {
  62. this.selectTextFileAndRead();
  63. })
  64. ListItem() {
  65. Row() {
  66. Text($r('app.string.select_key_file'))
  67. .fontSize(16)
  68. .textAlign(TextAlign.Start)
  69. .lineHeight(22)
  70. Blank()
  71. Text(this.keyFileName === '' ? $r('app.string.please_choose') : this.keyFileName)
  72. .fontSize(14)
  73. .textAlign(TextAlign.Start)
  74. .lineHeight(19)
  75. Image($r('app.media.right_arrow'))
  76. .height('19vp')
  77. .width('10vp')
  78. .margin({ left: 9, right: 9, top: 6, bottom: 6 })
  79. }
  80. .backgroundColor(0xFFFFFF)
  81. .width('100%')
  82. .height('48vp')
  83. .padding({ left: 12, right: 12 })
  84. }.onClick(() => {
  85. this.selectRsaKeyFileAndRead();
  86. })
  87. }
  88. .width('100%')
  89. .height('100%')
  90. .borderRadius(16)
  91. }
  92. }
  93. }
  94. .height('100vp')
  95. .margin({ left: 12, right: 12, bottom: 12 })
  96. GridRow() {
  97. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  98. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  99. Column() {
  100. Row() {
  101. Text($r('app.string.text_context'))
  102. .fontSize(16)
  103. .textAlign(TextAlign.Start)
  104. .fontWeight(500)
  105. .lineHeight(22)
  106. }
  107. .padding({ left: 12, right: 12 })
  108. .width('100%')
  109. .height('48vp')
  110. Row() {
  111. Text() {
  112. Span(this.plainText)
  113. .fontSize(16)
  114. .fontWeight(400)
  115. .fontColor('#182431')
  116. }.textAlign(TextAlign.Start)
  117. }
  118. .padding({ left: 12, right: 12, bottom: 4 })
  119. .width('100%')
  120. .height('52vp')
  121. }
  122. .borderRadius(16)
  123. .width('100%')
  124. .height('100')
  125. .backgroundColor(0xFFFFFF)
  126. }
  127. }
  128. }
  129. .height('100vp')
  130. .margin({ left: 12, right: 12, bottom: 12 })
  131. Column() {
  132. GridRow() {
  133. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  134. Column() {
  135. Button() {
  136. Text($r('app.string.generate_rsa_key_randomly')).fontSize(16).fontWeight(500)
  137. .lineHeight(22)
  138. .fontColor('#FFFFFF')
  139. }
  140. .id('encryptRsaGenKey')
  141. .borderRadius(20)
  142. .type(ButtonType.Capsule)
  143. .width('100%')
  144. .height('40vp')
  145. .margin({ bottom: 16 })
  146. .backgroundColor('#007DFF')
  147. .onClick(() => {
  148. this.genRsaKey();
  149. });
  150. Button() {
  151. Text($r('app.string.sign')).fontSize(16).fontWeight(500)
  152. .lineHeight(22)
  153. .fontColor('#FFFFFF')
  154. }
  155. .borderRadius(20)
  156. .id('signBtn')
  157. .type(ButtonType.Capsule)
  158. .margin({ left: 24, right: 24 })
  159. .width('100%')
  160. .height('40vp')
  161. .backgroundColor('#007DFF')
  162. .onClick(() => {
  163. if (this.textFileUri === '' || this.keyFileUri === '') {
  164. promptAction.showToast({
  165. message: $r('app.string.null_message')
  166. });
  167. } else {
  168. this.signFunc();
  169. }
  170. });
  171. }
  172. }
  173. }.margin({ left: 24, right: 24 })
  174. }.width('100%').height('412vp').justifyContent(FlexAlign.End)
  175. }
  176. .width('100%')
  177. .height('100%')
  178. }
  179. }
  180. async selectRsaKeyFileAndRead() {
  181. let documentSelectOptions = new picker.DocumentSelectOptions();
  182. documentSelectOptions.fileSuffixFilters = ['.txt'];
  183. documentSelectOptions.maxSelectNumber = 1;
  184. let uri: string = '';
  185. let documentViewPicker = new picker.DocumentViewPicker();
  186. await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
  187. uri = documentSelectResult[0];
  188. console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
  189. }).catch((err: Error) => {
  190. console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
  191. })
  192. this.keyFileUri = uri;
  193. // 获取到密钥文档文件的文件名称
  194. await TextFileManager.readTextFile(this.keyFileUri);
  195. this.keyFileName = TextFileManager.getName();
  196. this.keyString = TextFileManager.getString();
  197. }
  198. async selectTextFileAndRead() {
  199. let documentSelectOptions = new picker.DocumentSelectOptions();
  200. documentSelectOptions.fileSuffixFilters = ['.txt'];
  201. documentSelectOptions.maxSelectNumber = 1;
  202. let uri: string = '';
  203. let documentViewPicker = new picker.DocumentViewPicker();
  204. await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
  205. uri = documentSelectResult[0];
  206. console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
  207. }).catch((err: Error) => {
  208. console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
  209. })
  210. // 获取到文档文件的URI
  211. this.textFileUri = uri;
  212. // 获取到文档文件的文件名称
  213. await TextFileManager.readTextFile(this.textFileUri);
  214. this.textFileName = TextFileManager.getName();
  215. this.plainText = TextFileManager.getString();
  216. }
  217. async createTextFileAndWrite() {
  218. let documentSaveOptions = new picker.DocumentSaveOptions();
  219. documentSaveOptions.newFileNames = ['signText.txt'];
  220. let documentPicker = new picker.DocumentViewPicker();
  221. let documentSaveResult = await documentPicker.save(documentSaveOptions);
  222. this.signFileUri = documentSaveResult[0];
  223. await TextFileManager.writeTextFile(this.signFileUri, this.cipherText);
  224. }
  225. async createKeyFileAndWrite() {
  226. let documentSaveOptions = new picker.DocumentSaveOptions();
  227. documentSaveOptions.newFileNames = ['rsaKey.txt'];
  228. let documentPicker = new picker.DocumentViewPicker();
  229. try {
  230. let documentSaveResult = await documentPicker.save(documentSaveOptions);
  231. this.createKeyUri = documentSaveResult[0];
  232. await TextFileManager.writeTextFile(this.createKeyUri, this.keyString);
  233. } catch (error) {
  234. Logger.error(TAG, `save key failed, ${error}`);
  235. }
  236. }
  237. async signFunc() {
  238. if (this.plainText === '' || this.keyFileUri === '') {
  239. promptAction.showToast({
  240. message: $r('app.string.null_message')
  241. });
  242. return;
  243. }
  244. try {
  245. this.cipherText = await this.CryptoOperation.rsaConvertAndSign(this.keyString, this.plainText);
  246. } catch (error) {
  247. promptAction.showToast({
  248. message: $r('app.string.sign_fail')
  249. });
  250. Logger.error(TAG, `sign failed, ${error}`);
  251. }
  252. if (this.cipherText === '' || this.cipherText === null || this.cipherText === undefined) {
  253. promptAction.showToast({
  254. message: $r('app.string.sign_fail')
  255. });
  256. return;
  257. } else {
  258. await this.createTextFileAndWrite();
  259. }
  260. if (this.signFileUri === '' || typeof (this.signFileUri) == 'undefined') {
  261. promptAction.showToast({
  262. message: $r('app.string.sign_fail')
  263. });
  264. } else {
  265. promptAction.showToast({
  266. message: $r('app.string.sign_success')
  267. });
  268. }
  269. }
  270. async genRsaKey() {
  271. promptAction.showToast({
  272. message: $r('app.string.slow_rsa_key_gen')
  273. });
  274. try {
  275. this.keyString = await this.CryptoOperation.generateRsaKey();
  276. } catch (error) {
  277. Logger.error(TAG, `gen rsa key failed, ${error}`);
  278. }
  279. if (this.keyString === '' || typeof (this.keyString) == 'undefined') {
  280. promptAction.showToast({
  281. message: $r('app.string.gen_key_fail')
  282. });
  283. return;
  284. } else {
  285. try {
  286. await this.createKeyFileAndWrite();
  287. } catch (error) {
  288. Logger.error(TAG, `write rsa key failed, ${error}`);
  289. }
  290. }
  291. if (this.createKeyUri === '' || typeof (this.createKeyUri) == 'undefined') {
  292. promptAction.showToast({
  293. message: $r('app.string.gen_key_fail')
  294. });
  295. } else {
  296. promptAction.showToast({
  297. message: $r('app.string.gen_key_success')
  298. });
  299. }
  300. }
  301. }
  • 对文本文件验签:在[Verify.ets]文件中依次点击打开文件、选择密钥、选择签名文件,通过filePicker选择密文文本文件、密钥文件和签名文件,点击验签按钮,调用验签函数实现对文本内容进行验签,并显示验签结果。 对消息验签的过程中采用cryptoFramework.Verify完成验签操作。
  1. /*
  2. * Copyright (c) 2023 Huawei Device Co., Ltd.
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. import { promptAction } from '@kit.ArkUI';
  16. import Logger from '../util/Logger';
  17. import { picker } from '@kit.CoreFileKit';
  18. import { CryptoOperation } from '../cryptoframework/CryptoOperation';
  19. import TextFileManager from '../textfilemanager/TextFileManager';
  20. const TAG: string = '[Crypto_Framework]';
  21. @Component
  22. export struct Verify {
  23. @State keyFileName: string = '';
  24. @State keyFileUri: string = '';
  25. @State textFileUri: string = '';
  26. @State textFileName: string = '';
  27. @State keyString: string = '';
  28. @State plainText: string = '';
  29. @State message: string = '';
  30. @State signFileUri: string = '';
  31. @State signFileName: string = '';
  32. @State signText: string = '';
  33. @State createKeyUri: string = '';
  34. private CryptoOperation: CryptoOperation = new CryptoOperation();
  35. build() {
  36. Stack({ alignContent: Alignment.Center }) {
  37. Column() {
  38. GridRow() {
  39. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  40. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  41. List() {
  42. ListItem() {
  43. Row() {
  44. Text($r('app.string.open_file'))
  45. .fontSize(16)
  46. .textAlign(TextAlign.Start)
  47. .lineHeight(22)
  48. Blank()
  49. Text(this.textFileName === '' ? $r('app.string.please_choose') : this.textFileName)
  50. .fontSize(14)
  51. .textAlign(TextAlign.Start)
  52. .lineHeight(19)
  53. Image($r('app.media.right_arrow'))
  54. .height('19vp')
  55. .width('10vp')
  56. .margin({ left: 9, right: 9, top: 6, bottom: 6 })
  57. }
  58. .backgroundColor(0xFFFFFF)
  59. .width('100%')
  60. .height('52vp')
  61. .padding({ top: 4, left: 12, right: 12 })
  62. }.onClick(() => {
  63. this.selectTextFileAndRead();
  64. })
  65. ListItem() {
  66. Row() {
  67. Text($r('app.string.select_key_file'))
  68. .fontSize(16)
  69. .textAlign(TextAlign.Start)
  70. .lineHeight(22)
  71. Blank()
  72. Text(this.keyFileName === '' ? $r('app.string.please_choose') : this.keyFileName)
  73. .fontSize(14)
  74. .textAlign(TextAlign.Start)
  75. .lineHeight(19)
  76. Image($r('app.media.right_arrow'))
  77. .height('19vp')
  78. .width('10vp')
  79. .margin({ left: 9, right: 9, top: 6, bottom: 6 })
  80. }
  81. .backgroundColor(0xFFFFFF)
  82. .width('100%')
  83. .height('48vp')
  84. .padding({ left: 12, right: 12 })
  85. }.onClick(() => {
  86. this.selectRsaKeyFileAndRead();
  87. })
  88. }
  89. .width('100%')
  90. .height('100%')
  91. .borderRadius(16)
  92. }
  93. }
  94. }
  95. .height('100vp')
  96. .margin({ left: 12, right: 12, bottom: 12 })
  97. GridRow() {
  98. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  99. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  100. List() {
  101. ListItem() {
  102. Row() {
  103. Text($r('app.string.select_signature_file'))
  104. .fontSize(16)
  105. .textAlign(TextAlign.Start)
  106. .lineHeight(22)
  107. Blank()
  108. Text(this.signFileName === '' ? $r('app.string.please_choose') : this.signFileName)
  109. .fontSize(14)
  110. .textAlign(TextAlign.Start)
  111. .lineHeight(19)
  112. Image($r('app.media.right_arrow'))
  113. .height('19vp')
  114. .width('10vp')
  115. .margin({ left: 9, right: 9, top: 6, bottom: 6 })
  116. }
  117. .backgroundColor(0xFFFFFF)
  118. .width('100%')
  119. .height('56vp')
  120. .padding({ left: 12, right: 12, top: 4, bottom: 4 })
  121. }.onClick(() => {
  122. this.selectSignFileAndRead();
  123. })
  124. }
  125. .width('100%')
  126. .borderRadius(16)
  127. }
  128. }
  129. }
  130. .height('56vp')
  131. .margin({ left: 12, right: 12, bottom: 12 })
  132. GridRow() {
  133. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  134. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  135. Column() {
  136. Row() {
  137. Text($r('app.string.text_context'))
  138. .fontSize(16)
  139. .textAlign(TextAlign.Start)
  140. .fontWeight(500)
  141. .lineHeight(22)
  142. }
  143. .padding({ left: 12, right: 12 })
  144. .width('100%')
  145. .height('48vp')
  146. Row() {
  147. Text() {
  148. Span(this.plainText)
  149. .fontSize(16)
  150. .fontWeight(400)
  151. .fontColor('#182431')
  152. }.textAlign(TextAlign.Start)
  153. }
  154. .padding({ left: 12, right: 12, bottom: 4 })
  155. .width('100%')
  156. .height('52vp')
  157. }
  158. .borderRadius(16)
  159. .width('100%')
  160. .height('100')
  161. .backgroundColor(0xFFFFFF)
  162. }
  163. }
  164. }
  165. .height('100vp')
  166. .margin({ left: 12, right: 12, bottom: 12 })
  167. Column() {
  168. GridRow() {
  169. GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12 } }) {
  170. Column() {
  171. Button() {
  172. Text($r('app.string.verify')).fontSize(16).fontWeight(500)
  173. .lineHeight(22)
  174. .fontColor('#FFFFFF')
  175. }
  176. .borderRadius(20)
  177. .id('verifyBtn')
  178. .type(ButtonType.Capsule)
  179. .margin({ left: 24, right: 24 })
  180. .width('100%')
  181. .height('40vp')
  182. .backgroundColor('#007DFF')
  183. .onClick(() => {
  184. if (this.textFileUri === '' || this.keyFileUri === '' || this.signFileUri === '') {
  185. promptAction.showToast({
  186. message: $r('app.string.null_message')
  187. });
  188. } else {
  189. this.verifyFunc();
  190. }
  191. });
  192. }
  193. }
  194. }.margin({ left: 24, right: 24 })
  195. }.width('100%').height('340vp').justifyContent(FlexAlign.End)
  196. }
  197. .width('100%')
  198. .height('100%')
  199. }
  200. }
  201. async selectRsaKeyFileAndRead() {
  202. let documentSelectOptions = new picker.DocumentSelectOptions();
  203. documentSelectOptions.fileSuffixFilters = ['.txt'];
  204. documentSelectOptions.maxSelectNumber = 1;
  205. let uri: string = '';
  206. let documentViewPicker = new picker.DocumentViewPicker();
  207. await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
  208. uri = documentSelectResult[0];
  209. console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
  210. }).catch((err: Error) => {
  211. console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
  212. })
  213. // 获取到密钥文档文件的URI
  214. this.keyFileUri = uri;
  215. // 获取到密钥文档文件的文件名称
  216. await TextFileManager.readTextFile(this.keyFileUri);
  217. this.keyFileName = TextFileManager.getName();
  218. this.keyString = TextFileManager.getString();
  219. }
  220. async selectTextFileAndRead() {
  221. let documentSelectOptions = new picker.DocumentSelectOptions();
  222. documentSelectOptions.fileSuffixFilters = ['.txt'];
  223. documentSelectOptions.maxSelectNumber = 1;
  224. let uri: string = '';
  225. let documentViewPicker = new picker.DocumentViewPicker();
  226. await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
  227. uri = documentSelectResult[0];
  228. console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
  229. }).catch((err: Error) => {
  230. console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
  231. })
  232. // 获取到文档文件的URI
  233. this.textFileUri = uri;
  234. // 获取到文档文件的文件名称
  235. await TextFileManager.readTextFile(this.textFileUri);
  236. this.textFileName = TextFileManager.getName();
  237. this.plainText = TextFileManager.getString();
  238. }
  239. async selectSignFileAndRead() {
  240. let documentSelectOptions = new picker.DocumentSelectOptions();
  241. documentSelectOptions.fileSuffixFilters = ['.txt'];
  242. documentSelectOptions.maxSelectNumber = 1;
  243. let uri: string = '';
  244. let documentViewPicker = new picker.DocumentViewPicker();
  245. await documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
  246. uri = documentSelectResult[0];
  247. console.info('documentViewPicker.select to text file succeed and uris are:' + uri);
  248. }).catch((err: Error) => {
  249. console.error(`Invoke documentViewPicker.select failed, code is ${err}, message is ${err.message}`);
  250. })
  251. // 获取到文档文件的URI
  252. this.signFileUri = uri;
  253. // 获取到文档文件的文件名称
  254. await TextFileManager.readTextFile(this.signFileUri);
  255. this.signFileName = TextFileManager.getName();
  256. this.signText = TextFileManager.getString();
  257. }
  258. async createKeyFileAndWrite() {
  259. let documentSaveOptions = new picker.DocumentSaveOptions();
  260. documentSaveOptions.newFileNames = ['rsaKey.txt'];
  261. let documentPicker = new picker.DocumentViewPicker();
  262. try {
  263. let documentSaveResult = await documentPicker.save(documentSaveOptions);
  264. this.createKeyUri = documentSaveResult[0];
  265. await TextFileManager.writeTextFile(this.createKeyUri, this.keyString);
  266. } catch (error) {
  267. Logger.error(TAG, `save key failed, ${error}`);
  268. }
  269. }
  270. async verifyFunc() {
  271. let verifyRes: Boolean = false;
  272. if (this.plainText === '' || this.keyFileUri === '' || this.signText === '') {
  273. promptAction.showToast({
  274. message: $r('app.string.null_message')
  275. });
  276. return;
  277. }
  278. try {
  279. verifyRes = await this.CryptoOperation.rsaConvertAndVerify(this.keyString, this.plainText, this.signText);
  280. } catch (error) {
  281. Logger.error(TAG, `verify failed, ${error}`);
  282. }
  283. if (verifyRes != true) {
  284. promptAction.showToast({
  285. message: $r('app.string.verify_fail')
  286. });
  287. return;
  288. } else {
  289. promptAction.showToast({
  290. message: $r('app.string.verify_success')
  291. });
  292. }
  293. }
  294. }

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

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

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

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

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

鸿蒙面经

在这里插入图片描述

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


本文转载自: https://blog.csdn.net/2301_76813281/article/details/140874505
版权归原作者 爱桥代码的程序媛 所有, 如有侵权,请联系我们删除。

“鸿蒙系统开发【加解密算法库框架】安全”的评论:

还没有评论