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