提交 e440f13f 编写于 作者: A Annie_wang

update docs

Signed-off-by: NAnnie_wang <annie.wangli@huawei.com>
上级 b1f9843a
......@@ -939,7 +939,7 @@ For the symmetric encryption and decryption modes that require parameters such a
| algName | string | Yes | Yes | Symmetric encryption and decryption parameters. Options:<br>- **IvParamsSpec**: applicable to the CBC, CTR, OFB, and CFB modes.<br>- **GcmParamsSpec**: applicable to the GCM mode.<br>- **CcmParamsSpec**: applicable to the CCM mode.|
> **NOTE**<br>
> The **params** parameter in [init()](#init-2) is of the **ParamsSpec** type (parent class), but a child class object (such as **IvParamsSpec**) needs to be passed in. When constructing the child class object, set **algName** for the parent class **ParamsSpec** to let the algorithm library know the type of child class object to pass in in **init()**.
> The **params** parameter in [init()](#init-2) is of the **ParamsSpec** type (parent class), but a child class object (such as **IvParamsSpec**) needs to be passed in. When constructing the child class object, set **algName** in the parent class **ParamsSpec** to let the algorithm library know the type of child class object to pass in in **init()**.
## IvParamsSpec
......@@ -954,11 +954,13 @@ Defines the child class of [ParamsSpec](#paramsspec). It is used as the paramete
| iv | [DataBlob](#datablob) | Yes | Yes | IV for encryption and decryption. Options:<br>- AES CBC, CTR, OFB, or CFB mode: 16-byte IV<br>- 3DES CBC, OFB, or CFB mode: 8-byte IV|
> **NOTE**<br>
> Before passing [init()](#init-2), specify **algName** for its parent class [ParamsSpec](#paramsspec).
> Before passing **IvParamsSpec** to [init()](#init-2), specify **algName** in its parent class [ParamsSpec](#paramsspec).
## GcmParamsSpec
Defines the child class of [ParamsSpec](#paramsspec) for the GCM mode. It is used as the parameters of [init()](#init-2) during symmetric encryption and decryption. <br>**GcmParamsSpec** applies to the GCM mode.
Defines the child class of [ParamsSpec](#paramsspec) for the GCM mode. It is used as the parameters of [init()](#init-2) during symmetric encryption and decryption.
**GcmParamsSpec** applies to the GCM mode.
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -969,22 +971,24 @@ Defines the child class of [ParamsSpec](#paramsspec) for the GCM mode. It is use
| authTag | [DataBlob](#datablob) | Yes | Yes | Authentication tag, which is of 16 bytes.<br>When the GCM mode is used for encryption, [DataBlob](#datablob) output by [doFinal()](#dofinal-2) is required. The last 16 bytes of [DataBlob](#datablob) are used as as **authTag** in [GcmParamsSpec](#gcmparamsspec) of [init()](#init-2). |
> **NOTE**
> Before passing [init()](#init-2), specify **algName** for its parent class [ParamsSpec](#paramsspec).
> Before passing **GcmParamsSpec** to [init()](#init-2), specify **algName** in its parent class [ParamsSpec](#paramsspec).
## CcmParamsSpec
Defines the child class of [ParamsSpec](#paramsspec) for the CCM mode. It is used as the parameters of [init()](#init-2) during symmetric encryption and decryption. <br>**CcmParamsSpec** applies to the CCM mode.
Defines the child class of [ParamsSpec](#paramsspec) for the CCM mode. It is used as the parameters of [init()](#init-2) during symmetric encryption and decryption.
**CcmParamsSpec** applies to the CCM mode.
**System capability**: SystemCapability.Security.CryptoFramework
| Name | Type | Readable| Writable| Description |
| ------- | --------------------- | ---- | ---- | ------------------------------------------------------------ |
| iv | [DataBlob](#datablob) | Yes | Yes | IV, which is of 7 bytes. |
| aad | [DataBlob](#datablob) | Yes | Yes | Additional authenticated data (AAD), which is of 8 bytes. |
| aad | [DataBlob](#datablob) | Yes | Yes | AAD, which is of 8 bytes. |
| authTag | [DataBlob](#datablob) | Yes | Yes | Authentication tag, which is of 12 bytes.<br>When the CCM mode is used for encryption, [DataBlob](#datablob) output by [doFinal()](#dofinal-2) is required. The last 12 bytes of [DataBlob](#datablob) are used as as **authTag** in [CcmParamsSpec](#ccmparamsspec) of [init()](#init-2).|
> **NOTE**
> Before passing [init()](#init-2), specify **algName** for its parent class [ParamsSpec](#paramsspec).
> Before passing **CcmParamsSpec** to [init()](#init-2), specify **algName** in its parent class [ParamsSpec](#paramsspec).
## CryptoMode
......@@ -1014,7 +1018,7 @@ Provides APIs for key operations. Before performing cryptographic operations (su
getEncoded() : DataBlob
Obtains the key in hexadecimal format. This API returns the result synchronously.
Obtains a key in hexadecimal format. This API returns the result synchronously.
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1041,7 +1045,9 @@ console.info("key hex:" + uint8ArrayToShowStr(encodedKey.data));
## SymKey
Provides APIs for symmetric key operations. It is a child class of [Key](#key). Its objects need to be passed to [init()](#init-2) of the [Cipher](#cipher) instance in symmetric encryption and decryption. <br>Symmetric keys can be generated by a [SymKeyGenerator](#symkeygenerator).
Provides APIs for symmetric key operations. **SymKey** is a child class of [Key](#key), and its objects need to be passed to [init()](#init-2) of the [Cipher](#cipher) instance in symmetric encryption and decryption.
Symmetric keys can be generated by a [SymKeyGenerator](#symkeygenerator).
### clearMem
......@@ -1063,15 +1069,17 @@ function uint8ArrayToShowStr(uint8Array) {
let key; // The key is generated by a symKeyGenerator. The generation process is omitted here.
let encodedKey = key.getEncoded();
console.info("key hex: "+ uint8ArrayToShowStr(encodedKey.data)); // Display key content.
console.info("key hex: "+ uint8ArrayToShowStr(encodedKey.data)); // Key content is displayed.
key.clearMem();
encodedKey = key.getEncoded();
console.info("key hex:" + uint8ArrayToShowStr(encodedKey.data)); // Display all 0s.
console.info("key hex:" + uint8ArrayToShowStr(encodedKey.data)); // All 0s are displayed.
```
## PubKey
Provides APIs for public key operations. It is a child class of [Key](#key). Its objects need to be passed in during asymmetric encryption and decryption, signature verification, and key agreement. <br>Public keys can be generated by an **AsyKeyGenerator**.
Provides APIs for public key operations. **PubKey** is a child class of [Key](#key), and its objects need to be passed in during asymmetric encryption and decryption, signature verification, and key agreement.
Public keys can be generated by an **AsyKeyGenerator**.
### Attributes
......@@ -1087,7 +1095,7 @@ Provides APIs for public key operations. It is a child class of [Key](#key). Its
getEncoded() : DataBlob
Obtains the key in binary format. This API returns the result synchronously. The public key format must comply with the ASN.1 syntax, X.509 specifications, and DER encoding format.
Obtains a key in binary format. This API returns the result synchronously. The public key format must comply with the ASN.1 syntax, X.509 specifications, and DER encoding format.
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1115,7 +1123,9 @@ console.info("key encoded:" + uint8ArrayToShowStr(encodedKey.data));
## PriKey
Provides APIs for private key operations. It is a child class of [Key](#key). Its objects need to be passed in during asymmetric encryption and decryption, signature verification, and key agreement. <br>Private keys can be generated by an **AsyKeyGenerator**.
Provides APIs for private key operations. **PriKey** is a child class of [Key](#key), and its objects need to be passed in during asymmetric encryption and decryption, signature verification, and key agreement.
Private keys can be generated by an **AsyKeyGenerator**.
### Attributes
......@@ -1130,7 +1140,7 @@ Provides APIs for private key operations. It is a child class of [Key](#key). It
getEncoded() : DataBlob
Obtains the key in binary format. This API returns the result synchronously. The private key format must comply with the ASN.1 syntax, PKCS #8 specifications, and DER encoding mode.
Obtains a key in binary format. This API returns the result synchronously. The private key format must comply with the ASN.1 syntax, PKCS #8 specifications, and DER encoding mode.
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1173,11 +1183,13 @@ key.clearMem();
## KeyPair
Defines an asymmetric key pair, which includes a public key and a private key. <br>Asymmetric key pairs can be generated by the **AsyKeyGenerator**.
Defines an asymmetric key pair, which includes a public key and a private key.
Asymmetric key pairs can be generated by an **AsyKeyGenerator**.
> **NOTE**
>
> The **pubKey** and **priKey** objects in the **KeyPair** object exist as one parameter in the **KeyPair** object. When **KeyPair** leaves the scope, its internal objects may be destructed. <br>The service must reference the **KeyPair** object instead of the internal **pubKey** or **priKey** object.
> The **pubKey** and **priKey** objects in the **KeyPair** object are defined as one parameter in **KeyPair**. When **KeyPair** leaves the scope, its internal objects may be destructed. <br>The service must reference the **KeyPair** object instead of the **pubKey** or **priKey** object.
### Attributes
......@@ -1193,7 +1205,9 @@ Defines an asymmetric key pair, which includes a public key and a private key. <
createSymKeyGenerator(algName : string) : SymKeyGenerator
Creates a **symKeyGenerator** instance based on the specified algorithm. <br>For details about the supported specifications, see [Key Generation Specifications](../../security/cryptoFramework-overview.md#key-generation- specifications).
Creates a **symKeyGenerator** instance based on the specified algorithm.
For details about the supported specifications, see [Key Generation Specifications](../../security/cryptoFramework-overview.md#key-generation-specifications).
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1218,7 +1232,9 @@ let symKeyGenerator = cryptoFramework.createSymKeyGenerator('3DES192');
## SymKeyGenerator
Provides APIs for using the **symKeyGenerator**. <br>Before using any API of the **SymKeyGenerator** class, you must create a **symKeyGenerator** instance by using [createSymKeyGenerator](#cryptoframeworkcreatesymkeygenerator).
Provides APIs for using the **symKeyGenerator**.
Before using any API of the **SymKeyGenerator** class, you must create a **symKeyGenerator** instance by using [createSymKeyGenerator](#cryptoframeworkcreatesymkeygenerator).
### Attributes
......@@ -1232,7 +1248,11 @@ Provides APIs for using the **symKeyGenerator**. <br>Before using any API of the
generateSymKey(callback : AsyncCallback\<SymKey>) : void
Generates a key randomly. This API uses an asynchronous callback to return the result. <br>This API can be used only after a **symKeyGenerator** instance is created by using [createSymKeyGenerator](#cryptoframeworkcreatesymkeygenerator). <br>**RAND_priv_bytes()** of OpenSSL can be used to generate random keys.
Generates a symmetric key randomly. This API uses an asynchronous callback to return the result.
This API can be used only after a **symKeyGenerator** instance is created by using [createSymKeyGenerator](#cryptoframeworkcreatesymkeygenerator).
**RAND_priv_bytes()** of OpenSSL can be used to generate random keys.
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1267,7 +1287,11 @@ symKeyGenerator.generateSymKey((err, symKey) => {
generateSymKey() : Promise\<SymKey>
Generates a key randomly. This API uses a promise to return the result. <br>This API can be used only after a **symKeyGenerator** instance is created by using [createSymKeyGenerator](#cryptoframeworkcreatesymkeygenerator). <br>**RAND_priv_bytes()** of OpenSSL can be used to generate random keys.
Generates a symmetric key randomly. This API uses a promise to return the result.
This API can be used only after a **symKeyGenerator** instance is created by using [createSymKeyGenerator](#cryptoframeworkcreatesymkeygenerator).
**RAND_priv_bytes()** of OpenSSL can be used to generate random keys.
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1399,7 +1423,9 @@ symKeyGenerator.convertKey(keyMaterialBlob)
createAsyKeyGenerator(algName : string) : AsyKeyGenerator
Creates an **AsyKeyGenerator** instance based on the specified algorithm. <br>For details about the supported specifications, see [Key Generation Specifications](../../security/cryptoFramework-overview.md#key-generation- specifications).
Creates an **AsyKeyGenerator** instance based on the specified algorithm.
For details about the supported specifications, see [Key Generation Specifications](../../security/cryptoFramework-overview.md#key-generation-specifications).
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1509,7 +1535,7 @@ keyGenPromise.then( keyPair => {
convertKey(pubKey : DataBlob, priKey : DataBlob, callback : AsyncCallback\<KeyPair\>) : void
Converts data into an asymmetric key. This API uses an asynchronous callback to return the result. For details, see **Key Conversion**.
Converts data into an asymmetric key. This API uses an asynchronous callback to return the result. For more information, see **Key Conversion**.
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1547,7 +1573,7 @@ asyKeyGenerator.convertKey(pubKey, priKey, (err, keyPair) => {
convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair>
Converts data into an asymmetric key. This API uses a promise to return the result. For details, see **Key Conversion**.
Converts data into an asymmetric key. This API uses a promise to return the result. For more information, see **Key Conversion**.
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1562,7 +1588,7 @@ Converts data into an asymmetric key. This API uses a promise to return the resu
| Type | Description |
| ----------------- | --------------------------------- |
| Promise\<[KeyPair](#keypair)> | Promise used to return the key pair generated.|
| Promise\<[KeyPair](#keypair)> | Promise used to return the key pair obtained. |
**Error codes**
......@@ -1588,15 +1614,17 @@ keyGenPromise.then( keyPair => {
**Key Conversion**
1. After **getEncoded()** is called for the asymmetric public and private keys (RSA and ECC), binary data in X.509 format and binary data in PKCS #8 format are returned, respectively. The data can be used for cross-application transfer or persistent storage.
2. The public key returned by **convertKey()** must comply with the ASN.1 syntax, X.509 specifications, and DER encoding format, and the private key must comply with the ASN.1 syntax, PKCS #8 specifications, and DER encoding format.
3. In **convertKey()**, you can pass in either **pubKey** or **priKey**, or both of them. If one of them is passed in, the returned **KeyPair** instance contains only the key converted from the data you passed in.
- If **getEncoded()** is called to obtain a public key and a private key (RSA and ECC), binary data in X.509 format and binary data in PKCS #8 format are returned, respectively. The data can be used for cross-application transfer or persistent storage.
- When **convertKey()** is called to convert binary data into an asymmetric key pair, the public key material must comply with the ASN.1 syntax, X.509 specifications, and DER encoding format, and the private key material must comply with the ASN.1 syntax, PKCS #8 specifications, and DER encoding format.
- In **convertKey()**, you can pass in either **pubKey** or **priKey**, or both of them. If one of them is passed in, the returned **KeyPair** instance contains only the key converted from the data you passed in.
## cryptoFramework.createCipher
createCipher(transformation : string) : Cipher
Creates a [Cipher](#cipher) instance based on the specified algorithm. <br>For details about the supported specifications, see [Encryption and Decryption Specifications](../../security/cryptoFramework-overview.md#encryption-and-decryption-specifications).
Creates a [Cipher](#cipher) instance based on the specified algorithm.
For details about the supported specifications, see [Encryption and Decryption Specifications](../../security/cryptoFramework-overview.md#encryption-and-decryption-specifications).
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1604,11 +1632,11 @@ Creates a [Cipher](#cipher) instance based on the specified algorithm. <br>For d
| Name | Type | Mandatory| Description |
| -------------- | ------ | ---- | ------------------------------------------------------------ |
| transformation | string | Yes | Combination of the algorithm name (including the key length), encryption mode, and padding algorithm of the **Cipher** instance to create.<br>For details about, see **Algorithm String** in [Encryption and Decryption Specifications](../../security/cryptoFramework-overview.md#encryption-and-decryption-specifications).|
| transformation | string | Yes | Combination of the algorithm name (including the key length), encryption mode, and padding algorithm of the **Cipher** instance to create.<br>For details, see **Algorithm String** in [Encryption and Decryption Specifications](../../security/cryptoFramework-overview.md#encryption-and- decryption-specifications). |
> **NOTE**
> 1. In symmetric encryption and decryption, the implementation of PKCS #5 is the same as that of PKCS #7. PKCS #5 and PKCS #7 use the same padding length and block length. That is, data is padded with 8 bytes in 3DES and 16 bytes in AES. **noPadding** indicates that no padding is performed. <br>You need to understand the differences between different block cipher modes and use the correct parameter specifications. For example, padding is required for ECB and CBC. Otherwise, ensure that the plaintext length is an integer multiple of the block size. No padding is recommended for other modes. In this case, the ciphertext length is the same as the plaintext length.
> 2. If RSA is used for asymmetric encryption and decryption, two **Cipher** objects must be created to perform encryption and decryption separately. For symmetric encryption and decryption, one **cipher** object can be used to perform both encryption and decryption as long as the algorithm specifications are the same.
> - In symmetric encryption and decryption, the implementation of PKCS #5 is the same as that of PKCS #7. PKCS #5 and PKCS #7 use the same padding length and block length. That is, data is padded with 8 bytes in 3DES and 16 bytes in AES. **noPadding** indicates that no padding is performed. <br>You need to understand the differences between different block cipher modes and set parameter correctly. For example, padding is required for ECB and CBC. Otherwise, the plaintext length must be an integer multiple of the block size. No padding is recommended for other modes. In this case, the ciphertext length is the same as the plaintext length.
> - If RSA is used for asymmetric encryption and decryption, two **Cipher** objects must be created to perform encryption and decryption separately. For symmetric encryption and decryption, one **cipher** object can be used to perform both encryption and decryption as long as the algorithm specifications are the same.
**Return value**
......@@ -1633,12 +1661,14 @@ try {
## Cipher
Provides APIs for cipher operations. The [init()](#init-2), [update()](#update-4), and [doFinal()](#dofinal-2) APIs in this class are called in sequence to implement symmetric encryption or decryption and asymmetric encryption or decryption. <br>For details about the complete encryption and decryption process, see [Encrypting and Decrypting Data](../../security/cryptoFramework-guidelines.md#encrypting-and-decrypting-data).
Provides APIs for cipher operations. The [init()](#init-2), [update()](#update-4), and [doFinal()](#dofinal-2) APIs in this class are called in sequence to implement symmetric encryption/decryption and asymmetric encryption/decryption.
For details about the complete encryption and decryption process, see [Encrypting and Decrypting Data](../../security/cryptoFramework-guidelines.md#encrypting-and-decrypting-data).
A complete symmetric encryption/decryption process is slightly different from the asymmetric encryption/decryption process.
- Symmetric encryption and decryption: **init()** and **doFinal()** are mandatory. **update()** is optional and can be called multiple times to encrypt or decrypt big data. After **doFinal()** is called to complete an encryption or decryption operation, **init()** can be called to start a new encryption or decryption operation.
- RSA asymmetric encryption and decryption: **init()** and **doFinal()** are mandatory, and **update()** is not supported. **doFinal()** can be called multiple times to encrypt or decrypt big data. **init()** cannot be called repeatedly. If the encryption/decryption mode or padding mode is changed, a new **Cipher** object must be created.
- In symmetric encryption and decryption, **init()** and **doFinal()** are mandatory. **update()** is optional and can be called multiple times to encrypt or decrypt big data by segment. After **doFinal()** is called to complete an encryption/decryption operation, **init()** can be called to start a new encryption/decryption operation.
- In RSA asymmetric encryption and decryption, **init()** and **doFinal()** are mandatory, and **update()** is not supported. **doFinal()** can be called multiple times to encrypt or decrypt big data by segment. **init()** cannot be called repeatedly. If the encryption/decryption mode or padding mode is changed, a new **Cipher** object must be created.
### Attributes
......@@ -1653,7 +1683,9 @@ A complete symmetric encryption/decryption process is slightly different from th
init(opMode : CryptoMode, key : Key, params : ParamsSpec, callback : AsyncCallback\<void>) : void
Initializes a [cipher](#cipher) instance. This API uses an asynchronous callback to return the result. **init()**This API can be used only after a [Cipher](#cipher) instance is created by using [createCipher](#cryptoframeworkcreatecipher).
Initializes a [cipher](#cipher) instance. This API uses an asynchronous callback to return the result.
This API can be used only after a [Cipher](#cipher) instance is created by using [createCipher](#cryptoframeworkcreatecipher).
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1695,7 +1727,9 @@ cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, null, (err, ) => {
init(opMode : CryptoMode, key : Key, params : ParamsSpec) : Promise\<void>
Initializes a [cipher](#cipher) instance. This API uses a promise to return the result. <br>**init()**This API can be used only after a [Cipher](#cipher) instance is created by using [createCipher](#cryptoframeworkcreatecipher).
Initializes a [cipher](#cipher) instance. This API uses a promise to return the result.
This API can be used only after a [Cipher](#cipher) instance is created by using [createCipher](#cryptoframeworkcreatecipher).
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1740,12 +1774,14 @@ cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, null)
update(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void
Updates the data to encrypt or decrypt by segment. This API uses an asynchronous callback to return the encrypted or decrypted data. <br>This API can be called only after the [Cipher](#cipher) instance is initialized by using [init()](init-2).
Updates the data to encrypt or decrypt by segment. This API uses an asynchronous callback to return the encrypted or decrypted data.
This API can be called only after the [Cipher](#cipher) instance is initialized by using [init()](init-2).
> **NOTE**
> 1. If you are not familiar with the block modes for symmetric encryption and decryption, add a judgment to determine whether the result of each **update()** and **doFinal()** is null. If the result is not null, obtain the data to concatenate the complete ciphertext or plaintext. The reason is the block mode and the related specifications affect the **update()** and [doFinal()](#dofinal-2) results. <br>For example, in ECB and CBC modes, data is encrypted or decrypted by block no matter whether the data passed in by **update()** is an integer multiple of the block length, and the encrypted/decrypted block data generated by this **update()** is output. <br>That is, encrypted/decrypted data is returned as long as the data passed in by **update()** reaches the size of a block. Otherwise, **null** is returned and the data will be retained until a block is formed in the next **update()**/**doFinal()**. <br>When **doFinal()** is called, the data that has not been encrypted or decrypted will be padded based on the padding mode set in [createCipher](#cryptoframeworkcreatecipher) to an integer multiple of the block length, and then encrypted or decrypted. <br>For a mode in which a block cipher can be converted into a stream cipher, the length of the ciphertext may be the same as that of the plaintext.
> 2. **update()** may be called multiple times or may not be called ([doFinal()](#dofinal-2) is called after [init](#init-2)), depending on the size of the data to encrypt or decrypt. <br>The algorithm library does not set a limit on the amount of data that can be passed in by **updated()** (once or accumulatively). For symmetric encryption and decryption of a large amount of data, you are advised to call **update()** multiple times to pass in the data by segment. <br>For details about the sample code for calling **update()** multiple times in AES, see [Encrypting and Decrypting Data](../../security/cryptoFramework-guidelines.md#encrypting-and-decrypting-data).
> 3. RSA asymmetric encryption and decryption do not support **update()**.
> - The **update()** and [doFinal()](#dofinal-2) results vary with the block mode you use. If you are not familiar with the block modes for symmetric encryption and decryption, add a judgment to determine whether the result of each **update()** and **doFinal()** is null. If the result is not null, obtain the data to concatenate the complete ciphertext or plaintext.<br>For example, in ECB and CBC modes, data is encrypted or decrypted by block no matter whether the data passed in by **update()** is an integer multiple of the block length, and the encrypted/decrypted block data generated by this **update()** is output. <br>That is, data is output by **update()** as long as the input data is of the block size. Otherwise, **null** is returned and the data will be retained until a block is formed in the next **update()**/**doFinal()**. <br>When **doFinal()** is called, the data that has not been encrypted or decrypted will be padded based on the padding mode set in [createCipher](#cryptoframeworkcreatecipher) to an integer multiple of the block length, and then encrypted or decrypted. <br>For a mode in which a block cipher can be converted into a stream cipher, the length of the ciphertext may be the same as that of the plaintext.
> - **update()** can be called multiple times or not be called ([doFinal()](#dofinal-2) is called after [init](#init-2)), depending on the size of the data to encrypt or decrypt. <br>The algorithm library does not set a limit on the amount of data that can be passed in by **updated()** (once or accumulatively). For symmetric encryption and decryption of a large amount of data, you are advised to call **update()** multiple times to pass in the data by segment. <br>For details about the sample code for calling **update()** multiple times in AES, see [Encrypting and Decrypting Data](../../security/cryptoFramework-guidelines.md#encrypting-and-decrypting-data).
> - RSA asymmetric encryption and decryption do not support **update()**.
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1800,9 +1836,9 @@ update(data : DataBlob) : Promise\<DataBlob>
Updates the data to encrypt or decrypt by segment. This API uses a promise to return the encrypted or decrypted data. <br>This API can be called only after the [Cipher](#cipher) instance is initialized by using [init()](init-2).
> **NOTE**
> 1. If you are not familiar with the block modes for symmetric encryption and decryption, add a judgment to determine whether the result of each **update()** and **doFinal()** is null. If the result is not null, obtain the data to concatenate the complete ciphertext or plaintext. The reason is the block mode and the related specifications affect the **update()** and [doFinal()](#dofinal-2) results. <br>For example, in ECB and CBC modes, data is encrypted or decrypted by block no matter whether the data passed in by **update()** is an integer multiple of the block length, and the encrypted/decrypted block data generated by this **update()** is output. <br>That is, encrypted/decrypted data is returned as long as the data passed in by **update()** reaches the size of a block. Otherwise, **null** is returned and the data will be retained until a block is formed in the next **update()**/**doFinal()**. <br>When **doFinal()** is called, the data that has not been encrypted or decrypted will be padded based on the padding mode set in [createCipher](#cryptoframeworkcreatecipher) to an integer multiple of the block length, and then encrypted or decrypted. <br>For a mode in which a block cipher can be converted into a stream cipher, the length of the ciphertext may be the same as that of the plaintext.
> 2. **update()** may be called multiple times or may not be called ([doFinal()](#dofinal-2) is called after [init](#init-2)), depending on the size of the data to encrypt or decrypt. <br>The algorithm library does not set a limit on the amount of data that can be passed in by **updated()** (once or accumulatively). For symmetric encryption and decryption of a large amount of data, you are advised to call **update()** multiple times to pass in the data by segment. For details about the sample code for calling **update()** multiple times in AES, see [Encrypting and Decrypting Data](../../security/cryptoFramework-guidelines.md#encrypting-and-decrypting-data).
> 3. RSA asymmetric encryption and decryption do not support **update()**.
> - The **update()** and [doFinal()](#dofinal-2) results vary with the block mode you use. If you are not familiar with the block modes for symmetric encryption and decryption, add a judgment to determine whether the result of each **update()** and **doFinal()** is null. If the result is not null, obtain the data to concatenate the complete ciphertext or plaintext.<br>For example, in ECB and CBC modes, data is encrypted or decrypted by block no matter whether the data passed in by **update()** is an integer multiple of the block length, and the encrypted/decrypted block data generated by this **update()** is output. <br>That is, data is output as long as the data passed in by **update()** is of the block size. Otherwise, **null** is returned and the data will be retained until a block is formed in the next **update()**/**doFinal()**. <br>When **doFinal()** is called, the data that has not been encrypted or decrypted will be padded based on the padding mode set in [createCipher](#cryptoframeworkcreatecipher) to an integer multiple of the block length, and then encrypted or decrypted. <br>For a mode in which a block cipher can be converted into a stream cipher, the length of the ciphertext may be the same as that of the plaintext.
> - **update()** can be called multiple times or not be called ([doFinal()](#dofinal-2) is called after [init](#init-2)), depending on the size of the data to encrypt or decrypt. <br>The algorithm library does not set a limit on the amount of data that can be passed in by **updated()** (once or accumulatively). For symmetric encryption and decryption of a large amount of data, you are advised to call **update()** multiple times to pass in the data by segment. For details about the sample code for calling **update()** multiple times in AES, see [Encrypting and Decrypting Data](../../security/cryptoFramework-guidelines.md#encrypting-and-decrypting-data).
> - RSA asymmetric encryption and decryption do not support **update()**.
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1816,7 +1852,7 @@ Updates the data to encrypt or decrypt by segment. This API uses a promise to re
| Type | Description |
| ------------------------------- | ------------------------------------------------ |
| Promise\<[DataBlob](#datablob)> | Promise used to returns the **DataBlob** (containing the encrypted or decrypted data).|
| Promise\<[DataBlob](#datablob)> | Promise used to return the **DataBlob** (containing the encrypted or decrypted data). |
**Error codes**
......@@ -1858,18 +1894,20 @@ cipher.update(plainText)
doFinal(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void
(1) Encrypts or decrypts the remaining data (generated by the block ciper mode) and the data passed in by **doFinal()** to finalize the symmetric encryption or decryption. This API uses an asynchronous callback to return the encrypted or decrypted data. <br>If a small amount of data needs to be encrypted or decrypted, you can use **doFinal()** to pass in data without using **update()**. If all the data has been passed in by [update()](#update-4), you can pass in **null** in **data** of **doFinal()**. <br>The output of **doFinal()** varies with the symmetric encryption/decryption mode in use.
(1) Encrypts or decrypts the remaining data (generated by the block ciper mode) and the data passed in by **doFinal()** to finalize the symmetric encryption or decryption. This API uses an asynchronous callback to return the encrypted or decrypted data. <br>If a small amount of data needs to be encrypted or decrypted, you can use **doFinal()** to pass in data without using **update()**. If all the data has been passed in by [update()](#update-4), you can pass in **null** in **data** of **doFinal()**.
The output of **doFinal()** varies with the symmetric encryption/decryption mode in use.
- Symmetric encryption in GCM and CCM mode: The result consists of the ciphertext and **authTag** (the last 16 bytes for GCM and the last 12 bytes for CCM). If **null** is passed in by **data** of **doFinal()**, the result of **doFinal()** is **authTag**. <br>**authTag** must be [GcmParamsSpec](#gcmparamsspec) or [CcmParamsSpec](#ccmparamsspec) used for decryption. The ciphertext is the **data** passed in for decryption.
- Symmetric encryption and decryption in other modes and symmetric decryption in GCM and CCM modes: The result is the complete plaintext/ciphertext.
(2) Encrypts or decrypts the input data for RSA asymmetric encryption/decryption. This API uses an asynchronous callback to return the result. If a large amount of data needs to be encrypted/decrypted, call **doFinal()** multiple times and concatenate the result of each **doFinal()** to obtain the complete plaintext/ciphertext.
(2) Encrypts or decrypts the input data for RSA asymmetric encryption/decryption. This API uses an asynchronous callback to return the result. If a large amount of data needs to be encrypted/decrypted, call **doFinal()** multiple times and concatenate the result of each **doFinal()** to obtain the complete plaintext/ciphertext.
> **NOTE**
> 1. In symmetric encryption or decryption, calling **doFinal()** means the end of an encryption or decryption process, and the [Cipher](#cipher) instance state will be cleared. To start a new encryption or decryption operation, you must call [init()](#init-2) to pass in a complete parameter list for initialization. <br>For example, if the same symmetric key is used for a **Cipher** instance to perform encryption and then decryption. After the encryption is complete, the **params** in **init** for decryption must be set instead of being **null**.
> 2. If a decryption fails, check whether the data to be encrypted and decrypted matches the parameters in **[init](#init-2)**. For the GCM mode, check whether the **authTag** obtained after encryption is obtained from the **GcmParamsSpec** for decryption.
> 3. The result of **doFinal()** may be **null**. To avoid exceptions, determine whether the result is **null** before using the **.data** field to access the **doFinal()** result.
> 4. For details about the sample code for calling **doFinal()** multiple times during RSA asymmetric encryption and decryption, see [Encrypting and Decrypting Data](../../security/cryptoFramework-guidelines.md#encrypting-and-decrypting-data).
> - In symmetric encryption or decryption, calling **doFinal()** means the end of an encryption or decryption process, and the [Cipher](#cipher) instance state will be cleared. To start a new encryption or decryption operation, you must call [init()](#init-2) to pass in a complete parameter list for initialization. <br>For example, if the same symmetric key is used for a **Cipher** instance to perform encryption and then decryption. After the encryption is complete, the **params** in **init** for decryption must be set instead of being **null**.
> - If a decryption operation fails, check whether the data to be encrypted and decrypted matches the parameters in **[init](#init-2)**. For the GCM mode, check whether the **authTag** obtained after encryption is obtained from the **GcmParamsSpec** for decryption.
> - The result of **doFinal()** may be **null**. To avoid exceptions, determine whether the result is **null** before using the **.data** field to access the **doFinal()** result.
> - For details about the sample code for calling **doFinal()** multiple times during RSA asymmetric encryption and decryption, see [Encrypting and Decrypting Data](../../security/cryptoFramework-guidelines.md#encrypting-and-decrypting-data).
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -1912,18 +1950,20 @@ cipher.doFinal(data, (err, output) => {
doFinal(data : DataBlob) : Promise\<DataBlob>
(1) Encrypts or decrypts the remaining data (generated by the block ciper mode) and the data passed in by **doFinal()** to finalize the symmetric encryption or decryption. This API uses a promise to return the encrypted or decrypted data. <br>If a small amount of data needs to be encrypted or decrypted, you can use **doFinal()** to pass in data without using **update()**. If all the data has been passed in by [update()](#update-4), you can pass in **null** in **data** of **doFinal()**. <br>The output of **doFinal()** varies with the symmetric encryption/decryption mode in use.
(1) Encrypts or decrypts the remaining data (generated by the block ciper mode) and the data passed in by **doFinal()** to finalize the symmetric encryption or decryption. This API uses a promise to return the encrypted or decrypted data. <br>If a small amount of data needs to be encrypted or decrypted, you can use **doFinal()** to pass in data without using **update()**. If all the data has been passed in by [update()](#update-4), you can pass in **null** in **data** of **doFinal()**.
The output of **doFinal()** varies with the symmetric encryption/decryption mode in use.
- Symmetric encryption in GCM and CCM mode: The result consists of the ciphertext and **authTag** (the last 16 bytes for GCM and the last 12 bytes for CCM). If **null** is passed in by **data** of **doFinal()**, the result of **doFinal()** is **authTag**. <br>**authTag** must be [GcmParamsSpec](#gcmparamsspec) or [CcmParamsSpec](#ccmparamsspec) used for decryption. The ciphertext is the **data** passed in for decryption.
- Symmetric encryption and decryption in other modes and symmetric decryption in GCM and CCM modes: The result is the complete plaintext/ciphertext.
(2) Encrypts or decrypts the input data for RSA asymmetric encryption/decryption. This API uses a promise to return the result. If a large amount of data needs to be encrypted/decrypted, call **doFinal()** multiple times and concatenate the result of each **doFinal()** to obtain the complete plaintext/ciphertext.
(2) Encrypts or decrypts the input data for RSA asymmetric encryption/decryption. This API uses a promise to return the result. If a large amount of data needs to be encrypted/decrypted, call **doFinal()** multiple times and concatenate the result of each **doFinal()** to obtain the complete plaintext/ciphertext.
> **NOTE**
> 1. In symmetric encryption or decryption, calling **doFinal()** means the end of an encryption or decryption process, and the [Cipher](#cipher) instance state will be cleared. To start a new encryption or decryption operation, you must call [init()](#init-2) to pass in a complete parameter list for initialization. <br>For example, if the same symmetric key is used for a **Cipher** instance to perform encryption and then decryption. After the encryption is complete, the **params** in **init** for decryption must be set instead of being **null**.
> 2. If a decryption fails, check whether the data to be encrypted and decrypted matches the parameters in **[init](#init-2)**. For the GCM mode, check whether the **authTag** obtained after encryption is obtained from the **GcmParamsSpec** for decryption.
> 3. The result of **doFinal()** may be **null**. To avoid exceptions, determine whether the result is **null** before using the **.data** field to access the **doFinal()** result.
> 4. For details about the sample code for calling **doFinal()** multiple times during RSA asymmetric encryption and decryption, see [Encrypting and Decrypting Data](../../security/cryptoFramework-guidelines.md#encrypting-and-decrypting-data).
> - In symmetric encryption or decryption, calling **doFinal()** means the end of an encryption or decryption process, and the [Cipher](#cipher) instance state will be cleared. To start a new encryption or decryption operation, you must call [init()](#init-2) to pass in a complete parameter list for initialization. <br>For example, if the same symmetric key is used for a **Cipher** instance to perform encryption and then decryption. After the encryption is complete, the **params** in **init** for decryption must be set instead of being **null**.
> - If a decryption fails, check whether the data to be encrypted and decrypted matches the parameters in **[init](#init-2)**. For the GCM mode, check whether the **authTag** obtained after encryption is obtained from the **GcmParamsSpec** for decryption.
> - The result of **doFinal()** may be **null**. To avoid exceptions, determine whether the result is **null** before using the **.data** field to access the **doFinal()** result.
> - For details about the sample code for calling **doFinal()** multiple times during RSA asymmetric encryption and decryption, see [Encrypting and Decrypting Data](../../security/cryptoFramework-guidelines.md#encrypting-and-decrypting-data).
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -2021,14 +2061,16 @@ keyGenPromise.then(rsaKeyPair => {
});
```
> **NOTE**
> **NOTE**<br>
> For more encryption and decryption examples, see [Encrypting and Decrypting Data](../../security/cryptoFramework-guidelines.md#encrypting-and-decrypting data).
## cryptoFramework.createSign
createSign(algName : string) : Sign
Creates a **Sign** instance. <br>For details about the supported specifications, see [Signing and Signature Verification Specifications](../../security/cryptoFramework-overview.md#signing-and-signature-verification-specifications).
Creates a **Sign** instance.
For details about the supported specifications, see [Signing and Signature Verification Specifications](../../security/cryptoFramework-overview.md#signing-and-signature-verification-specifications).
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -2060,7 +2102,7 @@ Provides APIs for signing. Before using any API of the **Sign** class, you must
The signing mode is determined in **createSign()**, and the key is set by **init()**.
If the data to be signed is short, you can call **sign()** to pass in the data for signing after **init()**.
If the data to be signed is short, you can use **sign()** to pass in the data for signing after **init()**.
If the data to be signed is long, you can use **update()** to pass in the data by segment, and then use **sign()** to sign the entire data.
......@@ -2078,7 +2120,7 @@ If **update()** is used to pass in data by segment, **data** of **sign()** can b
init(priKey : PriKey, callback : AsyncCallback\<void>) : void
Initializes a **Sign** object using a private key. This API uses an asynchronous callback to return the result. The **Sign** class does not support repeated calling of **init()**.
Initializes a **Sign** instance using a private key. This API uses an asynchronous callback to return the result. The **Sign** class does not support repeated calling of **init()**.
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -2101,7 +2143,7 @@ Initializes a **Sign** object using a private key. This API uses an asynchronous
init(priKey : PriKey) : Promise\<void>
Initializes a **Sign** object using a private key. This API uses a promise to return the result. The **Sign** class does not support repeated calling of **init()**.
Initializes a **Sign** instance using a private key. This API uses a promise to return the result. The **Sign** class does not support repeated calling of **init()**.
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -2131,7 +2173,7 @@ update(data : DataBlob, callback : AsyncCallback\<void>) : void
Updates the data to be signed. This API uses an asynchronous callback to return the result.
> **NOTE**
> **NOTE**<br>
> For details about the sample code for calling **update()** multiple times, see [Signing Data and Verifying Signatures](../../security/cryptoFramework-guidelines.md#signing-data-and-verifying-signatures).
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -2157,7 +2199,7 @@ update(data : DataBlob) : Promise\<void>;
Updates the data to be signed. This API uses a promise to return the result.
> **NOTE**
> **NOTE**<br>
> For details about the sample code for calling **update()** multiple times, see [Signing Data and Verifying Signatures](../../security/cryptoFramework-guidelines.md#signing-data-and-verifying-signatures).
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -2247,8 +2289,8 @@ function stringToUint8Array(str) {
let globalKeyPair;
let SignMessageBlob;
let plan1 = "This is Sign test plan1"; // The first segment of data.
let plan2 = "This is Sign test plan2"; // The second segment of fata.
let plan1 = "This is Sign test plan1"; // The first segment of the data.
let plan2 = "This is Sign test plan2"; // The second segment of the data.
let input1 = { data : stringToUint8Array(plan1) };
let input2 = { data : stringToUint8Array(plan2) };
......@@ -2259,8 +2301,8 @@ function signMessageCallback() {
globalKeyPair = keyPair;
let priKey = globalKeyPair.priKey;
signer.init(priKey, function (err, data) {
signer.update(input1, function (err, data) { // add first segment of data
signer.sign(input2, function (err, data) { // add second segment of data, sign input1 and input2
signer.update(input1, function (err, data) { // Add the first segment of the data.
signer.sign(input2, function (err, data) { // Add the second segment of the data, and sign input1 and input2.
SignMessageBlob = data;
AlertDialog.show({message : "res" + SignMessageBlob.data});
});
......@@ -2286,8 +2328,8 @@ function stringToUint8Array(str) {
let globalKeyPair;
let SignMessageBlob;
let plan1 = "This is Sign test plan1"; // The first segment of data.
let plan2 = "This is Sign test plan2"; // The second segment of fata.
let plan1 = "This is Sign test plan1"; // The first segment of the data.
let plan2 = "This is Sign test plan2"; // The second segment of the data.
let input1 = { data : stringToUint8Array(plan1) };
let input2 = { data : stringToUint8Array(plan2) };
......@@ -2300,9 +2342,9 @@ function signMessagePromise() {
let priKey = globalKeyPair.priKey;
return signer.init(priKey);
}).then(() => {
return signer.update(input1); // add first segment of data
return signer.update(input1); // Add the first segment of the data.
}).then(() => {
return signer.sign(input2); // add second segment of data, sign input1 and input2
return signer.sign(input2); // Add the second segment of the data, and sign input1 and input2.
}).then(dataBlob => {
SignMessageBlob = dataBlob;
console.info("sign output is " + SignMessageBlob.data);
......@@ -2477,7 +2519,7 @@ Updates the data for signature verification. This API uses a promise to return t
verify(data : DataBlob, signatureData : DataBlob, callback : AsyncCallback\<boolean>) : void
Verifies the signature. This API uses an asynchronous callback to return the result.
Verifies a signature. This API uses an asynchronous callback to return the result.
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -2501,7 +2543,7 @@ Verifies the signature. This API uses an asynchronous callback to return the res
verify(data : DataBlob, signatureData : DataBlob) : Promise\<boolean>
Verifies the signature. This API uses a promise to return the result.
Verifies a signature. This API uses a promise to return the result.
**System capability**: SystemCapability.Security.CryptoFramework
......@@ -2569,7 +2611,9 @@ verifyInitPromise.then(() => {
createKeyAgreement(algName : string) : KeyAgreement
Creates a **KeyAgreement** instance. <br>For details about the supported specifications, see "Key Agreement Specifications" (../../security/cryptoFramework-overview.md#key-agreement-specifications).
Creates a **KeyAgreement** instance.
For details about the supported specifications, see [Key Agreement Specifications](../../security/cryptoFramework-overview.md#key-agreement-specifications).
**System capability**: SystemCapability.Security.CryptoFramework
......
......@@ -2,21 +2,18 @@
> **NOTE**
>
> This development guide applies to API version 9, OpenHarmony SDK version 3.2.7 or later, and JS development.
> This guide applies to JS development using OpenHarmony API version 9 and SDK version 3.2.7 or later.
## Generating and Converting Keys
## Generating and Converting a Key
**When to Use**
Typical key generation operations involve the following:
1. Randomly create a key instance. This instance can be used for subsequent encryption and decryption.
2. Convert external or stored binary data into a key instance. This instance can be used for subsequent encryption and decryption.
3. Obtain the binary data of a key for storage or transmission.
> **NOTE**
>
> The key instance can be a symmetric key instance (**SymKey**) or an asymmetric key pair instance (**KeyPair**). The **KeyPair** instance consists a public key (PubKey) and a private key (**PriKey**). For details about the relationship between keys, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
- Randomly create a key instance for subsequent encryption and decryption.
- Convert external or stored binary data into a key instance for subsequent encryption and decryption.
- Obtain the binary data of a key for storage or transmission.
> **NOTE**<br>The key instance can be a symmetric key instance (**SymKey**) or an asymmetric key pair instance (**KeyPair**). The **KeyPair** instance consists a public key (**PubKey**) and a private key (**PriKey**). For details about the relationship between keys, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
**Available APIs**
......@@ -32,10 +29,10 @@ The table below describes the APIs used in this guide.
|AsyKeyGenerator|generateKeyPair() : Promise\<KeyPair>|Generates an asymmetric key pair randomly. This API uses a promise to return the result.|
|SymKeyGenerator|generateSymKey(callback : AsyncCallback\<SymKey>) : void|Generates a symmetric key randomly. This API uses an asynchronous callback to return the result.|
|SymKeyGenerator|generateSymKey() : Promise\<SymKey>|Generates a symmetric key randomly. This API uses a promise to return the result.|
| AsyKeyGenerator | convertKey(pubKey : DataBlob, priKey : DataBlob, callback : AsyncCallback\<KeyPair>) : void | Converts the binary data into a key pair. This API uses an asynchronous callback to return the result.<br>(**pubKey** or **priKey** can be **null**. That is, you can pass in only **pubKey** or **priKey**. As a result, the return **KeyPair** instance contains only the public or private key.) |
| AsyKeyGenerator | convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair> | Converts the binary data into a key pair. This API uses a promise to return the result.<br>(**pubKey** or **priKey** can be **null**. That is, you can pass in only **pubKey** or **priKey**. As a result, the returned **KeyPair** instance contains only the public or private key.) |
| SymKeyGenerator | convertKey(key : DataBlob, callback : AsyncCallback\<SymKey>) : void| Converts the binary data into a symmetric key. This API uses an asynchronous callback to return the result. |
| SymKeyGenerator |convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair>| Converts the binary data into a symmetric key. This API uses a promise to return the result. |
| AsyKeyGenerator | convertKey(pubKey : DataBlob, priKey : DataBlob, callback : AsyncCallback\<KeyPair>) : void | Converts binary data into a key pair. This API uses an asynchronous callback to return the result.<br>(**pubKey** or **priKey** can be **null**. That is, you can pass in only **pubKey** or **priKey**. As a result, the returned **KeyPair** instance contains only the public or private key.)|
| AsyKeyGenerator | convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair> | Converts binary data into a key pair. This API uses a promise to return the result.<br>(**pubKey** or **priKey** can be **null**. That is, you can pass in only **pubKey** or **priKey**. As a result, the returned **KeyPair** instance contains only the public or private key.)|
| SymKeyGenerator | convertKey(key : DataBlob, callback : AsyncCallback\<SymKey>) : void| Converts binary data into a symmetric key. This API uses an asynchronous callback to return the result.|
| SymKeyGenerator |convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair>| Converts binary data into a symmetric key. This API uses a promise to return the result.|
| Key | getEncoded() : DataBlob; | Obtains the binary data of a key. (The child class instances of **Key** include **SymKey**, **PubKey**, and **PriKey**.)|
**How to Develop**
......@@ -46,7 +43,7 @@ Example 1: Randomly generate an asymmetric key pair and obtain its binary data.
2. Randomly generate an asymmetric key pair using **AsyKeyGenerator**.
3. Obtain binary data of the key pair generated.
For example, randomly generate an RSA key (1024 bits and two primes) using promise-based APIs.
The following sample code presents how to randomly generate an RSA key (1024 bits and two primes) using promise-based APIs:
```javascript
import cryptoFramework from '@ohos.security.cryptoFramework';
......@@ -75,7 +72,7 @@ Example 2: Randomly generate a symmetric key and obtain its binary data.
2. Randomly generate a symmetric key using **SymKeyGenerator**.
3. Obtain binary data of the key generated.
For example, randomly generate an AES key (256 bits) using promise-based APIs.
The following sample code presents how to randomly generate a 256-bit AES key using promise-based APIs:
```javascript
import cryptoFramework from '@ohos.security.cryptoFramework';
......@@ -103,7 +100,7 @@ function testGenerateAesKey() {
Example 3: Generate an asymmetric key pair from the binary RSA key data.
1. Obtain the binary data of the RSA public or private key. The public key must comply with the ASN.1 syntax, X.509 specifications, and DER encoding format. The private key must comply with the ASN.1 syntax, PKCS #8 specifications, and DER encoding format.
2. Create an **AsyKeyGenerator** instance and call **convertKey()** to convert the key binary data (data of the private or public key, or both) passed in to a **KeyPair** instance.
2. Create an **AsyKeyGenerator** instance and call **convertKey()** to convert the key binary data (data of the private or public key, or both) into a **KeyPair** instance.
```javascript
import cryptoFramework from '@ohos.security.cryptoFramework';
......@@ -123,17 +120,19 @@ function convertAsyKey() {
> **NOTE**
>
> The public key returned by **convertKey()** must be in the DER format complying with X.509 specifications, and the private key must be in the DER format complying with PKCS #8 specifications.
> The public key material to be converted in **convertKey()** must be in the DER format complying with X.509 specifications, and the private key material must be in the DER format complying with PKCS #8 specifications.
Example 4: Generate an asymmetric key pair from the binary ECC key data.
Example 4: Generate an asymmetric key pair from the binary ECC key data.
1. Obtain the ECC binary key data and encapsulate it into a **DataBlob** instance.
2. Call **convertKey()** to convert the key binary data (data of the private or public key, or both) passed in to a **KeyPair** instance.
2. Call **convertKey()** to convert the key binary data (data of the private or public key, or both) into to a **KeyPair** instance.
```javascript
function convertEccAsyKey() {
let pubKeyArray = new Uint8Array([4,196,55,233,100,227,224,38,38,5,128,81,53,112,129,7,59,189,116,105,182,87,190,85,31,248,172,116,213,7,206,85,190,65,169,193,138,173,232,187,74,54,78,251,29,131,192,223,251,227,170,138,80,7,98,193,216,168,235,114,255,188,70,134,104]);
let priKeyArray = new Uint8Array([255,70,89,220,189,19,41,157,175,173,83,60,74,216,195,96,24,181,231,23,112,247,150,126,15,155,24,79,33,97,31,225]);
let pubKeyArray = new Uint8Array([48,89,48,19,6,7,42,134,72,206,61,2,1,6,8,42,134,72,206,61,3,1,7,3,66,0,4,83,96,142,9,86,214,126,106,247,233,92,125,4,128,138,105,246,162,215,71,81,58,202,121,26,105,211,55,130,45,236,143,55,16,248,75,167,160,167,106,2,152,243,44,68,66,0,167,99,92,235,215,159,239,28,106,124,171,34,145,124,174,57,92]);
let priKeyArray = new Uint8Array([48,49,2,1,1,4,32,115,56,137,35,207,0,60,191,90,61,136,105,210,16,27,4,171,57,10,61,123,40,189,28,34,207,236,22,45,223,10,189,160,10,6,8,42,134,72,206,61,3,1,7]);
let pubKeyBlob = { data: pubKeyArray };
let priKeyBlob = { data: priKeyArray };
let generator = cryptoFrameWork.createAsyKeyGenerator("ECC256");
......@@ -146,13 +145,13 @@ function convertEccAsyKey() {
}
```
Example 5: Generate a symmetric key from binary key data.
Example 5: Generate a symmetric key from binary data.
1. Create a **SymKeyGenerator** instance.
2. Generate a symmetric key from the binary data passed in.
3. Obtain binary data of the key generated.
For example, generate a 3DES key (192 bits only) using callback-based APIs.
The following sample code presents how to generate a 3DES key (192 bits only) using callback-based APIs:
```javascript
import cryptoFramework from '@ohos.security.cryptoFramework';
......@@ -201,12 +200,12 @@ function testConvertAesKey() {
**When to Use**
Important data needs to be encrypted in data storage or transmission for security purposes. Typical encryption and decryption operations involve the following:
1. Encrypt and decrypt data using a symmetric key.
2. Encrypt and decrypt data using an asymmetric key pair.
- Encrypt and decrypt data using a symmetric key.
- Encrypt and decrypt data using an asymmetric key pair.
**Available APIs**
For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). <br>Due to the complexity of cryptographic algorithms, the implementation varies depending on the specifications and parameters you use, and cannot be enumerated by sample code. Before you start, understand the APIs in the API reference to ensure correct use of these APIs.
The table below describes the APIs used in this guide.
......@@ -229,7 +228,7 @@ Example 1: Encrypt and decrypt data using a symmetric key.
3. Create a **Cipher** instance.
4. Encrypt or decrypt data.
For example, use AES GCM to encrypt and decrypt data using promise-based APIs.
The following sample code presents how to use the AES-GCM to encrypt and decrypt data with promise-based APIs:
```js
import cryptoFramework from '@ohos.security.cryptoFramework';
......@@ -250,8 +249,9 @@ function genGcmParamsSpec() {
arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0]; // 16 bytes
let dataTag = new Uint8Array(arr);
let tagBlob = {data : dataTag};
let gcmParamsSpec = {iv : ivBlob, aad : aadBlob, authTag : tagBlob, algoName : "GcmParamsSpec"};
let tagBlob = {data : dataTag}; // The authTag of GCM is obtained by doFinal() in encryption and passed in params of init() in decryption.
let gcmParamsSpec = {iv : ivBlob, aad : aadBlob, authTag : tagBlob, algName : "GcmParamsSpec"};
return gcmParamsSpec;
}
......@@ -298,8 +298,8 @@ function testAesGcm() {
}, 10)
}).then(() => {
// Create a SymKeyGenerator instance.
let symAlgoName = 'AES128';
let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgoName);
let symAlgName = 'AES128';
let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
if (symKeyGenerator == null) {
console.error('createSymKeyGenerator failed');
return;
......@@ -311,9 +311,9 @@ function testAesGcm() {
globalGcmParams = genGcmParamsSpec();
// Create a Cipher instance.
let cipherAlgoName = 'AES128|GCM|PKCS7';
let cipherAlgName = 'AES128|GCM|PKCS7';
try {
globalCipher = cryptoFramework.createCipher(cipherAlgoName);
globalCipher = cryptoFramework.createCipher(cipherAlgName);
console.info(`cipher algName: ${globalCipher.algName}`);
} catch (error) {
console.error(`createCipher failed, ${error.code}, ${error.message}`);
......@@ -339,7 +339,7 @@ function testAesGcm() {
let promiseFinal = globalCipher.doFinal(null); // doFinal
return promiseFinal;
}).then(authTag => {
// Obtain the authentication information after encryption.
// In GCM mode, the encrypted authentication information needs to be obtained from the output of doFinal() and passed in globalGcmParams of init() in decryption.
globalGcmParams.authTag = authTag;
return;
}).then(() => {
......@@ -355,7 +355,7 @@ function testAesGcm() {
let promiseFinal = globalCipher.doFinal(null); // doFinal
return promiseFinal;
}).then(finalOutput => {
if (finalOutput == null) {
if (finalOutput == null) { // Check whether the result is null before using finalOutput.data.
console.info('GCM finalOutput is null');
}
}).catch(error => {
......@@ -364,7 +364,7 @@ function testAesGcm() {
}
```
For example, 3DES ECB is used. Generate a key from the existing data to encrypt and decrypt data using callback-based APIs.
The following sample code presents how to use the the 3DES ECB to convert existing data into a key and encrypt and decrypt data using callback-based APIs:
```js
import cryptoFramework from '@ohos.security.cryptoFramework';
......@@ -408,11 +408,11 @@ function genKeyMaterialBlob() {
return {data : keyMaterial};
}
// For example, 3DES ECB is used. Use existing data to generate a key to encrypt and decrypt data, and return the result in a callback.
// Use the 3DES ECB to Generate a key from the existing data and encrypt and decrypt data using callback-based APIs.
function test3DesEcb() {
// Create a SymKeyGenerator instance.
let symAlgoName = '3DES192';
let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgoName);
let symAlgName = '3DES192';
let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
if (symKeyGenerator == null) {
console.error('createSymKeyGenerator failed');
return;
......@@ -420,9 +420,9 @@ function test3DesEcb() {
console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
// Create a Cipher instance.
let cipherAlgoName = '3DES192|ECB|PKCS7';
let cipherAlgName = '3DES192|ECB|PKCS7';
try {
globalCipher = cryptoFramework.createCipher(cipherAlgoName);
globalCipher = cryptoFramework.createCipher(cipherAlgName);
console.info(`cipher algName: ${globalCipher.algName}`);
} catch (error) {
console.error(`createCipher failed, ${error.code}, ${error.message}`);
......@@ -473,7 +473,7 @@ function test3DesEcb() {
console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data));
// doFinal
globalCipher.doFinal(null, (error, finalOutput) => {
if (finalOutput != null) {
if (finalOutput == null) { // Check whether the result is null before using finalOutput.data.
console.info("decrypt plainText:" + uint8ArrayToString(finalOutput.data));
}
})
......@@ -489,12 +489,153 @@ function test3DesEcb() {
}
}
```
The following sample code presents how to call **update()** multiple times to implement AES GCM encryption and decryption by using promise-based APIs:
```javascript
import cryptoFramework from '@ohos.security.cryptoFramework';
var globalCipher;
var globalGcmParams;
var globalKey;
var globalCipherText;
var globalPlainText;
function genGcmParamsSpec() {
let arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0 , 0, 0]; // 12 bytes
let dataIv = new Uint8Array(arr);
let ivBlob = {data : dataIv};
arr = [0, 0, 0, 0 , 0, 0, 0, 0]; // 8 bytes
let dataAad = new Uint8Array(arr);
let aadBlob = {data : dataAad};
arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0]; // 16 bytes
let dataTag = new Uint8Array(arr);
let tagBlob = {data : dataTag};
let gcmParamsSpec = {iv : ivBlob, aad : aadBlob, authTag : tagBlob, algName : "GcmParamsSpec"};
return gcmParamsSpec;
}
// Output the byte streams in hexadecimal format.
function uint8ArrayToShowStr(uint8Array) {
return Array.prototype.map
.call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
.join('');
}
// Convert byte streams into strings in plaintext.
function uint8ArrayToString(array) {
let arrayString = '';
for (let i = 0; i < array.length; i++) {
arrayString += String.fromCharCode(array[i]);
}
return arrayString;
}
// The algorithm library does not limit the number of update() times and the amount of data to be encrypted and decrypted each time. You can use update() multiple times based on the memory usage.
function testAesMultiUpdate() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('testAesMultiUpdate');
}, 10)
}).then(() => {
// Create a SymKeyGenerator instance.
let symAlgName = 'AES128';
let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
if (symKeyGenerator == null) {
console.error('createSymKeyGenerator failed');
return;
}
console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
// Use the key generator to randomly generate a 128-bit symmetric key.
let promiseSymKey = symKeyGenerator.generateSymKey();
// Constructor
globalGcmParams = genGcmParamsSpec();
// Create a Cipher instance.
let cipherAlgName = 'AES128|GCM|PKCS7';
try {
globalCipher = cryptoFramework.createCipher(cipherAlgName);
console.info(`cipher algName: ${globalCipher.algName}`);
} catch (error) {
console.error(`createCipher failed, ${error.code}, ${error.message}`);
return;
}
return promiseSymKey;
}).then(key => {
let encodedKey = key.getEncoded();
console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data));
globalKey = key;
return key;
}).then(key => {
// Initialize the cipher environment and start encryption.
let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
let promiseInit = globalCipher.init(mode, key, globalGcmParams); // init
return promiseInit;
}).then(async () => {
let plainText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the plaintext contains 43 bytes.
let messageArr = [];
let updateLength = 20; // Pass in 20 bytes by update() each time.
globalCipherText = [];
for (let i = 0; i <= plainText.length; i++) {
if ((i % updateLength == 0 || i == plainText.length) && messageArr.length != 0) {
let message = new Uint8Array(messageArr);
let messageBlob = { data : message };
let updateOutput = await globalCipher.update(messageBlob); // Update by segment.
// Combine the result of each update() to obtain the ciphertext. In certain cases, the doFinal() results need to be combined, which depends on the cipher block mode
// and padding mode you use. In this example, the doFinal() result in GCM mode contains authTag but not ciphertext. Therefore, there is no need to combine the results.
globalCipherText = globalCipherText.concat(Array.from(updateOutput.data));
messageArr = [];
}
if (i < plainText.length) {
messageArr.push(plainText.charCodeAt(i));
}
}
return;
}).then(() => {
let promiseFinal = globalCipher.doFinal(null); // doFinal
return promiseFinal;
}).then(authTag => {
// Obtain the authentication information after encryption.
globalGcmParams.authTag = authTag;
return;
}).then(() => {
// Initialize the cipher environment and start decryption.
let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams); // init
return promiseInit;
}).then(async () => {
let updateLength = 20;
let updateTimes = Math.ceil(globalCipherText.length / updateLength); // Round up to the nearest integer.
globalPlainText = "";
for (let i = 0; i < updateTimes; i++) {
let messageArr = globalCipherText.slice(i * updateLength, (i + 1) * updateLength);
let message = new Uint8Array(messageArr);
let messageBlob = { data : message };
let updateOutput = await globalCipher.update(messageBlob); // Pass in data by segment.
globalPlainText += uint8ArrayToString(updateOutput.data); // Restore the original plaintext.
}
return;
}).then(() => {
let promiseFinal = globalCipher.doFinal(null); // doFinal
return promiseFinal;
}).then(finalOutput => {
if (finalOutput == null) {
console.info('GCM finalOutput is null');
}
console.info(`decrypt output: ${globalPlainText}`);
}).catch(error => {
console.error(`catch error, ${error.code}, ${error.message}`);
})
}
```
Example 2: Encrypt and decrypt data using an asymmetric key pair.
1. Generate an RSA key pair.<br> Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA asymmetric key pair.
2. Create a **Cipher** instance.<br> Call **createCipher()** to create a **Cipher** instance, and set the key and encryption/decryption mode.
3. Perform encryption and decryption operations.<br> Call **doFinal()** provided by the **Cipher** instance to encrypt data or decrypt data.
1. Generate an RSA key pair.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA asymmetric key pair.
2. Create a **Cipher** instance.<br>Call **createCipher()** to create a **Cipher** instance, and set the key and encryption/decryption mode.
3. Perform encryption and decryption operations.<br>Call **doFinal()** provided by the **Cipher** instance to encrypt data or decrypt data.
```javascript
import cryptoFramework from "@ohos.security.cryptoFramework"
......@@ -538,25 +679,166 @@ function encryptMessageCallback() {
})
})
}
function decryptMessageProMise() {
let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
let decoder = cryptoFramework.createCipher("RSA1024|PKCS1");
let keyGenPromise = rsaGenerator.generateKeyPair();
let keyPair;
let cipherDataBlob;
let input = { data : stringToUint8Array(plan) };
keyGenPromise.then(rsaKeyPair => {
keyPair = rsaKeyPair;
return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null);
}).then(() => {
return cipher.doFinal(input);
}).then(dataBlob => {
console.info("EncryptOutPut is " + dataBlob.data);
AlertDialog.show({message : "output" + dataBlob.data});
cipherDataBlob = dataBlob;
return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null);
}).then(() => {
return decoder.doFinal(cipherDataBlob);
}).then(decodeData => {
if (decodeData.data.toString() === input.data.toString()) {
AlertDialog.show({message : "decrypt success"});
return;
}
AlertDialog.show({message : "decrypt fail"});
});
}
function decryptMessageCallback() {
let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
let decoder = cryptoFramework.createCipher("RSA1024|PKCS1");
let plainText = "this is cipher text";
let input = {data : stringToUint8Array(plainText) };
let cipherData;
let keyPair;
rsaGenerator.generateKeyPair(function (err, newKeyPair) {
keyPair = newKeyPair;
cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, function (err, data) {
cipher.doFinal(input, function (err, data) {
AlertDialog.show({ message : "EncryptOutPut is " + data.data} );
cipherData = data;
decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, function (err, data) {
decoder.doFinal(cipherData, function (err, data) {
if (input.data.toString() === data.data.toString()) {
AlertDialog.show({ message : "decrype success"} );
return;
}
AlertDialog.show({ message : "decrype fail"} );
});
});
});
});
});
}
```
The following sample code presents how to implement RSA asymmetric encryption and decryption (**doFinal()** is called multiple times):
```javascript
import cryptoFramework from "@ohos.security.cryptoFramework"
function stringToUint8Array(str) {
var arr = [];
for (var i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i));
}
var tmpArray = new Uint8Array(arr);
return tmpArray;
}
// Convert byte streams into strings in plaintext.
function uint8ArrayToString(array) {
let arrayString = '';
for (let i = 0; i < array.length; i++) {
arrayString += String.fromCharCode(array[i]);
}
return arrayString;
}
function encryptLongMessagePromise() {
let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!";
let globalCipherOutput;
let globalDecodeOutput;
var globalKeyPair;
let plainTextSplitLen = 64; // The length of the plaintext to be encrypted or decrypted each time by RSA depends on the number of key bits and padding mode. For details, see the Crypto Framework Overview.
let cipherTextSplitLen = 128; // Length of the ciphertext = Number of key bits/8
let keyGenName = "RSA1024";
let cipherAlgName = "RSA1024|PKCS1";
let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object.
let cipher = cryptoFramework.createCipher(cipherAlgName); // Create a Cipher object.
let decoder = cryptoFramework.createCipher(cipherAlgName); // Create a Decoder object.
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("testRsaMultiDoFinal");
}, 10);
}).then(() => {
return asyKeyGenerator.generateKeyPair(); // Generate an RSA key.
}).then(keyPair => {
globalKeyPair = keyPair; // Save the key to global variables.
return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null);
}).then(async () => {
globalCipherOutput = [];
// Split the plaintext by 64 characters and cyclically call doFinal() to encrypt the plaintext. If a 1024-bit key is used, 128-byte ciphertext is generated each time.
for (let i = 0; i < (globalPlainText.length / plainTextSplitLen); i++) {
let tempStr = globalPlainText.substr(i * plainTextSplitLen, plainTextSplitLen);
let tempBlob = { data : stringToUint8Array(tempStr) };
let tempCipherOutput = await cipher.doFinal(tempBlob);
globalCipherOutput = globalCipherOutput.concat(Array.from(tempCipherOutput.data));
}
console.info(`globalCipherOutput len is ${globalCipherOutput.length}, data is: ${globalCipherOutput.toString()}`);
return;
}).then(() =>{
return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, globalKeyPair.priKey, null);
}).then(async() => {
globalDecodeOutput = [];
// Split and decrypt the ciphertext by 128 bytes, and combine the plaintext obtained each time.
for (let i = 0; i < (globalCipherOutput.length / cipherTextSplitLen); i++) {
let tempBlobData = globalCipherOutput.slice(i * cipherTextSplitLen, (i + 1) * cipherTextSplitLen);
let message = new Uint8Array(tempBlobData);
let tempBlob = { data : message };
let tempDecodeOutput = await decoder.doFinal(tempBlob);
globalDecodeOutput += uint8ArrayToString(tempDecodeOutput.data);
}
if (globalDecodeOutput === globalPlainText) {
console.info(`encode and decode success`);
} else {
console.info(`encode and decode error`);
}
return;
}).catch(error => {
console.error(`catch error, ${error.code}, ${error.message}`);
})
}
```
> **NOTE**
>
> - In RSA encryption and decryption, **init()** cannot be repeatedly called to initialize the **Cipher** instance. You must create a **Cipher** instance for each of encryption and decryption.
> - The RSA encryption has a limit on the length of the plaintext to be encrypted. For details, see "Basic Concepts" in [Crypto Framework Overview](cryptoFramework-overview.md).
> - In RSA encryption and decryption, **init()** cannot be repeatedly called to initialize the **Cipher** instance. You must create a **Cipher** instance for each encryption and decryption.
> - The RSA encryption has a limit on the length of the plaintext to be encrypted. For details, see "Basic Concepts" in [Cryptographic Framework Overview](cryptoFramework-overview.md).
> - In RSA decryption, the length of the ciphertext to be decrypted each time is the number of bits of the RSA key divided by 8.
## Signing Data and Verifying Signatures
## Generating and Verifying a Signature
**When to Use**
A digital signature can be used to verify the authenticity of a message. Typical signing and signature verification operations involve the following:
- Use RSA to sign data and verify the signature.
- Use ECC to sign data and verify the signature.
- Use the RSA to generate and verify a signature.
- Use the ECC to generate and verify a signature.
**Available APIs**
For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). <br>Due to the complexity of cryptographic algorithms, the implementation varies depending on the specifications and parameters you use, and cannot be enumerated by sample code. Before you start, understand the APIs in the API reference to ensure correct use of these APIs.
|Instance|API|Description|
|---|---|---|
......@@ -577,12 +859,12 @@ For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cry
**How to Develop**
Example 1: Use RSA to sign data and verify the signature.
1. Generate an RSA key pair.<br> Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA asymmetric key pair.
2. Create a **Sign** instance.<br> Call **createSign()** to create a **Sign** instance, initialize the **Sign** instance, and set a private key for signing.
3. Generate a signature.<br> Call **update()** provided by the **Sign** class to add the data for signing and call **sign()** to generate a signature.
4. Create a **Verify** instance.<br> Call **createVerify()** to create a **Verify** instance, initialize the instance, and set a public key for signature verification.
5. Verify the signature.<br> Call **update()** provided by the **Verify** class to add signature data and call **verify()** to verify the signature.
Example 1: Use the RSA to generate and verify a signature.
1. Generate an RSA key pair.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA asymmetric key pair.
2. Create a **Sign** instance.<br>Call **createSign()** to create a **Sign** instance, initialize the **Sign** instance, and set a private key for signing.
3. Generate a signature.<br>Call **update()** provided by the **Sign** class to add the data for signing and call **sign()** to generate a signature.
4. Create a **Verify** instance.<br>Call **createVerify()** to create a **Verify** instance, initialize the instance, and set a public key for signature verification.
5. Verify the signature.<br>Call **update()** provided by the **Verify** class to add signature data and call **verify()** to verify the signature.
```javascript
import cryptoFramework from "@ohos.security.cryptoFramework"
......@@ -661,12 +943,12 @@ function verifyMessageCallback() {
}
```
Example 2: Using ECC to sign data and verify the signature.
1. Generate an ECC key.<br> Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an ECC asymmetric key pair.
2. Create a **Sign** instance.<br> Call **createSign()** to create a **Sign** instance, initialize the **Sign** instance, and set a private key for signing.
3. Generate a signature.<br> Call **update()** provided by the **Sign** class to add the data for signing and call **doFinal()** to generate a signature.
4. Create a **Verify** instance.<br> Call **createVerify()** to create a **Verify** instance, initialize the instance, and set a public key for signature verification.
5. Verify the signature.<br> Call **update()** provided by the **Verify** class to add signature data and call **doFinal()** to verify the signature.
Example 2: Use the ECDSA to generate and verify a signature.
1. Generate an ECC key.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an ECC asymmetric key pair.
2. Create a **Sign** instance.<br>Call **createSign()** to create a **Sign** instance, initialize the **Sign** instance, and set a private key for signing.
3. Generate a signature.<br>Call **update()** provided by the **Sign** class to add the data for signing and call **doFinal()** to generate a signature.
4. Create a **Verify** instance.<br>Call **createVerify()** to create a **Verify** instance, initialize the instance, and set a public key for signature verification.
5. Verify the signature.<br>Call **update()** provided by the **Verify** class to add signature data and call **doFinal()** to verify the signature.
```javascript
import cryptoFramework from "@ohos.security.cryptoFramework"
......@@ -745,14 +1027,81 @@ function verifyMessageCallback() {
})
}
```
The following sample code presents how to call **update()** multiple times to implement signing and signature verification:
```javascript
import cryptoFramework from "@ohos.security.cryptoFramework"
function stringToUint8Array(str) {
var arr = [];
for (var i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i));
}
var tmpArray = new Uint8Array(arr);
return tmpArray;
}
function signLongMessagePromise() {
let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
"This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!";
let globalSignData;
let textSplitLen = 64; // Customized data splitting length.
let keyGenName = "RSA1024";
let cipherAlgName = "RSA1024|PKCS1|SHA256";
let globalKeyPair;
let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object.
let signer = cryptoFramework.createSign(cipherAlgName); //Create a cipher object for encryption.
let verifier = cryptoFramework.createVerify(cipherAlgName); // Create a Decoder object for decryption.
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("testRsaMultiUpdate");
}, 10);
}).then(() => {
return asyKeyGenerator.generateKeyPair(); // Generate an RSA key.
}).then(keyPair => {
globalKeyPair = keyPair; // Save the key to global variables.
return signer.init(globalKeyPair.priKey);
}).then(async () => {
// If the plaintext is too large, split the plaintext based on the specified length and cyclically call update() to pass in the plaintext.
for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) {
let tempStr = globalPlainText.substr(i * textSplitLen, textSplitLen);
let tempBlob = { data : stringToUint8Array(tempStr) };
await signer.update(tempBlob);
}
return signer.sign(null);
}).then(data =>{
globalSignData = data.data;
console.info(`globalSignOutput len is ${globalSignData.length}, data is: ${globalSignData.toString()}`);
return verifier.init(globalKeyPair.pubKey);
}).then(async() => {
// Split and decrypt the ciphertext by 128 bytes, and combine the plaintext obtained each time.
for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) {
let tempData = globalPlainText.slice(i * textSplitLen, (i + 1) * textSplitLen);
let tempBlob = { data : stringToUint8Array(tempData) };
await verifier.update(tempBlob);
}
return verifier.verify(null, { data : globalSignData});
}).then(res => {
console.info(`verify res is ${res}`);
}).catch(error => {
console.error(`catch error, ${error.code}, ${error.message}`);
})
}
```
## Generating a Digest
**When to Use**
A message digest is a fixed size numeric representation of the content of a message, computed by a has function. The message digest is sent with the message. The receiver can generate a digest for the message and compare it with the digest received. If the two digests are the same, the message integrity is verified.
A message digest (MD) is a fixed size numeric representation of the content of a message, computed by a has function. It is sent with the message. The receiver can generate a digest for the message and compare it with the digest received. If the two digests are the same, the message integrity is verified.
Typical message digest operations involve the following:
Typical MD operations involve the following:
1. Create an **Md** instance.
2. Add one or more segments of data for generating a digest.
......@@ -776,7 +1125,7 @@ For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cry
**How to Develop**
1. Call **createMd()** to create an **Md** instance.
2. Call **update()** to update the data for computing a digest. **update()** can be called multiple times to update the data by segment.
2. Call **update()** to pass in the data for computing a digest. **update()** can be called multiple times to pass in the data by segment.
3. Call **digest()** to compute a digest.
4. Obtain the digest algorithm and length of the digest generated.
......@@ -805,7 +1154,7 @@ function GenDataBlob(dataBlobLen) {
return dataBlob;
}
// Compute a message digest using promise-based APIs.
// Compute an MD using promise-based APIs.
function doMdByPromise(algName) {
var md;
try {
......@@ -814,8 +1163,13 @@ function doMdByPromise(algName) {
console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
}
console.error("[Promise]: Md algName is: " + md.algName);
// Initial update().
var promiseMdUpdate = md.update(GenDataBlob(12));
promiseMdUpdate.then(() => {
// Call update() multiple times based on service requirements.
promiseMdUpdate = md.update(GenDataBlob(12));
return promiseMdUpdate;
}).then(mdOutput => {
var PromiseMdDigest = md.digest();
return PromiseMdDigest;
}).then(mdOutput => {
......@@ -827,7 +1181,7 @@ function doMdByPromise(algName) {
});
}
// Compute a message digest using callback-based APIs.
// Compute an MD using callback-based APIs.
function doMdByCallback(algName) {
var md;
try {
......@@ -836,13 +1190,19 @@ function doMdByCallback(algName) {
console.error("[Callback]: error code: " + error.code + ", message is: " + error.message);
}
console.error("[Callback]: Md algName is: " + md.algName);
// Initial update().
md.update(GenDataBlob(12), (err,) => {
if (err) {
console.error("[Callback]: err: " + err.code);
}
md.digest((err1, mdOutput) => {
// Call update() multiple times based on service requirements.
md.update(GenDataBlob(12), (err1,) => {
if (err1) {
console.error("[Callback]: err: " + err1.code);
}
md.digest((err2, mdOutput) => {
if (err2) {
console.error("[Callback]: err: " + err2.code);
} else {
console.error("[Callback]: MD result: " + mdOutput.data);
var mdLen = md.getMdLength();
......@@ -850,6 +1210,64 @@ function doMdByCallback(algName) {
}
});
});
});
}
```
The following sample code presents how to call **update()** multiple times to update the MD:
```javascript
import cryptoFramework from "@ohos.security.cryptoFramework"
async function updateData(index, obj, data) {
console.error("update " + (index + 1) + " MB data...");
return obj.update(data);
}
function stringToUint8Array(str) {
var arr = [];
for (var i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i));
}
var tmpUint8Array = new Uint8Array(arr);
return tmpUint8Array;
}
function GenDataBlob(dataBlobLen) {
var dataBlob;
if (dataBlobLen == 12) {
dataBlob = {data: stringToUint8Array("my test data")};
} else {
console.error("GenDataBlob: dataBlobLen is invalid");
dataBlob = {data: stringToUint8Array("my test data")};
}
return dataBlob;
}
function LoopMdPromise(algName, loopSize) {
var md;
try {
md = cryptoFramework.createMd(algName);
} catch (error) {
console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
return;
}
console.error("[Promise]: Md algName is: " + md.algName);
var promiseMdUpdate = md.update(GenDataBlob(12));
promiseMdUpdate.then(() => {
var PromiseMdDigest = md.digest();
return PromiseMdDigest;
}).then(async () => {
for (var i = 0; i < loopSize; i++) {
await updateData(i, md, GenDataBlob(12));
}
var PromiseMdDigest = md.digest();
return PromiseMdDigest;
}).then(mdOutput => {
console.error("[Promise]: MD result: " + mdOutput.data);
var mdLen = md.getMdLength();
console.error("[Promise]: MD len: " + mdLen);
}).catch(error => {
console.error("[Promise]: error: " + error.message);
});
}
```
......@@ -871,7 +1289,7 @@ For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cry
**How to Develop**
1. Generate an ECC key.<br> Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an ECC asymmetric key pair.
1. Generate an ECC key.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an ECC asymmetric key pair.
2. Generate a shared secret by using the private and public ECC keys.
```javascript
......@@ -970,7 +1388,6 @@ function GenDataBlob(dataBlobLen) {
return dataBlob;
}
// Generate a MAC using promise-based APIs.
function doHmacByPromise(algName) {
var mac;
try {
......@@ -988,6 +1405,11 @@ function doHmacByPromise(algName) {
var promiseMacInit = mac.init(symKey);
return promiseMacInit;
}).then(() => {
// Initial update().
var promiseMacUpdate = mac.update(GenDataBlob(12));
return promiseMacUpdate;
}).then(() => {
// Call update() multiple times based on service requirements.
var promiseMacUpdate = mac.update(GenDataBlob(12));
return promiseMacUpdate;
}).then(() => {
......@@ -1023,13 +1445,19 @@ function doHmacByCallback(algName) {
if (err1) {
console.error("[Callback]: err: " + err1.code);
}
// Initial update().
mac.update(GenDataBlob(12), (err2, ) => {
if (err2) {
console.error("[Callback]: err: " + err2.code);
}
mac.doFinal((err3, macOutput) => {
// Call update() multiple times based on service requirements.
mac.update(GenDataBlob(12), (err3, ) => {
if (err3) {
console.error("[Callback]: err: " + err3.code);
}
mac.doFinal((err4, macOutput) => {
if (err4) {
console.error("[Callback]: err: " + err4.code);
} else {
console.error("[Callback]: HMAC result: " + macOutput.data);
var macLen = mac.getMacLength();
......@@ -1039,19 +1467,83 @@ function doHmacByCallback(algName) {
});
});
});
});
}
```
The following sample code presents how to call **update()** multiple times to update the MAC:
```javascript
import cryptoFramework from "@ohos.security.cryptoFramework"
async function updateData(index, obj, data) {
console.error("update " + (index + 1) + " MB data...");
return obj.update(data);
}
function stringToUint8Array(str) {
var arr = [];
for (var i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i));
}
var tmpUint8Array = new Uint8Array(arr);
return tmpUint8Array;
}
function GenDataBlob(dataBlobLen) {
var dataBlob;
if (dataBlobLen == 12) {
dataBlob = {data: stringToUint8Array("my test data")};
} else {
console.error("GenDataBlob: dataBlobLen is invalid");
dataBlob = {data: stringToUint8Array("my test data")};
}
return dataBlob;
}
function LoopHmacPromise(algName, loopSize) {
var mac;
try {
mac = cryptoFramework.createMac(algName);
} catch (error) {
console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
return;
}
console.error("[Promise]: Mac algName is: " + mac.algName);
var KeyBlob = {
data : stringToUint8Array("12345678abcdefgh")
}
var symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
var promiseConvertKey = symKeyGenerator.convertKey(KeyBlob);
promiseConvertKey.then(symKey => {
var promiseMacInit = mac.init(symKey);
return promiseMacInit;
}).then(async () => {
for (var i = 0; i < loopSize; i++) {
await updateData(i, mac, GenDataBlob(12));
}
var promiseMacUpdate = mac.update(GenDataBlob(12));
return promiseMacUpdate;
}).then(() => {
var PromiseMacDoFinal = mac.doFinal();
return PromiseMacDoFinal;
}).then(macOutput => {
console.error("[Promise]: HMAC result: " + macOutput.data);
var macLen = mac.getMacLength();
console.error("[Promise]: MAC len: " + macLen);
}).catch(error => {
console.error("[Promise]: error: " + error.message);
});
}
```
## Generating Random Numbers
## Generating a Random Number
**When to Use**
Typical random number operations involve the following:
1. Generate a random number.
2. Set a seed based on the random number generated.
- Generate a random number.
- Set a seed based on the random number generated.
**Available APIs**
......
# Security Subsystem Changelog
## cl.security.1 ParamsSpec Attribute Name Change
Changed **algoName** of the **ParamsSpec** structure to **algName**.
**Change Impact**
For the released JavaScript APIs that use **ParamsSpec** and its child classes **IvParamsSpec**, **GcmParamsSpec**, and **CcmParamsSpec** as parameters or return values, **algoName** must be changed to **algName**.
The change must be made for all the applications that use these APIs. Otherwise, the compilation in the SDK of the new version cannot be successful.
**Key API/Component Changes**
API prototype before the change:
```ts
interface ParamsSpec {
/**
* Indicates the algorithm name. Should be set before initialization of a cipher object.
* @type { string }
* @syscap SystemCapability.Security.CryptoFramework
* @since 9
*/
algoName : string;
}
```
API prototype after the change:
```ts
interface ParamsSpec {
/**
* Indicates the algorithm name. Should be set before initialization of a cipher object.
* @type { string }
* @syscap SystemCapability.Security.CryptoFramework
* @since 9
*/
algName : string;
}
```
**Adaptation Guide**
Change **algoName** to **algName** in **ParamsSpec** and its child classes **IvParamsSpec**, **GcmParamsSpec**, and **CcmParamsSpec**.
```ts
function genGcmParamsSpec() {
let arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0 , 0, 0]; // 12 bytes
let dataIv = new Uint8Array(arr);
let ivBlob = {data : dataIv};
arr = [0, 0, 0, 0 , 0, 0, 0, 0]; // 8 bytes
let dataAad = new Uint8Array(arr);
let aadBlob = {data : dataAad};
arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0]; // 16 bytes
let dataTag = new Uint8Array(arr);
let tagBlob = {data : dataTag};
let gcmParamsSpec = {iv : ivBlob, aad : aadBlob, authTag : tagBlob, algName : "GcmParamsSpec"};
return gcmParamsSpec;
}
```
For details, see the APIs of **ParamsSpec** in [Crypto Framework](../../../application-dev/reference/apis/js-apis-cryptoFramework.md#paramsspec).
## Change of cl.security.2 ECC Algorithm Parameter Name from ECC512 to ECC521
**Change Impact**
Behavior of released JavaScript APIs will be changed.
The application needs to be adapted to obtain the correct result in the SDK of the new version.
**Key API/Component Changes**
The parameter passed in the APIs is changed from **ECC512** to **ECC521**. The related APIs remain unchanged. For details, see [Key Generation Specifications](../../../application-dev/security/cryptoFramework-overview.md#key-generation-specifications). The following APIs are involved:
cryptoFramework.createAsyKeyGenerator
cryptoFramework.createSign
cryptoFramework.createVerify
cryptoFramework.createKeyAgreement
**Adaptation Guide**
```js
import cryptoFramework from "@ohos.security.cryptoFramework"
let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator("ECC521");
```
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册