HarmonyOS Next 对称密钥生成全攻略:从原理到实践
本文旨在深入探讨华为鸿蒙HarmonyOS Next系统(截止目前API12)的技术细节,基于实际开发实践进行总结。
主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。
本文为原创内容,任何形式的转载必须注明出处及原作者。
一、引言
在数据安全的浩瀚领域中,对称密钥犹如一把坚固的锁,守护着我们宝贵的信息资产。它的重要性怎么强调都不为过,无论是个人隐私数据的加密存储,还是企业敏感信息在网络中的传输,对称密钥都扮演着关键角色。通过使用对称密钥进行加密,只有拥有相同密钥的授权方才能解密并获取原始数据,从而有效地防止数据被未授权访问和窃取。在各种加密技术中,对称密钥以其加密和解密速度快的优势,成为处理大量数据加密任务的首选,如文件加密、数据库加密以及实时通信中的数据加密等场景。接下来,我们将深入探讨 HarmonyOS Next 中对称密钥的生成和转换,从原理到实践全方位剖析这一重要技术。
二、对称密钥生成和转换规格
(一)AES、3DES、SM4 等算法的特点与适用场景
- AES 算法
- AES(Advanced Encryption Standard)作为当今最为常用的对称加密算法之一,具有诸多显著特点。它是一种分组密码算法,分组长度固定为 128 位,密钥长度则可灵活选择 128 位、192 位或 256 位。与 3DES 相比,AES 展现出更高的安全性,这得益于其更为先进的加密算法结构。同时,AES 的处理速度更快,能够高效地处理大量数据加密任务。在实际应用中,AES 广泛应用于各种对安全性和性能要求较高的场景,如在线支付系统中对用户银行卡信息的加密存储、云计算环境下的数据中心数据加密等。 - 3DES 算法
- 3DES(Triple Data Encryption Algorithm),也称为 3DESede 或 TripleDES,其加密原理是使用 3 个 64 位的密钥对数据块进行三次加密,相当于对每个数据块执行三次 DES(Data Encryption Standard)加密算法。这种加密方式使得 3DES 的密钥长度更长,从而提供了比 DES 更高的安全性。然而,相对而言,其处理速度不如 AES 快。3DES 适用于一些对安全性有一定要求,但对性能要求不是特别苛刻的场景,例如某些企业内部网络中的数据加密传输,在硬件资源有限且 AES 支持不完全的情况下,3DES 可以作为一种过渡性的加密解决方案。 - SM4 算法
- SM4 是我国自主研发的分组密码算法,分组长度同样为 128 位,密钥长度为 128 位,并且可通过扩展密钥增加密钥长度。SM4 的加密算法与密钥扩展算法都采用 32 轮非线性迭代结构,其独特之处在于数据解密和数据加密的算法结构相同,只是轮密钥的使用顺序相反,解密轮密钥是加密轮密钥的逆序。SM4 在国内的一些安全敏感领域得到了广泛应用,如政府部门的数据加密、国内金融机构的部分业务加密等,以保障国家信息安全和关键基础设施的安全。
(二)字符串参数承载密钥规格的方式及示例
在 HarmonyOS Next 中,通过特定的字符串参数来承载密钥规格,从而方便地生成对应的密钥。以 AES 算法为例,其字符串参数由“对称密钥算法”和“密钥长度”拼接而成。具体来说,当要生成 128 位的 AES 密钥时,对应的字符串参数为“AES128”;生成 192 位密钥时,字符串参数为“AES192”;生成 256 位密钥时,字符串参数为“AES256”。这种简洁而明确的方式使得开发者能够直观地指定所需的密钥规格。同样,对于 3DES 算法,其字符串参数为“3DES192”(表示密钥长度为 192 位);SM4 算法的字符串参数为“SM4_128”(表示密钥长度为 128 位)。通过这些字符串参数,开发者可以在创建对称密钥生成器时,准确地指定所需的密钥规格,为后续的加密操作奠定基础。
三、随机生成对称密钥(ArkTS 与 C/C++ 示例)
(一)ArkTS 代码实现步骤与解释
- 首先,导入必要的模块:
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
这里的 cryptoFramework
是 HarmonyOS Next 提供的加解密算法框架模块,通过导入它,我们可以使用其中的各种加密相关功能。
2. 然后,创建对称密钥生成器:
let symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256');
在这一步中,我们使用 createSymKeyGenerator
函数并传入字符串参数“AES256”,表示我们要创建一个密钥算法为 AES、密钥长度为 256 位的对称密钥生成器。这一步是根据我们之前提到的字符串参数承载密钥规格的方式来指定所需的密钥类型。
3. 接下来,生成对称密钥:
let promiseSymKey = symKeyGenerator.generateSymKey();
调用生成器的 generateSymKey
方法来随机生成对称密钥。这个方法返回一个 Promise 对象,因为密钥生成可能需要一定的时间,特别是对于较长密钥长度的情况。
4. 最后,获取密钥的二进制数据并处理结果:
promiseSymKey.then(key => {
let encodedKey = key.getEncoded();
console.info('key hex:' + encodedKey.data);
});
当密钥生成成功后,通过 Promise 的 then
方法获取生成的密钥对象,并调用 getEncoded
方法获取密钥的二进制数据。这里将二进制数据转换为十六进制字符串并输出,以便开发者查看和使用生成的密钥。
(二)C/C++ 代码实现步骤与解释(包括 CMake 脚本配置)
- CMake 脚本配置
- 在 C/C++ 项目中使用 HarmonyOS Next 的加密功能,需要在 CMake 脚本中正确链接相关动态库。在 CMakeLists.txt 文件中添加以下代码:
target_link_libraries(entry PUBLIC libohcrypto.so)
这行代码的作用是将 libohcrypto.so
动态库链接到项目中,使得项目能够使用其中的加密函数和功能。
2. 代码实现
- 首先,包含必要的头文件:
#include "CryptoArchitectureKit/crypto_common.h"
#include "CryptoArchitectureKit/crypto_sym_key.h"
这些头文件提供了使用对称密钥生成功能所需的函数声明和数据结构定义。
- 然后,创建对称密钥生成器并生成密钥:
OH_CryptoSymKeyGenerator *ctx = nullptr;
OH_CryptoSymKey *keyCtx = nullptr;
Crypto_DataBlob out = {.data = nullptr,.len = 0};
OH_Crypto_ErrCode ret = OH_CryptoSymKeyGenerator_Create("AES256", &ctx);
if (ret!= CRYPTO_SUCCESS) {
return ret;
}
ret = OH_CryptoSymKeyGenerator_Generate(ctx, &keyCtx);
if (ret!= CRYPTO_SUCCESS) {
OH_CryptoSymKeyGenerator_Destroy(ctx);
return ret;
}
这里首先创建一个 OH_CryptoSymKeyGenerator
类型的指针 ctx
来表示对称密钥生成器上下文,以及一个 OH_CryptoSymKey
类型的指针 keyCtx
来存储生成的密钥。然后使用 OH_CryptoSymKeyGenerator_Create
函数创建一个 AES256 密钥生成器,传入字符串参数“AES256”来指定密钥规格。如果创建成功,接着使用 OH_CryptoSymKeyGenerator_Generate
函数生成对称密钥。在整个过程中,通过检查返回的错误码 ret
来确保操作的正确性,如果出现错误,及时释放已分配的资源。
- 最后,获取密钥的二进制数据并释放资源:
ret = OH_CryptoSymKey_GetKeyData(keyCtx, &out);
OH_CryptoSymKeyGenerator_Destroy(ctx);
OH_CryptoSymKey_Destroy(keyCtx);
if (ret!= CRYPTO_SUCCESS) {
return ret;
}
OH_Crypto_FreeDataBlob(&out);
return ret;
使用 OH_CryptoSymKey_GetKeyData
函数获取生成密钥的二进制数据,并存储在 out
结构体中。然后依次销毁密钥生成器上下文和密钥对象,释放相关资源。最后,使用 OH_Crypto_FreeDataBlob
函数释放存储二进制数据的结构体所占用的内存。
四、指定二进制数据转换对称密钥(ArkTS 与 C/C++ 示例)
(一)转换流程与代码示例分析(ArkTS)
- 首先,获取指定的对称密钥二进制数据并封装成
DataBlob
对象:
function genKeyMaterialBlob(): cryptoFramework.DataBlob {
let arr = [
0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c,
0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // 密钥长度为192位,即24字节。
let keyMaterial = new Uint8Array(arr);
return { data: keyMaterial };
}
这里定义了一个函数 genKeyMaterialBlob
,用于创建一个包含特定二进制数据的 DataBlob
对象,模拟了从外部获取或存储的对称密钥二进制数据。
2. 接着,创建对称密钥生成器并进行转换:
let symKeyGenerator = cryptoFramework.createSymKeyGenerator('3DES192');
let keyMaterialBlob = genKeyMaterialBlob();
try {
symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => {
if (error) {
let e: BusinessError = error as BusinessError;
console.error(`convertKey error, ${e.code}, ${e.message}`);
return;
}
console.info('key algName:' + key.algName);
console.info('key format:' + key.format);
let encodedKey = key.getEncoded();
console.info('key getEncoded hex: ' + encodedKey.data);
});
} catch (error) {
let e: BusinessError = error as BusinessError;
console.error(`convertKey failed, ${e.code}, ${e.message}`);
}
首先创建一个密钥算法为3DES、密钥长度为192位的对称密钥生成器。然后使用 convertKey
方法,传入之前创建的 DataBlob
对象,尝试将二进制数据转换为对称密钥。如果转换成功,在回调函数中获取生成的密钥对象,输出其算法名称、格式以及二进制数据(以十六进制字符串形式)。如果转换过程中出现错误,通过捕获异常并输出错误信息。
(二)转换流程与代码示例分析(C/C++)
- 同样,先准备好二进制数据并封装成
Crypto_DataBlob
结构:
#include "CryptoArchitectureKit/crypto_common.h"
#include "CryptoArchitectureKit/crypto_sym_key.h"
#include <string.h>
static OH_Crypto_ErrCode testConvertHmacKey() {
const char *algName = "HMAC";
OH_CryptoSymKeyGenerator *ctx = nullptr;
OH_CryptoSymKey *convertKeyCtx = nullptr;
Crypto_DataBlob out = {.data = nullptr,.len = 0};
OH_Crypto_ErrCode ret;
char *arr = const_cast<char *>("12345678abcdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh");
Crypto_DataBlob convertBlob = {.data = (uint8_t *)(arr),.len = strlen(arr)};
这里定义了一个函数 testConvertHmacKey
,创建了一个包含特定字符串(模拟二进制数据)的 Crypto_DataBlob
结构,用于后续的转换操作。
2. 然后,创建对称密钥生成器并进行转换:
ret = OH_CryptoSymKeyGenerator_Create(algName, &ctx);
if (ret!= CRYPTO_SUCCESS) {
return ret;
}
ret = OH_CryptoSymKeyGenerator_Convert(ctx, &convertBlob, &convertKeyCtx);
if (ret!= CRYPTO_SUCCESS) {
OH_CryptoSymKeyGenerator_Destroy(ctx);
return ret;
}
使用 OH_CryptoSymKeyGenerator_Create
函数创建一个HMAC密钥生成器(这里以HMAC为例,其他对称密钥算法类似),传入算法名称字符串。然后使用 OH_CryptoSymKeyGenerator_Convert
函数,传入准备好的二进制数据 convertBlob
,尝试将其转换为对称密钥。如果转换成功,继续后续操作;如果转换失败,及时销毁已创建的密钥生成器上下文并返回错误码。
3. 最后,获取转换后的密钥二进制数据并释放资源:
ret = OH_CryptoSymKey_GetKeyData(convertKeyCtx, &out);
OH_CryptoSymKeyGenerator_Destroy(ctx);
OH_CryptoSymKey_Destroy(convertKeyCtx);
if (ret!= CRYPTO_SUCCESS) {
return ret;
}
OH_Crypto_FreeDataBlob(&out);
return ret;
使用 OH_CryptoSymKey_GetKeyData
函数获取转换后密钥的二进制数据,并存储在 out
结构体中。然后依次销毁密钥生成器上下文和密钥对象,释放相关资源。最后,使用 OH_Crypto_FreeDataBlob
函数释放存储二进制数据的结构体所占用的内存。
五、总结
在本次对 HarmonyOS Next 对称密钥生成的深入探索中,我们详细了解了多种生成和转换对称密钥的方式。通过对 AES、3DES、SM4 等算法特点和适用场景的分析,我们能够根据实际需求选择最合适的算法。在随机生成对称密钥方面,ArkTS 和 C/C++ 两种实现方式各有特点,ArkTS 借助 Promise 实现了异步操作,方便在复杂应用中管理密钥生成过程,而 C/C++ 则通过传统的函数调用和错误码处理方式提供了高效的性能。在指定二进制数据转换对称密钥时,同样的两种语言实现都清晰地展示了转换流程,从数据准备、生成器创建到转换操作和结果处理。
对于选择何种生成和转换方式,我们开发者需要综合考虑多个因素。如果应用是基于 ArkTS 开发且注重异步操作和简洁的代码结构,那么 ArkTS 的相关方法会是不错的选择;而如果对性能有较高要求且熟悉 C/C++ 编程,C/C++ 实现则更能发挥其优势。同时,还需考虑密钥的使用场景、系统资源以及与其他组件的兼容性等因素,以上。