1# Encryption and Decryption by Segment with an RSA Asymmetric Key Pair
2
3
4For details about the algorithm specifications, see [RSA](crypto-asym-encrypt-decrypt-spec.md#rsa).
5
6
7**Encryption**
8
9
101. Use [cryptoFramework.createAsyKeyGenerator](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreateasykeygenerator) and [AsyKeyGenerator.generateKeyPair](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#generatekeypair-1) to generate a 1024-bit RSA asymmetric key pair (**KeyPair**) with two primes. The number of primes is not specified by default. The **KeyPair** object includes a public key (**PubKey**) and a private key (**PriKey**).
11
12   In addition to the example in this topic, [RSA](crypto-asym-key-generation-conversion-spec.md#rsa) and [Randomly Generating an Asymmetric Key Pair](crypto-generate-asym-key-pair-randomly.md) may help you better understand how to generate an RSA asymmetric key pair. Note that the input parameters in the reference documents may be different from those in the example below.
13
142. Use [cryptoFramework.createCipher](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatecipher) with the string parameter **'RSA1024|PKCS1'** to create a **Cipher** instance for encryption. The key type is **RSA1024**, and the padding mode is **PKCS1**.
15
163. Use [Cipher.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-1) to initialize the **Cipher** instance. In **Cipher.init**, set **opMode** to **CryptoMode.ENCRYPT_MODE** (encryption) and **key** to **KeyPair.PubKey** (the key used for encryption).
17
184. Call [Cipher.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-1) multiple times to pass in the plaintext and encrypt it by segment.
19
20   The output of **doFinal** may be **null**. To avoid exceptions, always check whether the result is **null** before accessing specific data.
21
22   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.
23
24
25**Decryption**
26
27
281. If RSA is used, the **Cipher** instance cannot be initialized repeatedly. Use [cryptoFramework.createCipher](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatecipher) to create a new **Cipher** instance.
29
302. Use [Cipher.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-1) to initialize the **Cipher** instance. In **Cipher.init**, set **opMode** to **CryptoMode.DECRYPT_MODE** (decryption) and **key** to **KeyPair.PriKey** (the key used for decryption). When PKCS1 mode is used, pass in **null** in **params**.
31
323. Call [Cipher.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-1) multiple times to pass in the ciphertext and decrypt it by segment.
33
34
35- Example (using asynchronous APIs):
36
37  ```ts
38  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
39  import { buffer } from '@kit.ArkTS';
40  // Encrypt the message by segment.
41  async function rsaEncryptBySegment(pubKey: cryptoFramework.PubKey, plainText: cryptoFramework.DataBlob) {
42    let cipher = cryptoFramework.createCipher('RSA1024|PKCS1');
43    await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null);
44    let plainTextSplitLen = 64;
45    let cipherText = new Uint8Array();
46    for (let i = 0; i < plainText.data.length; i += plainTextSplitLen ) {
47      let updateMessage = plainText.data.subarray(i, i + plainTextSplitLen );
48      let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
49      // Split the plaintext by 64 bytes and cyclically call doFinal() to encrypt the plaintext using a 1024-bit key. A 128-byte ciphertext is generated each time.
50      let updateOutput = await cipher.doFinal(updateMessageBlob);
51      let mergeText = new Uint8Array(cipherText.length + updateOutput.data.length);
52      mergeText.set(cipherText);
53      mergeText.set(updateOutput.data, cipherText.length);
54      cipherText = mergeText;
55    }
56    let cipherBlob: cryptoFramework.DataBlob = { data: cipherText };
57    return cipherBlob;
58  }
59  // Decrypt the message by segment.
60  async function rsaDecryptBySegment(priKey: cryptoFramework.PriKey, cipherText: cryptoFramework.DataBlob) {
61    let decoder = cryptoFramework.createCipher('RSA1024|PKCS1');
62    await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, priKey, null);
63    let cipherTextSplitLen = 128; // Length of the ciphertext = Number of key bits/8
64    let decryptText = new Uint8Array();
65    for (let i = 0; i < cipherText.data.length; i += cipherTextSplitLen) {
66      let updateMessage = cipherText.data.subarray(i, i + cipherTextSplitLen);
67      let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
68      // Split the ciphertext by 128 bytes, decrypt the ciphertext, and combine the plaintext obtained each time.
69      let updateOutput = await decoder.doFinal(updateMessageBlob);
70      let mergeText = new Uint8Array(decryptText.length + updateOutput.data.length);
71      mergeText.set(decryptText);
72      mergeText.set(updateOutput.data, decryptText.length);
73      decryptText = mergeText;
74    }
75    let decryptBlob: cryptoFramework.DataBlob = { data: decryptText };
76    return decryptBlob;
77  }
78  async function rsaEncryptLongMessage() {
79    let message = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
80      "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
81      "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
82      "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
83      "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
84      "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
85      "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
86      "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!";
87    let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024");  // Create an AsyKeyGenerator object.
88    let keyPair = await asyKeyGenerator.generateKeyPair(); // Randomly generate an RSA key pair.
89    let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) };
90    let encryptText = await rsaEncryptBySegment(keyPair.pubKey, plainText);
91    let decryptText = await rsaDecryptBySegment(keyPair.priKey, encryptText);
92    if (plainText.data.toString() === decryptText.data.toString()) {
93      console.info('decrypt ok');
94      console.info('decrypt plainText: ' + buffer.from(decryptText.data).toString('utf-8'));
95    } else {
96      console.error('decrypt failed');
97    }
98  }
99  ```
100
101- Example (using synchronous APIs):
102
103  ```ts
104  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
105  import { buffer } from '@kit.ArkTS';
106  // Encrypt the message by segment.
107  function rsaEncryptBySegment(pubKey: cryptoFramework.PubKey, plainText: cryptoFramework.DataBlob) {
108    let cipher = cryptoFramework.createCipher('RSA1024|PKCS1');
109    cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null);
110    let plainTextSplitLen = 64;
111    let cipherText = new Uint8Array();
112    for (let i = 0; i < plainText.data.length; i += plainTextSplitLen ) {
113      let updateMessage = plainText.data.subarray(i, i + plainTextSplitLen );
114      let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
115      // Split the plaintext by 64 bytes and cyclically call doFinal() to encrypt the plaintext using a 1024-bit key. The ciphertext of 128 bytes is generated each time.
116      let updateOutput = cipher.doFinalSync(updateMessageBlob);
117      let mergeText = new Uint8Array(cipherText.length + updateOutput.data.length);
118      mergeText.set(cipherText);
119      mergeText.set(updateOutput.data, cipherText.length);
120      cipherText = mergeText;
121    }
122    let cipherBlob: cryptoFramework.DataBlob = { data: cipherText };
123    return cipherBlob;
124  }
125  // Decrypt the message by segment.
126  function rsaDecryptBySegment(priKey: cryptoFramework.PriKey, cipherText: cryptoFramework.DataBlob) {
127    let decoder = cryptoFramework.createCipher('RSA1024|PKCS1');
128    decoder.initSync(cryptoFramework.CryptoMode.DECRYPT_MODE, priKey, null);
129    let cipherTextSplitLen = 128; // Length of the ciphertext = Number of key bits/8
130    let decryptText = new Uint8Array();
131    for (let i = 0; i < cipherText.data.length; i += cipherTextSplitLen) {
132      let updateMessage = cipherText.data.subarray(i, i + cipherTextSplitLen);
133      let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
134      // Split the ciphertext by 128 bytes, decrypt the ciphertext, and combine the plaintext obtained each time.
135      let updateOutput = decoder.doFinalSync(updateMessageBlob);
136      let mergeText = new Uint8Array(decryptText.length + updateOutput.data.length);
137      mergeText.set(decryptText);
138      mergeText.set(updateOutput.data, decryptText.length);
139      decryptText = mergeText;
140    }
141    let decryptBlob: cryptoFramework.DataBlob = { data: decryptText };
142    return decryptBlob;
143  }
144  function main() {
145    let message = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
146      "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
147      "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
148      "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
149      "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
150      "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
151      "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
152      "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!";
153    let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024");  // Create an AsyKeyGenerator object.
154    let keyPair = asyKeyGenerator.generateKeyPairSync(); // Randomly generate an RSA key pair.
155    let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) };
156    let encryptText = rsaEncryptBySegment(keyPair.pubKey, plainText);
157    let decryptText = rsaDecryptBySegment(keyPair.priKey, encryptText);
158    if (plainText.data.toString() === decryptText.data.toString()) {
159      console.info('decrypt ok');
160      console.info('decrypt plainText: ' + buffer.from(decryptText.data).toString('utf-8'));
161    } else {
162      console.error('decrypt failed');
163    }
164  }
165  ```
166