HarmonyOS 鸿蒙Next huks(通用密钥)大文件如何分段加解密,有没有示例?

发布于 1周前 作者 sinazl 来自 鸿蒙OS

HarmonyOS 鸿蒙Next huks(通用密钥)大文件如何分段加解密,有没有示例?

小的单个文件,是可以正常加解密的。
但是大文件(大于 200K)需要分段加解密,调用updateSession方法,但是官方文档没有关于这个updateSession怎么分段调用的示例。

试了很多次,加密不报错,但是解密出来的文件不对。

3 回复
import { hilog } from '[@kit](/user/kit).PerformanceAnalysisKit';
import { huks } from '[@kit](/user/kit).UniversalKeystoreKit';
import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';

[@Entry](/user/Entry)
[@Component](/user/Component)
struct Index {
build() {
Column() {
Button('测试加解密')
.width('100%')
.onClick(async () => {
generatorData()
await GenerateAesKey();
await EncryptData();
await DecryptData();
})
}
.width('100%')
.height('100%')
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
}
}

let aesKeyAlias = 'test_aesKeyAlias';
let handle: number;
let plainText = '1234567890';
let IV = '001122334455';
let cipherData: Uint8Array;

function generatorData() {
let i = 0
plainText = '1234567890';
while (i <= 13) {
i++
plainText = plainText + plainText
}
console.log('造数据成功')
}

function StringToUint8Array(str: String) {
let arr: number[] = new Array();
for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i));
}
return new Uint8Array(arr);
}

function Uint8ArrayToString(fileData: Uint8Array) {
let dataString = '';
for (let i = 0; i < fileData.length; i++) {
dataString += String.fromCharCode(fileData[i]);
}
return dataString;
}

function GetAesGenerateProperties() {
let properties: Array<huks.HuksParam> = [{
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES
}, {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128
}, {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
}];
return properties;
}

function GetAesEncryptProperties() {
let properties: Array<huks.HuksParam> = [{
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES
}, {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128
}, {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT
}, {
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksKeyPadding.HUKS_PADDING_PKCS7
}, {
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksCipherMode.HUKS_MODE_CBC
}, {
tag: huks.HuksTag.HUKS_TAG_IV,
value: StringToUint8Array(IV)
}];
return properties;
}

function GetAesDecryptProperties() {
let properties: Array<huks.HuksParam> = [{
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES
}, {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128
}, {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
}, {
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksKeyPadding.HUKS_PADDING_PKCS7
}, {
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksCipherMode.HUKS_MODE_CBC
}, {
tag: huks.HuksTag.HUKS_TAG_IV,
value: StringToUint8Array(IV)
}];
return properties;
}

async function GenerateAesKey() {
let genProperties = GetAesGenerateProperties();
let options: huks.HuksOptions = {
properties: genProperties
};

await huks.generateKeyItem(aesKeyAlias, options)
.then((data) => {
hilog.info(0x0000, 'AppDataSecurity', `promise: generate AES Key success, data = ${JSON.stringify(data)}`);
}).catch((error: Error) => {
hilog.error(0x0000, 'AppDataSecurity', `promise: generate AES Key failed, ${JSON.stringify(error)}`);
})
}

const MAX_UPDATE_SESSION_LENGTH = 1024;

// 分段加密
async function EncryptData() {
let encryptProperties = GetAesEncryptProperties();
let options: huks.HuksOptions = {
properties: encryptProperties,
inData: new Uint8Array(0)
};

await huks.initSession(aesKeyAlias, options)
.then((data) => {
handle = data.handle;
}).catch((error: Error) => {
hilog.error(0x0000, 'AppDataSecurity', `promise: init EncryptData failed, ${JSON.stringify(error)}`);
})

let resultTemp = new Uint8Array(0);
let contentTemp = plainText;
while (contentTemp.length > 0) {
// 超过长度会取最长
const contentCurr = contentTemp.substring(0, MAX_UPDATE_SESSION_LENGTH);
// 起始点大于长度会返回""
contentTemp = contentTemp.substring(MAX_UPDATE_SESSION_LENGTH, contentTemp.length);
options.inData = StringToUint8Array(contentCurr);
await huks.updateSession(handle, options).then((data) => {
const mergeText = new Uint8Array(resultTemp.length + data.outData!.length);
mergeText.set(resultTemp);
mergeText.set(data.outData!, resultTemp.length);
resultTemp = mergeText;
}).catch(async (error: BusinessError) => {
hilog.error(0x0000, 'AppDataSecurity', `promise: encrypt updateSession failed, ${JSON.stringify(error)}`);
})
}

//分段加解密时,传入finishSession的inData要设置为空的
options.inData = new Uint8Array(0);
await huks.finishSession(handle, options).then((data) => {
cipherData = new Uint8Array(resultTemp.length + data.outData!.length);
cipherData.set(resultTemp);
cipherData.set(data.outData!, resultTemp.length);
}).catch((error: Error) => {
hilog.error(0x0000, 'AppDataSecurity', `promise: encrypt data failed, ${JSON.stringify(error)}`);
})
}

// 分段解密
async function DecryptData() {
let decryptOptions = GetAesDecryptProperties()
let options: huks.HuksOptions = {
properties: decryptOptions,
inData: cipherData
};

await huks.initSession(aesKeyAlias, options)
.then((data) => {
handle = data.handle;
}).catch((error: Error) => {
hilog.error(0x0000, 'AppDataSecurity', `promise: init DecryptData failed, ${JSON.stringify(error)}`);
})

let resultTemp = new Uint8Array(0);
let contentTemp = cipherData;
while (contentTemp.length > 0) {
const contentCurr = contentTemp.slice(0, MAX_UPDATE_SESSION_LENGTH); // 超过长度会取最长
contentTemp = contentTemp.slice(MAX_UPDATE_SESSION_LENGTH, contentTemp.length);
options.inData = contentCurr;
await huks.updateSession(handle, options).then((data) => {
const mergeText = new Uint8Array(resultTemp.length + data.outData!.length);
mergeText.set(resultTemp);
mergeText.set(data.outData!, resultTemp.length);
resultTemp = mergeText;
}).catch((error: Error) => {
hilog.error(0x0000, 'AppDataSecurity', `promise: encrypt updateSession failed, ${JSON.stringify(error)}`);
})
}

options.inData = new Uint8Array(0);
await huks.finishSession(handle, options).then(() => {
let str = Uint8ArrayToString(resultTemp)
console.log("批量加解密结果:", str == plainText)
}).catch((error: Error) => {
hilog.error(0x0000, 'AppDataSecurity', `promise: decrypt data failed, ${JSON.stringify(error)}`);
})
}

huks分段加解密,你试下这个呢,我使用先加密,再解密,对比结果,是ok的

在HarmonyOS鸿蒙Next系统中,对于大文件的分段加解密处理,可以通过分段读取和写入数据,结合加密库实现。以下是一个分段加解密的示例:

分段加密

  1. 生成AES对称密钥。
  2. 创建AES加密的Cipher实例,并进行初始化。
  3. 自定义单次传入的数据量,通过多次调用Cipher.update方法传入数据片段进行加密。
  4. 最后调用Cipher.doFinal方法完成加密,并获取认证信息(如果需要)。

分段解密

  1. 创建AES解密的Cipher实例,并使用私钥进行初始化。
  2. 自定义单次传入的数据量,通过多次调用Cipher.doFinal方法传入密文片段进行解密。
  3. 将解密后的数据片段拼接成完整的明文。

示例代码可以参考HarmonyOS的官方文档或开发社区中的相关资源。由于篇幅限制,这里无法给出完整的代码实现。

如果在实际操作中遇到问题,建议查阅HarmonyOS的官方文档或相关开发社区的讨论,以获取更详细的解决方案。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部