• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2025 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
16// [Start gcm_seg_encrypt_decrypt_aes_symkey_async]
17import { cryptoFramework } from '@kit.CryptoArchitectureKit';
18import { buffer } from '@kit.ArkTS';
19
20function generateRandom(len: number) {
21  let rand = cryptoFramework.createRandom();
22  let generateRandSync = rand.generateRandomSync(len);
23  return generateRandSync;
24}
25
26function genGcmParamsSpec() {
27  let ivBlob = generateRandom(12);
28  let arr = [1, 2, 3, 4, 5, 6, 7, 8]; // 8 bytes
29  let dataAad = new Uint8Array(arr);
30  let aadBlob: cryptoFramework.DataBlob = { data: dataAad };
31  arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes
32  let dataTag = new Uint8Array(arr);
33  let tagBlob: cryptoFramework.DataBlob = {
34    data: dataTag
35  }; // The GCM authTag is obtained by doFinal() in encryption and passed in params of init() in decryption.
36  let gcmParamsSpec: cryptoFramework.GcmParamsSpec = {
37    iv: ivBlob,
38    aad: aadBlob,
39    authTag: tagBlob,
40    algName: 'GcmParamsSpec'
41  };
42  return gcmParamsSpec;
43}
44
45let gcmParams = genGcmParamsSpec();
46
47// 分段加密消息
48async function encryptMessageUpdateBySegment(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) {
49  let cipher = cryptoFramework.createCipher('AES128|GCM|PKCS7');
50  await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, gcmParams);
51  let updateLength = 20; // 假设以20字节为单位进行分段update,实际并无要求
52  let cipherText = new Uint8Array();
53  for (let i = 0; i < plainText.data.length; i += updateLength) {
54    let updateMessage = plainText.data.subarray(i, i + updateLength);
55    let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
56    // 分段update
57    let updateOutput = await cipher.update(updateMessageBlob);
58    // 把update的结果拼接起来,得到密文(有些情况下还需拼接doFinal的结果,这取决于分组模式
59    // 和填充模式,本例中GCM模式的doFinal结果只包含authTag而不含密文,所以不需要拼接)
60    let mergeText = new Uint8Array(cipherText.length + updateOutput.data.length);
61    mergeText.set(cipherText);
62    mergeText.set(updateOutput.data, cipherText.length);
63    cipherText = mergeText;
64  }
65  gcmParams.authTag = await cipher.doFinal(null);
66  let cipherBlob: cryptoFramework.DataBlob = { data: cipherText };
67  return cipherBlob;
68}
69
70// 分段解密消息
71async function decryptMessagePromise(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) {
72  let decoder = cryptoFramework.createCipher('AES128|GCM|PKCS7');
73  await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, gcmParams);
74  let updateLength = 20; // 假设以20字节为单位进行分段update,实际并无要求
75  let decryptText = new Uint8Array();
76  for (let i = 0; i < cipherText.data.length; i += updateLength) {
77    let updateMessage = cipherText.data.subarray(i, i + updateLength);
78    let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
79    // 分段update
80    let updateOutput = await decoder.update(updateMessageBlob);
81    // 把update的结果拼接起来,得到明文
82    let mergeText = new Uint8Array(decryptText.length + updateOutput.data.length);
83    mergeText.set(decryptText);
84    mergeText.set(updateOutput.data, decryptText.length);
85    decryptText = mergeText;
86  }
87  let decryptData = await decoder.doFinal(null);
88  if (decryptData == null) {
89    console.info('GCM decrypt success, decryptData is null');
90  }
91  let decryptBlob: cryptoFramework.DataBlob = { data: decryptText };
92  return decryptBlob;
93}
94
95async function genSymKeyByData(symKeyData: Uint8Array) {
96  let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
97  let aesGenerator = cryptoFramework.createSymKeyGenerator('AES128');
98  let symKey = await aesGenerator.convertKey(symKeyBlob);
99  console.info('convertKey success');
100  return symKey;
101}
102
103async function aes() {
104  let keyData = new Uint8Array([83, 217, 231, 76, 28, 113, 23, 219, 250, 71, 209, 210, 205, 97, 32, 159]);
105  let symKey = await genSymKeyByData(keyData);
106  let message = 'aaaaa.....bbbbb.....ccccc.....ddddd.....eee'; // 假设信息总共43字节,根据utf-8解码后,也是43字节
107  let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) };
108  let encryptText = await encryptMessageUpdateBySegment(symKey, plainText);
109  let decryptText = await decryptMessagePromise(symKey, encryptText);
110  if (plainText.data.toString() === decryptText.data.toString()) {
111    console.info('decrypt ok');
112    console.info('decrypt plainText: ' + buffer.from(decryptText.data).toString('utf-8'));
113  } else {
114    console.error('decrypt failed');
115  }
116}
117// [End gcm_seg_encrypt_decrypt_aes_symkey_async]
118
119@Entry
120@Component
121struct Index {
122  @State message: string = 'Encryption Decryption Guidance Aes ArkTs';
123
124  build() {
125    Column({ space: 12 }) {
126      Text(this.message).fontSize(20).fontWeight(FontWeight.Bold)
127      Button($r('app.string.call_aes_gcm_segmentation_asynchronous'))
128        .width('70%')
129        .onClick(() => {
130          try {
131            aes();
132            this.message = 'AES_GCMAsynchronousSuccess';
133          } catch {
134            this.message = 'AES_GCMAsynchronousFail';
135          }
136        })
137    }
138    .height('100%')
139    .width('100%')
140  }
141}