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}