文档管理中心
开发与测试开放能力API系统安全Crypto Architecture Kit(加解密算法框架服务)加解密介绍使用ECIES混合加解密(C/C++)

使用ECIES混合加解密(C/C++)

从API版本26.0.0开始,支持ECIES算法,ECIES是一种基于椭圆曲线密码学的加密算法。

约束条件:

  • 密钥协商算法支持ECC256、ECC384、ECC521。
  • 密钥派生算法仅支持X963KDF,摘要算法支持SHA1、SHA256、SHA384、SHA512。
  • 对称加密算法支持AES128、AES192、AES256。
  • 分组模式仅支持GCM。

在CMake脚本中链接相关动态库

收起
自动换行
深色代码主题
复制
  1. target_link_libraries(entry PUBLIC libohcrypto.so)

开发步骤

加密

  1. 调用OH_CryptoAsymKeyGenerator_CreateOH_CryptoAsymKeyGenerator_Generate,使用ECC算法生成密钥对。

  2. 调用OH_CryptoKeyAgreement_CreateOH_CryptoKeyAgreement_GenerateSecret,基于本端的私钥(KeyPair.priKey)与对端的公钥(KeyPair.pubKey)进行密钥协商,返回共享密钥。

  3. X963KDF密钥派生,调用OH_CryptoKdf_CreateOH_CryptoKdf_Derive,基于协商的共享密钥(Secret)进行密钥派生,返回派生后的密钥。

  4. 调用OH_CryptoSymCipher_Create,指定字符串参数'AES128|GCM',创建对称密钥类型为AES128、分组模式为GCM的Cipher实例,用于完成加密操作。

  5. 调用OH_CryptoSymCipher_Init,设置模式为加密(CRYPTO_ENCRYPT_MODE),指定加密密钥(OH_CryptoSymKey),初始化加密Cipher实例。

  6. 调用OH_CryptoSymCipher_Update,更新数据(明文),获取加密后的数据。

  7. 调用OH_CryptoSymCipher_Final,获取authTag。

    说明

    在GCM模式下,一次加密流程中,将每次update和最后final的结果拼接起来,会得到“密文 + authTag”,authTag为末尾的16字节。其余部分均为密文。如果final的data参数传入null,则final的结果就是authTag。

解密

  1. 调用OH_CryptoAsymKeyGenerator_CreateOH_CryptoAsymKeyGenerator_Generate,使用ECC算法生成密钥对。

  2. 调用OH_CryptoKeyAgreement_CreateOH_CryptoKeyAgreement_GenerateSecret,基于本端的私钥(KeyPair.priKey)与对端的公钥(KeyPair.pubKey)进行密钥协商,返回共享密钥。

  3. X963KDF密钥派生,调用OH_CryptoKdf_CreateOH_CryptoKdf_Derive,基于协商的共享密钥(Secret)进行密钥派生,返回派生后的密钥。

  4. 调用OH_CryptoSymCipher_Create,指定字符串参数'AES128|GCM',创建对称密钥类型为AES128、分组模式为GCM的Cipher实例,用于完成解密操作。

  5. 调用OH_CryptoSymCipher_Init,设置模式为解密(CRYPTO_DECRYPT_MODE),指定解密密钥(OH_CryptoSymKey),初始化解密Cipher实例。

  6. 调用OH_CryptoSymCipher_Update,更新数据(密文)。

  7. 调用OH_CryptoSymCipher_Final,获取解密数据。

示例代码

收起
自动换行
深色代码主题
复制
  1. #include <cstring>
  2. #include <hilog/log.h>
  3. #include "CryptoArchitectureKit/crypto_architecture_kit.h"
  4. #include "native_test.h"
  5. namespace ECIES {
  6. uint8_t aad[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
  7. uint8_t tag[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
  8. const uint8_t ivSize = 16;
  9. const uint8_t keySize = 16;
  10. struct CryptoContext {
  11. OH_CryptoKeyPair *keyPair;
  12. OH_CryptoSymKey *symKey;
  13. Crypto_DataBlob secret;
  14. Crypto_DataBlob ivData; // secret的前16字节作为IV,浅拷贝
  15. };
  16. OH_Crypto_ErrCode GenerateKeyPair(OH_CryptoKeyPair **keyPair)
  17. {
  18. OH_CryptoAsymKeyGenerator *asyKeyGenerator = nullptr;
  19. OH_Crypto_ErrCode ret = OH_CryptoAsymKeyGenerator_Create("ECC256", &asyKeyGenerator);
  20. if (ret != CRYPTO_SUCCESS) {
  21. return ret;
  22. }
  23. ret = OH_CryptoAsymKeyGenerator_Generate(asyKeyGenerator, keyPair);
  24. OH_CryptoAsymKeyGenerator_Destroy(asyKeyGenerator);
  25. return ret;
  26. }
  27. OH_Crypto_ErrCode GenerateSecret(OH_CryptoPrivKey *privKey, OH_CryptoPubKey *pubKey, Crypto_DataBlob *secret)
  28. {
  29. // EC密钥协商
  30. OH_CryptoKeyAgreement *keyAgreement = nullptr;
  31. OH_Crypto_ErrCode ret = OH_CryptoKeyAgreement_Create("ECC256", &keyAgreement);
  32. if (ret != CRYPTO_SUCCESS) {
  33. return ret;
  34. }
  35. ret = OH_CryptoKeyAgreement_GenerateSecret(keyAgreement, privKey, pubKey, secret);
  36. OH_CryptoKeyAgreement_Destroy(keyAgreement);
  37. return ret;
  38. }
  39. OH_Crypto_ErrCode KdfDeriveSecret(OH_CryptoPrivKey *privKey, OH_CryptoPubKey *pubKey, Crypto_DataBlob *secret)
  40. {
  41. // 使用X963KDF进行密钥派生
  42. OH_CryptoKdfParams *params = nullptr;
  43. OH_Crypto_ErrCode ret = OH_CryptoKdfParams_Create("X963KDF", &params);
  44. if (ret != CRYPTO_SUCCESS) {
  45. return ret;
  46. }
  47. Crypto_DataBlob keyData = {};
  48. ret = GenerateSecret(privKey, pubKey, &keyData);
  49. if (ret != CRYPTO_SUCCESS) {
  50. OH_CryptoKdfParams_Destroy(params);
  51. return ret;
  52. }
  53. ret = OH_CryptoKdfParams_SetParam(params, CRYPTO_KDF_KEY_DATABLOB, &keyData);
  54. OH_Crypto_FreeDataBlob(&keyData);
  55. if (ret != CRYPTO_SUCCESS) {
  56. OH_CryptoKdfParams_Destroy(params);
  57. return ret;
  58. }
  59. const char *info = "infostring";
  60. Crypto_DataBlob infoData = { .data = (uint8_t *)info, .len = strlen(info) };
  61. ret = OH_CryptoKdfParams_SetParam(params, CRYPTO_KDF_INFO_DATABLOB, &infoData);
  62. if (ret != CRYPTO_SUCCESS) {
  63. OH_CryptoKdfParams_Destroy(params);
  64. return ret;
  65. }
  66. OH_CryptoKdf *x963Kdf = nullptr;
  67. ret = OH_CryptoKdf_Create("X963KDF|SHA256", &x963Kdf);
  68. if (ret != CRYPTO_SUCCESS) {
  69. OH_CryptoKdfParams_Destroy(params);
  70. return ret;
  71. }
  72. ret = OH_CryptoKdf_Derive(x963Kdf, params, ivSize + keySize, secret);
  73. OH_CryptoKdf_Destroy(x963Kdf);
  74. OH_CryptoKdfParams_Destroy(params);
  75. return ret;
  76. }
  77. OH_Crypto_ErrCode GenerateSymKey(const Crypto_DataBlob *secret, OH_CryptoSymKey **symKey)
  78. {
  79. OH_CryptoSymKeyGenerator *symKeyGenerator = nullptr;
  80. OH_Crypto_ErrCode ret = OH_CryptoSymKeyGenerator_Create("AES128", &symKeyGenerator);
  81. if (ret != CRYPTO_SUCCESS) {
  82. return ret;
  83. }
  84. Crypto_DataBlob keyData = { .data = secret->data + ivSize, .len = keySize };
  85. ret = OH_CryptoSymKeyGenerator_Convert(symKeyGenerator, &keyData, symKey);
  86. OH_CryptoSymKeyGenerator_Destroy(symKeyGenerator);
  87. return ret;
  88. }
  89. void SetCipherIvData(CryptoContext *ctx, Crypto_DataBlob *secret)
  90. {
  91. ctx->ivData.data = secret->data;
  92. ctx->ivData.len = ivSize;
  93. }
  94. OH_Crypto_ErrCode SetCipherParams(OH_CryptoSymCipherParams *params, Crypto_DataBlob *ivBlob, Crypto_DataBlob *tagBlob)
  95. {
  96. Crypto_DataBlob aadBlob = { .data = aad, .len = sizeof(aad) };
  97. OH_Crypto_ErrCode ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_AAD_DATABLOB, &aadBlob);
  98. if (ret != CRYPTO_SUCCESS) {
  99. return ret;
  100. }
  101. ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_IV_DATABLOB, ivBlob);
  102. if (ret != CRYPTO_SUCCESS) {
  103. return ret;
  104. }
  105. ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_TAG_DATABLOB, tagBlob);
  106. return ret;
  107. }
  108. OH_Crypto_ErrCode Encrypt(CryptoContext *ctx, Crypto_DataBlob *plainText, Crypto_DataBlob *cipherText,
  109. Crypto_DataBlob *tagBlob)
  110. {
  111. // AES-GCM对称加密
  112. OH_CryptoSymCipherParams *params = nullptr;
  113. OH_Crypto_ErrCode ret = OH_CryptoSymCipherParams_Create(&params);
  114. if (ret != CRYPTO_SUCCESS) {
  115. return ret;
  116. }
  117. Crypto_DataBlob tagInit = { .data = tag, .len = sizeof(tag) };
  118. ret = SetCipherParams(params, &ctx->ivData, &tagInit);
  119. if (ret != CRYPTO_SUCCESS) {
  120. OH_CryptoSymCipherParams_Destroy(params);
  121. return ret;
  122. }
  123. OH_CryptoSymCipher *encCtx = nullptr;
  124. ret = OH_CryptoSymCipher_Create("AES128|GCM", &encCtx);
  125. if (ret != CRYPTO_SUCCESS) {
  126. OH_CryptoSymCipherParams_Destroy(params);
  127. return ret;
  128. }
  129. ret = OH_CryptoSymCipher_Init(encCtx, CRYPTO_ENCRYPT_MODE, ctx->symKey, params);
  130. OH_CryptoSymCipherParams_Destroy(params);
  131. if (ret != CRYPTO_SUCCESS) {
  132. OH_CryptoSymCipher_Destroy(encCtx);
  133. return ret;
  134. }
  135. ret = OH_CryptoSymCipher_Update(encCtx, plainText, cipherText);
  136. if (ret != CRYPTO_SUCCESS) {
  137. OH_CryptoSymCipher_Destroy(encCtx);
  138. return ret;
  139. }
  140. ret = OH_CryptoSymCipher_Final(encCtx, nullptr, tagBlob);
  141. OH_CryptoSymCipher_Destroy(encCtx);
  142. return ret;
  143. }
  144. OH_Crypto_ErrCode Decrypt(CryptoContext *ctx, Crypto_DataBlob *cipherText, Crypto_DataBlob *plainText,
  145. Crypto_DataBlob *tagBlob)
  146. {
  147. // AES-GCM对称解密
  148. OH_CryptoSymCipherParams *params = nullptr;
  149. OH_Crypto_ErrCode ret = OH_CryptoSymCipherParams_Create(&params);
  150. if (ret != CRYPTO_SUCCESS) {
  151. return ret;
  152. }
  153. ret = SetCipherParams(params, &ctx->ivData, tagBlob);
  154. if (ret != CRYPTO_SUCCESS) {
  155. OH_CryptoSymCipherParams_Destroy(params);
  156. return ret;
  157. }
  158. OH_CryptoSymCipher *decCtx = nullptr;
  159. ret = OH_CryptoSymCipher_Create("AES128|GCM", &decCtx);
  160. if (ret != CRYPTO_SUCCESS) {
  161. OH_CryptoSymCipherParams_Destroy(params);
  162. return ret;
  163. }
  164. ret = OH_CryptoSymCipher_Init(decCtx, CRYPTO_DECRYPT_MODE, ctx->symKey, params);
  165. if (ret != CRYPTO_SUCCESS) {
  166. OH_CryptoSymCipher_Destroy(decCtx);
  167. OH_CryptoSymCipherParams_Destroy(params);
  168. return ret;
  169. }
  170. ret = OH_CryptoSymCipher_Final(decCtx, cipherText, plainText);
  171. OH_CryptoSymCipher_Destroy(decCtx);
  172. OH_CryptoSymCipherParams_Destroy(params);
  173. return ret;
  174. }
  175. void CleanupDataBlob(Crypto_DataBlob *plainData, Crypto_DataBlob *cipherData, Crypto_DataBlob *tagBlob)
  176. {
  177. OH_Crypto_FreeDataBlob(plainData);
  178. OH_Crypto_FreeDataBlob(cipherData);
  179. OH_Crypto_FreeDataBlob(tagBlob);
  180. }
  181. void CleanupContext(CryptoContext *ctx)
  182. {
  183. OH_Crypto_FreeDataBlob(&ctx->secret);
  184. OH_CryptoSymKey_Destroy(ctx->symKey);
  185. OH_CryptoKeyPair_Destroy(ctx->keyPair);
  186. }
  187. } // namespace ECIES
  188. OH_Crypto_ErrCode doNativeTest()
  189. {
  190. ECIES::CryptoContext ctxA = {};
  191. ECIES::CryptoContext ctxB = {};
  192. Crypto_DataBlob plainData = {};
  193. Crypto_DataBlob cipherData = {};
  194. Crypto_DataBlob tagBlob = {};
  195. OH_Crypto_ErrCode ret = CRYPTO_INVALID_PARAMS;
  196. do {
  197. ret = ECIES::GenerateKeyPair(&ctxA.keyPair);
  198. if (ret != CRYPTO_SUCCESS) {
  199. break;
  200. }
  201. ret = ECIES::GenerateKeyPair(&ctxB.keyPair);
  202. if (ret != CRYPTO_SUCCESS) {
  203. break;
  204. }
  205. // A端密钥协商:A端的私钥 + B端的公钥
  206. ret = ECIES::KdfDeriveSecret(OH_CryptoKeyPair_GetPrivKey(ctxA.keyPair),
  207. OH_CryptoKeyPair_GetPubKey(ctxB.keyPair), &ctxA.secret);
  208. if (ret != CRYPTO_SUCCESS) {
  209. break;
  210. }
  211. ret = ECIES::GenerateSymKey(&ctxA.secret, &ctxA.symKey);
  212. if (ret != CRYPTO_SUCCESS) {
  213. break;
  214. }
  215. // 使用A端派生密钥的前16字节作为加解密端的IV
  216. ECIES::SetCipherIvData(&ctxA, &ctxA.secret);
  217. ECIES::SetCipherIvData(&ctxB, &ctxA.secret);
  218. // A端加密
  219. uint8_t message[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B };
  220. Crypto_DataBlob plainText = { .data = message, .len = sizeof(message) };
  221. ret = ECIES::Encrypt(&ctxA, &plainText, &cipherData, &tagBlob);
  222. if (ret != CRYPTO_SUCCESS) {
  223. break;
  224. }
  225. // B端密钥协商:B端的私钥 + A端的公钥
  226. ret = ECIES::KdfDeriveSecret(OH_CryptoKeyPair_GetPrivKey(ctxB.keyPair),
  227. OH_CryptoKeyPair_GetPubKey(ctxA.keyPair), &ctxB.secret);
  228. if (ret != CRYPTO_SUCCESS) {
  229. break;
  230. }
  231. ret = ECIES::GenerateSymKey(&ctxB.secret, &ctxB.symKey);
  232. if (ret != CRYPTO_SUCCESS) {
  233. break;
  234. }
  235. // B端解密
  236. ret = ECIES::Decrypt(&ctxB, &cipherData, &plainData, &tagBlob);
  237. } while (0);
  238. ECIES::CleanupDataBlob(&plainData, &cipherData, &tagBlob);
  239. ECIES::CleanupContext(&ctxA);
  240. ECIES::CleanupContext(&ctxB);
  241. OH_LOG_INFO(LOG_APP, "doNativeTest result: %{public}s", (ret == 0 ? "Success" : "Failed"));
  242. return ret;
  243. }
在 开发与测试 开放能力API 中进行搜索
请输入您想要搜索的关键词