• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 使用RSA非对称密钥分段加解密(C/C++)
2
3<!--Kit: Crypto Architecture Kit-->
4<!--Subsystem: Security-->
5<!--Owner: @zxz--3-->
6<!--Designer: @lanming-->
7<!--Tester: @PAFT-->
8<!--Adviser: @zengyawen-->
9
10对应的算法规格请查看[非对称密钥加解密算法规格:RSA](crypto-asym-encrypt-decrypt-spec.md#rsa)。
11
12**加密**
13
141. 调用[OH_CryptoAsymKeyGenerator_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-key-h.md#oh_cryptoasymkeygenerator_create)、[OH_CryptoAsymKeyGenerator_Generate](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-key-h.md#oh_cryptoasymkeygenerator_generate),生成RSA密钥类型为RSA1024、素数个数为2的非对称密钥对(keyPair)。keyPair对象中包括公钥PubKey、私钥PriKey。
15
16   如何生成RSA非对称密钥对,开发者可参考下文示例,并结合[非对称密钥生成和转换规格:RSA](crypto-asym-key-generation-conversion-spec.md#rsa)和[随机生成非对称密钥对](crypto-generate-asym-key-pair-randomly.md)理解。参考文档与当前示例可能存在入参差异,请在阅读时注意区分。
17
182. 调用[OH_CryptoAsymCipher_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-cipher-h.md#oh_cryptoasymcipher_create),指定字符串参数'RSA1024|PKCS1',创建非对称密钥类型为RSA1024、填充模式为PKCS1的Cipher实例,用于完成加解密操作。
19
203. 调用[OH_CryptoAsymCipher_Init](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-cipher-h.md#oh_cryptoasymcipher_init),设置模式为加密(CRYPTO_ENCRYPT_MODE),指定加密密钥(keyPair),初始化加密Cipher实例。
21
224. 多次调用[OH_CryptoAsymCipher_Final](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-cipher-h.md#oh_cryptoasymcipher_final),传入明文,获取加密后的数据。
23
24   - OH_CryptoAsymCipher_Final输出结果可能为NULL,在访问具体数据前,需要先判断结果是否为NULL,避免产生异常。
25
26   - 此处将明文按64个字节一组拆分,多次加密。使用1024位密钥,每次将生成128字节密文。
27   > **说明:**
28   > 非对称密钥的分段加解密是指当明文大于单次加解密支持的数据长度时,需要将待加解密数据分为合适长度的数据段,并对每个数据段执行加解密操作。详细介绍可见[非对称分段加解密介绍](crypto-encrypt-decrypt-by-segment.md#非对称加解密)。
29
30**解密**
31
321. 由于RSA算法的Cipher实例不支持重复init操作,需要调用[OH_CryptoAsymCipher_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-cipher-h.md#oh_cryptoasymcipher_create),重新生成Cipher实例。
33
342. 调用[OH_CryptoAsymCipher_Init](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-cipher-h.md#oh_cryptoasymcipher_init),设置模式为解密(CRYPTO_DECRYPT_MODE),指定解密密钥(keyPair)初始化解密Cipher实例。
35
363. 多次调用[OH_CryptoAsymCipher_Final](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-cipher-h.md#oh_cryptoasymcipher_final),传入密文,获取解密后的数据。
37
38- 异步方法示例:
39
40```C++
41#include "CryptoArchitectureKit/crypto_architecture_kit.h"
42#include <algorithm>
43#include <vector>
44#include <string>
45
46static std::vector<uint8_t> doTestRsaEnc(OH_CryptoKeyPair *keyPair, std::vector<uint8_t> &plainText)
47{
48    std::vector<uint8_t> cipherText;
49    OH_CryptoAsymCipher *cipher = nullptr;
50    OH_Crypto_ErrCode ret = OH_CryptoAsymCipher_Create("RSA1024|PKCS1", &cipher);
51    if (ret != CRYPTO_SUCCESS) {
52        return std::vector<uint8_t>{};
53    }
54
55    ret = OH_CryptoAsymCipher_Init(cipher, CRYPTO_ENCRYPT_MODE, keyPair);
56    if (ret != CRYPTO_SUCCESS) {
57        OH_CryptoAsymCipher_Destroy(cipher);
58        return std::vector<uint8_t>{};
59    }
60
61    size_t plainTextSplitLen = 64;
62    for (size_t i = 0; i < plainText.size(); i += plainTextSplitLen) {
63        Crypto_DataBlob in = {};
64        in.data = plainText.data() + i;
65        if (i + plainTextSplitLen > plainText.size()) {
66            in.len = plainText.size() - i;
67        } else {
68            in.len = plainTextSplitLen;
69        }
70        Crypto_DataBlob out = {};
71        ret = OH_CryptoAsymCipher_Final(cipher, &in, &out);
72        if (ret != CRYPTO_SUCCESS) {
73            OH_CryptoAsymCipher_Destroy(cipher);
74            return std::vector<uint8_t>{};
75        }
76        cipherText.insert(cipherText.end(), out.data, out.data + out.len);
77        OH_Crypto_FreeDataBlob(&out);
78    }
79
80    OH_CryptoAsymCipher_Destroy(cipher);
81    return cipherText;
82}
83
84static std::vector<uint8_t> doTestRsaDec(OH_CryptoKeyPair *keyPair, std::vector<uint8_t> &encryptText)
85{
86    std::vector<uint8_t> decryptText;
87    OH_CryptoAsymCipher *cipher = nullptr;
88    OH_Crypto_ErrCode ret = OH_CryptoAsymCipher_Create("RSA1024|PKCS1", &cipher);
89    if (ret != CRYPTO_SUCCESS) {
90        return std::vector<uint8_t>{};
91    }
92
93    ret = OH_CryptoAsymCipher_Init(cipher, CRYPTO_DECRYPT_MODE, keyPair);
94    if (ret != CRYPTO_SUCCESS) {
95        OH_CryptoAsymCipher_Destroy(cipher);
96        return std::vector<uint8_t>{};
97    }
98
99    size_t cipherTextSplitLen = 128; // RSA密钥每次加密生成的密文字节长度计算方式:密钥位数/8。
100    for (size_t i = 0; i < encryptText.size(); i += cipherTextSplitLen) {
101        Crypto_DataBlob in = {};
102        in.data = encryptText.data() + i;
103        if (i + cipherTextSplitLen > encryptText.size()) {
104            in.len = encryptText.size() - i;
105        } else {
106            in.len = cipherTextSplitLen;
107        }
108        Crypto_DataBlob out = {};
109        ret = OH_CryptoAsymCipher_Final(cipher, &in, &out);
110        if (ret != CRYPTO_SUCCESS) {
111            OH_CryptoAsymCipher_Destroy(cipher);
112            return std::vector<uint8_t>{};
113        }
114        decryptText.insert(decryptText.end(), out.data, out.data + out.len);
115        OH_Crypto_FreeDataBlob(&out);
116    }
117
118    OH_CryptoAsymCipher_Destroy(cipher);
119    return decryptText;
120}
121
122static OH_Crypto_ErrCode doTestRsaEncLongMessage()
123{
124    OH_CryptoAsymKeyGenerator *keyGen = nullptr;
125    OH_Crypto_ErrCode ret = OH_CryptoAsymKeyGenerator_Create("RSA1024", &keyGen);
126    if (ret != CRYPTO_SUCCESS) {
127        return ret;
128    }
129    OH_CryptoKeyPair *keyPair = nullptr;
130    ret = OH_CryptoAsymKeyGenerator_Generate(keyGen, &keyPair);
131    if (ret != CRYPTO_SUCCESS) {
132        OH_CryptoAsymKeyGenerator_Destroy(keyGen);
133        return ret;
134    }
135
136    std::string message =
137        "This is a long plainTest! This is a long plainTest! This is a long plainTest!"
138        "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!"
139        "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!"
140        "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!"
141        "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!"
142        "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!"
143        "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!"
144        "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!";
145
146    std::vector<uint8_t> plainText(message.begin(), message.end());
147    std::vector<uint8_t> cipherText = doTestRsaEnc(keyPair, plainText);
148    std::vector<uint8_t> decryptText = doTestRsaDec(keyPair, cipherText);
149
150    if ((plainText.size() != decryptText.size()) ||
151        (!std::equal(plainText.begin(), plainText.end(), decryptText.begin()))) {
152        OH_CryptoKeyPair_Destroy(keyPair);
153        OH_CryptoAsymKeyGenerator_Destroy(keyGen);
154        return CRYPTO_OPERTION_ERROR;
155    }
156
157    OH_CryptoKeyPair_Destroy(keyPair);
158    OH_CryptoAsymKeyGenerator_Destroy(keyGen);
159    return CRYPTO_SUCCESS;
160}
161```