• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Encryption and Decryption by Segment with an RSA Asymmetric Key Pair (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
10For details about the algorithm specifications, see [RSA](crypto-asym-encrypt-decrypt-spec.md#rsa).
11
12**Encryption**
13
141. Call [OH_CryptoAsymKeyGenerator_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-key-h.md#oh_cryptoasymkeygenerator_create) and [OH_CryptoAsymKeyGenerator_Generate](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-key-h.md#oh_cryptoasymkeygenerator_generate) to generate an asymmetric key pair (**keyPair**) of the RSA1024 type with two prime numbers. The **keyPair** object includes a public key (**PubKey**) and a private key (**PriKey**).
15
16   For details about how to generate an RSA asymmetric key pair, see the following example. To learn more, see [RSA](crypto-asym-key-generation-conversion-spec.md#rsa) and [Randomly Generating an Asymmetric Key Pair](crypto-generate-asym-key-pair-randomly.md). There may be differences between the input parameters in the reference documents and those in the following example.
17
182. Call [OH_CryptoAsymCipher_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-cipher-h.md#oh_cryptoasymcipher_create) with the string parameter **'RSA1024|PKCS1'** to create a **Cipher** instance for encryption. The key type is **RSA1024**, and the padding mode is **PKCS1**.
19
203. Call [OH_CryptoAsymCipher_Init](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-cipher-h.md#oh_cryptoasymcipher_init) to initialize the **Cipher** instance. Specifically, set **mode** to **CRYPTO_ENCRYPT_MODE**, and specify the key for encryption (**keyPair**).
21
224. Call [OH_CryptoAsymCipher_Final](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-cipher-h.md#oh_cryptoasymcipher_final) for multiple times and pass the plaintext to obtain the encrypted data.
23
24   - The output of **OH_CryptoAsymCipher_Final** may be **NULL**. To avoid exceptions, always check whether the result is **NULL** before accessing specific data.
25
26   - In this example, the plaintext is split by 64 bytes and encrypted multiple times by a 1024-bit key. A 128-byte ciphertext is generated each time.
27   > **NOTE**
28   > Segment-based encryption and decryption of asymmetric keys means that when the plaintext is longer than the data length supported by a single encryption or decryption operation, the data to be encrypted or decrypted needs to be divided into segments of proper length. For details, see [Asymmetric Encryption and Decryption](crypto-encrypt-decrypt-by-segment.md#asymmetric-encryption-and-decryption).
29
30**Decryption**
31
321. If RSA is used, the **Cipher** instance cannot be initialized repeatedly. Call [OH_CryptoAsymCipher_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-cipher-h.md#oh_cryptoasymcipher_create) to create a new **Cipher** instance.
33
342. Call [OH_CryptoAsymCipher_Init](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-cipher-h.md#oh_cryptoasymcipher_init) to initialize the **Cipher** instance. Specifically, set **mode** to **CRYPTO_DECRYPT_MODE**, and specify the key for decryption (**keyPair**).
35
363. Call [OH_CryptoAsymCipher_Final](../../reference/apis-crypto-architecture-kit/capi-crypto-asym-cipher-h.md#oh_cryptoasymcipher_final) for multiple times and pass the ciphertext to obtain the decrypted data.
37
38- Example (using asynchronous APIs):
39
40```C++
41#include "CryptoArchitectureKit/crypto_architecture_kit.h"
42#include <algorithm>
43#include <vector>
44
45static std::vector<uint8_t> doTestRsaEnc(OH_CryptoKeyPair *keyPair, std::vector<uint8_t> &plainText)
46{
47    std::vector<uint8_t> cipherText;
48    OH_CryptoAsymCipher *cipher = nullptr;
49    OH_Crypto_ErrCode ret = OH_CryptoAsymCipher_Create("RSA1024|PKCS1", &cipher);
50    if (ret != CRYPTO_SUCCESS) {
51        return std::vector<uint8_t>{};
52    }
53
54    ret = OH_CryptoAsymCipher_Init(cipher, CRYPTO_ENCRYPT_MODE, keyPair);
55    if (ret != CRYPTO_SUCCESS) {
56        OH_CryptoAsymCipher_Destroy(cipher);
57        return std::vector<uint8_t>{};
58    }
59
60    size_t plainTextSplitLen = 64;
61    for (size_t i = 0; i < plainText.size(); i += plainTextSplitLen) {
62        Crypto_DataBlob in = {};
63        in.data = plainText.data() + i;
64        if (i + plainTextSplitLen > plainText.size()) {
65            in.len = plainText.size() - i;
66        } else {
67            in.len = plainTextSplitLen;
68        }
69        Crypto_DataBlob out = {};
70        ret = OH_CryptoAsymCipher_Final(cipher, &in, &out);
71        if (ret != CRYPTO_SUCCESS) {
72            OH_CryptoAsymCipher_Destroy(cipher);
73            return std::vector<uint8_t>{};
74        }
75        cipherText.insert(cipherText.end(), out.data, out.data + out.len);
76        OH_Crypto_FreeDataBlob(&out);
77    }
78
79    OH_CryptoAsymCipher_Destroy(cipher);
80    return cipherText;
81}
82
83static std::vector<uint8_t> doTestRsaDec(OH_CryptoKeyPair *keyPair, std::vector<uint8_t> &encryptText)
84{
85    std::vector<uint8_t> decryptText;
86    OH_CryptoAsymCipher *cipher = nullptr;
87    OH_Crypto_ErrCode ret = OH_CryptoAsymCipher_Create("RSA1024|PKCS1", &cipher);
88    if (ret != CRYPTO_SUCCESS) {
89        return std::vector<uint8_t>{};
90    }
91
92    ret = OH_CryptoAsymCipher_Init(cipher, CRYPTO_DECRYPT_MODE, keyPair);
93    if (ret != CRYPTO_SUCCESS) {
94        OH_CryptoAsymCipher_Destroy(cipher);
95        return std::vector<uint8_t>{};
96    }
97
98    size_t cipherTextSplitLen = 128; // Length of the ciphertext = Number of key bits/8
99    for (size_t i = 0; i < encryptText.size(); i += cipherTextSplitLen) {
100        Crypto_DataBlob in = {};
101        in.data = encryptText.data() + i;
102        if (i + cipherTextSplitLen > encryptText.size()) {
103            in.len = encryptText.size() - i;
104        } else {
105            in.len = cipherTextSplitLen;
106        }
107        Crypto_DataBlob out = {};
108        ret = OH_CryptoAsymCipher_Final(cipher, &in, &out);
109        if (ret != CRYPTO_SUCCESS) {
110            OH_CryptoAsymCipher_Destroy(cipher);
111            return std::vector<uint8_t>{};
112        }
113        decryptText.insert(decryptText.end(), out.data, out.data + out.len);
114        OH_Crypto_FreeDataBlob(&out);
115    }
116
117    OH_CryptoAsymCipher_Destroy(cipher);
118    return decryptText;
119}
120
121static OH_Crypto_ErrCode doTestRsaEncLongMessage()
122{
123    OH_CryptoAsymKeyGenerator *keyGen = nullptr;
124    OH_Crypto_ErrCode ret = OH_CryptoAsymKeyGenerator_Create("RSA1024", &keyGen);
125    if (ret != CRYPTO_SUCCESS) {
126        return ret;
127    }
128    OH_CryptoKeyPair *keyPair = nullptr;
129    ret = OH_CryptoAsymKeyGenerator_Generate(keyGen, &keyPair);
130    if (ret != CRYPTO_SUCCESS) {
131        OH_CryptoAsymKeyGenerator_Destroy(keyGen);
132        return ret;
133    }
134
135    std::string message =
136        "This is a long plainTest! This is a long plainTest! This is a long plainTest!"
137        "This is a long plainTest! 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
145    std::vector<uint8_t> plainText(message.begin(), message.end());
146    std::vector<uint8_t> cipherText = doTestRsaEnc(keyPair, plainText);
147    std::vector<uint8_t> decryptText = doTestRsaDec(keyPair, cipherText);
148
149    if ((plainText.size() != decryptText.size()) ||
150        (!std::equal(plainText.begin(), plainText.end(), decryptText.begin()))) {
151        OH_CryptoKeyPair_Destroy(keyPair);
152        OH_CryptoAsymKeyGenerator_Destroy(keyGen);
153        return CRYPTO_OPERTION_ERROR;
154    }
155
156    OH_CryptoKeyPair_Destroy(keyPair);
157    OH_CryptoAsymKeyGenerator_Destroy(keyGen);
158    return CRYPTO_SUCCESS;
159}
160```
161