提交 2d4a8f3f 编写于 作者: A Annie_wang

update docs

Signed-off-by: NAnnie_wang <annie.wangli@huawei.com>
上级 5b738c8c
因为 它太大了无法显示 source diff 。你可以改为 查看blob
...@@ -4,27 +4,30 @@ ...@@ -4,27 +4,30 @@
> >
> This guide applies to JS development using OpenHarmony API version 9 and SDK version 3.2.7 or later. > This guide applies to JS development using OpenHarmony API version 9 and SDK version 3.2.7 or later.
## Generating and Converting a Key ## Key Generation and Conversion
**When to Use** ### When to Use
Typical key generation operations involve the following: Typical key generation operations involve the following:
1. Randomly create a key instance for subsequent encryption and decryption. 1. Randomly create a key object for subsequent encryption and decryption.
2. Convert external or stored binary data into a key instance for subsequent encryption and decryption. 2. Create a key object based on the specified key parameters for subsequent encryption and decryption.
3. Obtain the binary data of a key for storage or transmission. 3. Convert external or internal binary data into a key object for subsequent encryption and decryption.
> **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). 4. Obtain the binary data of a key object for storage or transmission.
5. Obtain the parameter properties of an asymmetric key object for storage or transmission.
> **NOTE**
>
> The key object can be a symmetric key object (**SymKey**) or an asymmetric key pair object (**KeyPair**). The **KeyPair** object 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** ### Available APIs
For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
The table below describes the APIs used in this guide. The following table describes the APIs used in typical key generation operations. For more information about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
|Instance|API|Description| |Instance|API|Description|
|---|---|---| |---|---|---|
|cryptoFramework|createAsyKeyGenerator(algName : string) : AsyKeyGenerator|Creates an **AsyKeyGenerator** instance.| |cryptoFramework|createAsyKeyGenerator(algName : string) : AsyKeyGenerator|Creates an **AsyKeyGenerator** instance based on the asymmetric key pair specifications specified by **algName**.|
|cryptoFramework|createAsyKeyGeneratorBySpec(asyKeySpec: AsyKeySpec): AsyKeyGeneratorBySpec;|Creates an **AsyKeyGenerator** instance based on the asymmetric key specifications specified by the key parameter.|
|cryptoFramework|createSymKeyGenerator(algName : string) : SymKeyGenerator|Creates a **SymKeyGenerator** instance.| |cryptoFramework|createSymKeyGenerator(algName : string) : SymKeyGenerator|Creates a **SymKeyGenerator** instance.|
|AsyKeyGenerator|generateKeyPair(callback : AsyncCallback\<KeyPair>) : void|Generates an asymmetric key pair randomly. This API uses an asynchronous callback to return the result.| |AsyKeyGenerator|generateKeyPair(callback : AsyncCallback\<KeyPair>) : void|Generates an asymmetric key pair randomly. This API uses an asynchronous callback to return the result.|
|AsyKeyGenerator|generateKeyPair() : Promise\<KeyPair>|Generates an asymmetric key pair randomly. This API uses a promise to return the result.| |AsyKeyGenerator|generateKeyPair() : Promise\<KeyPair>|Generates an asymmetric key pair randomly. This API uses a promise to return the result.|
...@@ -36,17 +39,17 @@ The table below describes the APIs used in this guide. ...@@ -36,17 +39,17 @@ The table below describes the APIs used in this guide.
| SymKeyGenerator |convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair>| Converts binary data into a symmetric key. This API uses a promise 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**.)| | Key | getEncoded() : DataBlob; | Obtains the binary data of a key. (The child class instances of **Key** include **SymKey**, **PubKey**, and **PriKey**.)|
**How to Develop** ### Randomly Generating an RSA Key Pair and Obtaining the Binary Data
Example 1: Randomly generate an asymmetric key pair and obtain its binary data. Randomly generate an asymmetric key pair and obtain its binary data.
1. Create an **AsyKeyGenerator** instance. 1. Create an **AsyKeyGenerator** instance.
2. Randomly generate an asymmetric key pair using **AsyKeyGenerator**. 2. Randomly generate an asymmetric key pair using **AsyKeyGenerator**.
3. Obtain binary data of the key pair generated. 3. Obtain the binary data of the key pair generated.
The following sample code demonstrates how to randomly generate an RSA key (1024 bits and two primes) using promise-based APIs. Example: Randomly generate an RSA key (1024 bits and two primes) in promise mode.
```javascript ```js
import cryptoFramework from '@ohos.security.cryptoFramework'; import cryptoFramework from '@ohos.security.cryptoFramework';
function generateAsyKey() { function generateAsyKey() {
...@@ -67,15 +70,17 @@ function generateAsyKey() { ...@@ -67,15 +70,17 @@ function generateAsyKey() {
} }
``` ```
Example 2: Randomly generate a symmetric key and obtain its binary data. ### Randomly Generating an AES Key and Obtaining the Binary Data
Randomly generate a symmetric key and obtain its binary data.
1. Create a **SymKeyGenerator** instance. 1. Create a **SymKeyGenerator** instance.
2. Randomly generate a symmetric key using **SymKeyGenerator**. 2. Randomly generate a symmetric key using **SymKeyGenerator**.
3. Obtain binary data of the key generated. 3. Obtain the binary data of the key generated.
The following example demonstrates how to randomly generate a 256-bit AES key using promise-based APIs. Example: Randomly generate an AES key (256 bits) in promise mode.
```javascript ```js
import cryptoFramework from '@ohos.security.cryptoFramework'; import cryptoFramework from '@ohos.security.cryptoFramework';
// Output the byte streams in hexadecimal format. // Output the byte streams in hexadecimal format.
...@@ -98,12 +103,14 @@ function testGenerateAesKey() { ...@@ -98,12 +103,14 @@ function testGenerateAesKey() {
} }
``` ```
Example 3: Generate an asymmetric key pair from the binary RSA key data. ### Converting Binary Data into an RSA Key Pair
Generate an RSA asymmetric key pair from the binary 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. 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) into a **KeyPair** instance. 2. Create an **AsyKeyGenerator** instance, and use **convertKey()** to convert the key binary data (data of the private or public key, or both) into a **KeyPair** instance.
```javascript ```js
import cryptoFramework from '@ohos.security.cryptoFramework'; import cryptoFramework from '@ohos.security.cryptoFramework';
function convertAsyKey() { function convertAsyKey() {
...@@ -121,22 +128,24 @@ function convertAsyKey() { ...@@ -121,22 +128,24 @@ function convertAsyKey() {
> **NOTE** > **NOTE**
> >
> 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. > The public key binary data to be converted by **convertKey()** must be in the DER format complying with X.509 specifications, and the private key binary data must be in the DER format complying with PKCS #8 specifications.
Example 4: Generate an asymmetric key pair from the binary ECC key data. ### Converting Binary Data into an ECC Key Pair
Generate an ECC asymmetric key pair from the binary data.
1. Obtain the ECC binary key data and encapsulate it into a **DataBlob** instance. 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) into a **KeyPair** instance. 2. Use **convertKey()** to convert the binary data (data of the private or public key, or both) into a **KeyPair** instance.
```javascript ```js
import cryptoFramework from "@ohos.security.cryptoFramework" import cryptoFramework from '@ohos.security.cryptoFramework';
function convertEccAsyKey() { function convertEccAsyKey() {
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 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 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 pubKeyBlob = { data: pubKeyArray };
let priKeyBlob = { data: priKeyArray }; let priKeyBlob = { data: priKeyArray };
let generator = cryptoFramework.createAsyKeyGenerator("ECC256"); let generator = cryptoFrameWork.createAsyKeyGenerator("ECC256");
generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => { generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => {
if (error) { if (error) {
AlertDialog.show({message : "Convert keypair fail"}); AlertDialog.show({message : "Convert keypair fail"});
...@@ -146,15 +155,17 @@ function convertEccAsyKey() { ...@@ -146,15 +155,17 @@ function convertEccAsyKey() {
} }
``` ```
Example 5: Generate a symmetric key from binary data. ### Converting Binary Data into a 3DES Key
Generate a symmetric key from the binary data.
1. Create a **SymKeyGenerator** instance. 1. Create a **SymKeyGenerator** instance.
2. Generate a symmetric key from the binary data passed in. 2. Convert the binary data into a **SymKey** instance.
3. Obtain binary data of the key generated. 3. Obtain the binary data of the key instance generated.
The following example demonstrates how to generate a 3DES key (192 bits only) using callback-based APIs. Example: Generate a 3DES key (192 bits only) in callback mode.
```javascript ```js
import cryptoFramework from '@ohos.security.cryptoFramework'; import cryptoFramework from '@ohos.security.cryptoFramework';
// Output the byte streams in hexadecimal format. // Output the byte streams in hexadecimal format.
...@@ -189,48 +200,259 @@ function testConvertAesKey() { ...@@ -189,48 +200,259 @@ function testConvertAesKey() {
let encodedKey = key.getEncoded(); // Obtain the binary data of the symmetric key and output a 192-bit byte stream. let encodedKey = key.getEncoded(); // Obtain the binary data of the symmetric key and output a 192-bit byte stream.
console.info('key getEncoded hex: ' + uint8ArrayToShowStr(encodedKey.data)); console.info('key getEncoded hex: ' + uint8ArrayToShowStr(encodedKey.data));
}) })
} catch (error) { // Throw an exception immediately in synchronous mode when an error is detected during the parameter check. } catch (error) { // Throw an exception immediately after an error is detected during the parameter check.
console.error(`convertKey failed, ${error.code}, ${error.message}`); console.error(`convertKey failed, ${error.code}, ${error.message}`);
return; return;
} }
} }
``` ```
## Encrypting and Decrypting Data ## Generating an Asymmetric Key Object and Obtaining Key Parameters
### When to Use
Typical key generation operations involve the following:
1. Create a key object based on the specified asymmetric key parameters for subsequent encryption and decryption.
2. Obtain the parameter properties of an asymmetric key object for storage or transmission.
> **NOTE**
>
> - Key parameters can be used to generate asymmetric keys from API version 10.
> - Asymmetric systems use a public key (**PubKey**) to encrypt data and a related private key (**PriKey**) to decrypt it. The public key and private key form a key pair (**KeyPair**). For details about asymmetric key parameters, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
### Available APIs
The following table describes the APIs used in typical key generation operations. For more information about the APIs, see [AsyKeyGeneratorBySpec](../reference/apis/js-apis-cryptoFramework.md#asykeygeneratorbyspec10).
|Instance|API|Description|
|---|---|---|
|AsyKeyGeneratorBySpec|generateKeyPair(callback: AsyncCallback<KeyPair>): void;|Generates a **KeyPair** instance based on the key parameters. This API uses an asynchronous callback to return the result.|
|AsyKeyGeneratorBySpec|generateKeyPair(): Promise<KeyPair>;|Generates a **KeyPair** instance based on the key parameters. This API uses a promise to return the result.|
|AsyKeyGeneratorBySpec|generatePriKey(callback: AsyncCallback<KeyPair>): void;|Generates a **PriKey** instance based on the key parameters. This API uses an asynchronous callback to return the result.|
|AsyKeyGeneratorBySpec|generatePriKey(): Promise<KeyPair>;|Generates a **PriKey** instance based on the key parameters. This API uses a promise to return the result.|
|AsyKeyGeneratorBySpec|generatePubKey(callback: AsyncCallback<KeyPair>): void;|Generates a **PubKey** instance based on the key parameters. This API uses an asynchronous callback to return the result.|
|AsyKeyGeneratorBySpec|generatePubKey(): Promise<KeyPair>;|Generates a **PubKey** instance based on the key parameters. This API uses a promise to return the result.|
| PriKey | getAsyKeySpec(itemType: AsyKeySpecItem): bigint \| string \| number; | Obtains the key specifications of a **PriKey** instance.|
| PubKey | getAsyKeySpec(itemType: AsyKeySpecItem): bigint \| string \| number; | Obtains the key specifications of a **PubKey** instance.|
### Generating an ECC Key Pair and Obtaining Key Specifications
Generate an ECC key pair based on parameters and obtain the key specifications.
1. Create an **AsyKeyGenerator** based on key parameters.
2. Use the **AsyKeyGenerator** to generate an asymmetric key pair based on the specified key parameters.
3. Obtain the key specifications of a key object.
Example: Generate an ECC key based on key parameters in promise mode.
```js
import cryptoFramework from '@ohos.security.cryptoFramework';
// Print bigint information.
function showBigIntInfo(bnName, bnValue) {
console.warn(bnName + ":");
console.warn(". Decimal: " + bnValue.toString());
console.warn(". Hexadecimal: " + bnValue.toString(16));
console.warn (". Length (bits): " + bnValue.toString(2).length);
}
// Construct the EccCommonSpec struct based on the key specifications. The EccCommonSpec struct defines the common parameters of the ECC private key and public key.
function genEccCommonSpec() {
let fieldFp = {
fieldType : "Fp",
p : BigInt("0xffffffffffffffffffffffffffffffff000000000000000000000001")
}
let G = {
x : BigInt("0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"),
y : BigInt("0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34")
}
let eccCommonSpec = {
algName : "ECC",
specType : cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC,
field : fieldFp,
a : BigInt("0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe"),
b : BigInt("0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4"),
g : G,
n : BigInt("0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d"),
h : 1
}
return eccCommonSpec;
}
// Print the ECC key specifications.
function showEccSpecDetailInfo(key, keyType) {
console.info("show detail of " + keyType + ":");
try {
let p = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FP_P_BN);
showBigIntInfo("--- p", p); //length is 224, hex : ffffffffffffffffffffffffffffffff000000000000000000000001
let a = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_A_BN);
showBigIntInfo("--- a", a); // length is 224, hex : fffffffffffffffffffffffffffffffefffffffffffffffffffffffe
let b = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_B_BN);
showBigIntInfo("--- b", b); // length is 224, hex : b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4
let gX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_X_BN);
showBigIntInfo("--- gX", gX); // length is 224, hex : b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21
let gY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_Y_BN);
showBigIntInfo("--- gY", gY); // length is 224, hex : bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34
let n = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_N_BN);
showBigIntInfo("--- n", n); // length is 224, hex : ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d
let h = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_H_NUM);
console.warn("--- h: " + h); //key h: 1
let fieldType = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_TYPE_STR);
console.warn("--- field type: " + fieldType); // key field type: Fp
let fieldSize = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_SIZE_NUM);
console.warn("--- field size: " + fieldSize); // key field size: 224
let curveName = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_CURVE_NAME_STR);
console.warn("--- curve name: " + curveName); // key curve name: NID_secp224r1
if (keyType == "priKey") {
let sk = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_SK_BN);
showBigIntInfo("--- sk", sk);
} else if (keyType == "pubKey") {
let pkX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_X_BN);
showBigIntInfo("--- pkX", pkX);
let pkY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_Y_BN);
showBigIntInfo("--- pkY", pkY);
}
} catch (error) {
console.error("getAsyKeySpec error");
console.error("error code: " + error.code + ", message is: " + error.message);
}
}
// Generate an ECC key pair based on the EccCommonSpec instance and obtain the key specifications.
function testEccUseCommKeySpecGet()
{
try {
let commKeySpec = genEccCommonSpec(); // Construct the EccCommonSpec object.
let generatorBySpec = cryptoFramework.createAsyKeyGeneratorBySpec(commKeySpec); // Create an AsyKeyGenerator instance based on the EccCommonSpec object.
let keyPairPromise = generatorBySpec.generateKeyPair(); // Generate an ECC key pair.
keyPairPromise.then( keyPair => {
showEccSpecDetailInfo(keyPair.priKey, "priKey"); // Obtain the ECC specifications of the private key.
showEccSpecDetailInfo(keyPair.pubKey, "pubKey"); // Obtain the ECC specifications of the public key.
}).catch(error => {
console.error("generateComm error");
console.error("error code: " + error.code + ", message is: " + error.message);
})
} catch(error) {
console.error("testEccUseCommSpec error");
console.error("error code: " + error.code + ", message is: " + error.message);
}
}
```
### Generating an RSA Public Key and Obtaining Key Specifications
Generate an RSA public key based on parameters and obtain key specifications.
1. Create an **AsyKeyGenerator** based on key parameters.
2. Use the **AsyKeyGenerator** to generate the public key of an asymmetric key pair.
3. Obtain the key specifications of the public key object.
Example: Generate an RSA public key based on key parameters in callback mode.
```js
import cryptoFramework from '@ohos.security.cryptoFramework';
// Generate RSA public key specifications.
function genRsaPubKeySpec(nIn : bigint, eIn : bigint) {
let rsaCommSpec = { n : nIn, algName : "RSA", specType : cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC };
let rsaPubKeySpec = { params: rsaCommSpec, pk : eIn, algName : "RSA", specType : cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC };
return rsaPubKeySpec;
}
**When to Use** // Construct an RSA public key specifications object based on the key parameters.
function genRsa2048PubKeySpec() {
let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25");
let eIn = BigInt("0x010001");
return genRsaPubKeySpec(nIn, eIn);
}
// Compare the RSA public key specifications with the expected values.
function compareRsaPubKeyBySpec(rsaKeySpec, n, e) {
if (rsaKeySpec.params.n != n) {
return false;
}
if (rsaKeySpec.pk != e) {
return false;
}
return true;
}
// Generate an RSA public key based on the RSA public key specifications, obtain the key specifications, and compare the key specifications with the expected values.
function rsaUsePubKeySpecGetCallback() {
let rsaPubKeySpec = genRsa2048PubKeySpec();
let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaPubKeySpec);
rsaGeneratorSpec.generatePubKey((error, key) => {
let pubKey = key;
let nBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_N_BN);
let eBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_PK_BN);
if (compareRsaPubKeyBySpec(rsaPubKeySpec, nBN, eBN) != true) {
AlertDialog.show({ message : "error pub key big number"} );
} else {
console.info("n, e in the pubKey are same as the spec.");
}
if (error) {
console.error("generate pubKey error" + "error code: " + error.code + "error message" + error.message);
}
});
}
```
## Encryption and Decryption
### 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: 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. 1. Encrypt and decrypt data using a symmetric key.
2. Encrypt and decrypt data using an asymmetric key pair. 2. Encrypt and decrypt data using an asymmetric key pair.
3. Obtain and set the **CipherSpecItem** parameter when the PKCS1_OAEP padding mode is used in RSA.
> **NOTE**
>
> - From API version 10, [CipherSpecItem](../reference/apis/js-apis-cryptoFramework.md#cipherspecitem10) can be obtained and set when the PKCS1_OAEP padding mode is used in RSA.
> - From API version 10, the string parameter without the key length is supported in encryption and decryption.
### Available APIs
**Available APIs** The following table describes the APIs used in the typical encryption and decryption operations. For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
> **NOTE**
>
> Due to complexity of cryptographic algorithms, the implementation varies depending on the key specifications and parameters you use, and cannot be enumerated by sample code. Before you start, understand the APIs to ensure correct use of these APIs.
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.
|Instance|API|Description| |Instance|API|Description|
|---|---|---| |---|---|---|
|cryptoFramework|createCipher(transformation : string) : Cipher|Creates a **Cipher** instance.| |cryptoFramework|createCipher(transformation : string) : Cipher|Creates a **Cipher** instance based on the algorithm specified by **transformation**.|
|Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec, callback : AsyncCallback\<void>) : void|Sets a key and initializes the **Cipher** instance. This API uses an asynchronous callback to return the result.| |Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec, callback : AsyncCallback\<void>) : void|Initializes the **Cipher** instance. This API uses an asynchronous callback to return the result.|
|Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec) : Promise\<void>|Sets a key and initializes the **Cipher** instance. This API uses a promise to return the result.| |Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec) : Promise\<void>|Initializes the **Cipher** instance. This API uses a promise to return the result.|
|Cipher|update(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Updates the data for encryption and decryption. This API uses an asynchronous callback to return the result.| |Cipher|update(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Updates the data for encryption and decryption. This API uses an asynchronous callback to return the result.|
|Cipher|update(data : DataBlob) : Promise\<DataBlob>|Updates the data for encryption and decryption. This API uses a promise to return the result.| |Cipher|update(data : DataBlob) : Promise\<DataBlob>|Updates the data for encryption and decryption. This API uses a promise to return the result.|
|Cipher|doFinal(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Finalizes the encryption or decryption. This API uses an asynchronous callback to return the result.| |Cipher|doFinal(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Finalizes the encryption or decryption. This API uses an asynchronous callback to return the result.|
|Cipher|doFinal(data : DataBlob) : Promise\<DataBlob>|Finalizes the encryption or decryption. This API uses a promise to return the result.| |Cipher|doFinal(data : DataBlob) : Promise\<DataBlob>|Finalizes the encryption or decryption. This API uses a promise to return the result.|
|Cipher|getCipherSpec(itemType: CipherSpecItem): string \| Uint8Array|Obtains cipher specifications. Currently, only the RSA is supported.|
|Cipher|setCipherSpec(itemType: CipherSpecItem, itemValue: Uint8Array): void|Sets cipher specifications. Currently, only the RSA is supported.|
**How to Develop** ### Encrypting and Decrypting Data Using AES GCM (Promise)
Example 1: Encrypt and decrypt data using a symmetric key. Encrypt and decrypt data using an AES symmetric key.
1. Create a **SymKeyGenerator** instance. 1. Create a **SymKeyGenerator** instance.
2. Use the key generator to generate a symmetric key. 2. Use the **SymKeyGenerator** to randomly generate a symmetric key.
3. Create a **Cipher** instance. 3. Create a **Cipher** instance.
4. Encrypt or decrypt data. 4. Encrypt or decrypt data.
The following example demonstrates how to use the AES-GCM to encrypt and decrypt data with promise-based APIs.
```js ```js
import cryptoFramework from '@ohos.security.cryptoFramework'; import cryptoFramework from '@ohos.security.cryptoFramework';
...@@ -281,17 +503,7 @@ function uint8ArrayToString(array) { ...@@ -281,17 +503,7 @@ function uint8ArrayToString(array) {
return arrayString; return arrayString;
} }
function genKeyMaterialBlob() { // Automatically generate an AES GCM key in promise mode.
let arr = [
0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c,
0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes)
let keyMaterial = new Uint8Array(arr);
return {data : keyMaterial};
}
// Automatically generate a key in AES GCM mode and return the result in a promise.
function testAesGcm() { function testAesGcm() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
setTimeout(() => { setTimeout(() => {
...@@ -308,7 +520,7 @@ function testAesGcm() { ...@@ -308,7 +520,7 @@ function testAesGcm() {
console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`); console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
// Use the key generator to randomly generate a 128-bit symmetric key. // Use the key generator to randomly generate a 128-bit symmetric key.
let promiseSymKey = symKeyGenerator.generateSymKey(); let promiseSymKey = symKeyGenerator.generateSymKey();
// Constructor // Generate GCM parameter specifications.
globalGcmParams = genGcmParamsSpec(); globalGcmParams = genGcmParamsSpec();
// Create a Cipher instance. // Create a Cipher instance.
...@@ -344,7 +556,7 @@ function testAesGcm() { ...@@ -344,7 +556,7 @@ function testAesGcm() {
globalGcmParams.authTag = authTag; globalGcmParams.authTag = authTag;
return; return;
}).then(() => { }).then(() => {
// Initialize the cipher environment and start decryption. // Initialize the Cipher instance and start decryption.
let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams); // init let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams); // init
return promiseInit; return promiseInit;
...@@ -365,7 +577,14 @@ function testAesGcm() { ...@@ -365,7 +577,14 @@ function testAesGcm() {
} }
``` ```
The following example demonstrates how to use the the 3DES ECB to convert existing data into a key and encrypt and decrypt data using callback-based APIs. ### Encrypting and Decrypting Data Using a 3DES ECB Symmetric Key (Callback)
Encrypt and decrypt data using a 3DES symmetric key.
1. Create a **SymKeyGenerator** instance.
2. Generate a key based on the existing binary data.
3. Create a **Cipher** instance.
4. Encrypt or decrypt data using the **Cipher** instance.
```js ```js
import cryptoFramework from '@ohos.security.cryptoFramework'; import cryptoFramework from '@ohos.security.cryptoFramework';
...@@ -409,7 +628,7 @@ function genKeyMaterialBlob() { ...@@ -409,7 +628,7 @@ function genKeyMaterialBlob() {
return {data : keyMaterial}; return {data : keyMaterial};
} }
// Use the 3DES ECB to Generate a key from the existing data and encrypt and decrypt data using callback-based APIs. // Generate a 3DES ECB key from the existing data in callback mode.
function test3DesEcb() { function test3DesEcb() {
// Create a SymKeyGenerator instance. // Create a SymKeyGenerator instance.
let symAlgName = '3DES192'; let symAlgName = '3DES192';
...@@ -444,7 +663,7 @@ function test3DesEcb() { ...@@ -444,7 +663,7 @@ function test3DesEcb() {
console.info('key getEncoded hex: ' + uint8ArrayToShowStr(encodedKey.data)); console.info('key getEncoded hex: ' + uint8ArrayToShowStr(encodedKey.data));
globalKey = key; globalKey = key;
// Initialize the cipher environment and start encryption. // Initialize the Cipher instance and start encryption.
let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE; let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
// init // init
globalCipher.init(mode, key, null, (err, ) => { globalCipher.init(mode, key, null, (err, ) => {
...@@ -465,7 +684,7 @@ function test3DesEcb() { ...@@ -465,7 +684,7 @@ function test3DesEcb() {
globalCipherText = new Uint8Array(globalCipherText); globalCipherText = new Uint8Array(globalCipherText);
globalCipherText = {data : globalCipherText}; globalCipherText = {data : globalCipherText};
} }
// Initialize the cipher environment and start decryption. // Initialize the Cipher instance and start decryption.
let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
// init // init
globalCipher.init(mode, globalKey, null, (err, ) => { globalCipher.init(mode, globalKey, null, (err, ) => {
...@@ -490,9 +709,19 @@ function test3DesEcb() { ...@@ -490,9 +709,19 @@ function test3DesEcb() {
} }
} }
``` ```
The following example demonstrates how to call **update()** multiple times to implement AES GCM encryption and decryption by using promise-based APIs.
```javascript ### Encrypting and Decrypting Data Using an AES GCM Symmetric Key by Segment (Promise)
Use an AES symmetric key to encrypt and decrypt a large amount of data by segment using **update()**.
1. Create a **SymKeyGenerator** instance.
2. Generate a key based on the existing binary data.
3. Create a **Cipher** instance.
4. Encrypt or decrypt data.
Example: Encrypt and decrypt a large amount in AES GCM mode by calling **update()** multiple times in promise mode.
```js
import cryptoFramework from '@ohos.security.cryptoFramework'; import cryptoFramework from '@ohos.security.cryptoFramework';
var globalCipher; var globalCipher;
...@@ -550,7 +779,7 @@ function testAesMultiUpdate() { ...@@ -550,7 +779,7 @@ function testAesMultiUpdate() {
console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`); console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
// Use the key generator to randomly generate a 128-bit symmetric key. // Use the key generator to randomly generate a 128-bit symmetric key.
let promiseSymKey = symKeyGenerator.generateSymKey(); let promiseSymKey = symKeyGenerator.generateSymKey();
// Constructor // Construct key specifications.
globalGcmParams = genGcmParamsSpec(); globalGcmParams = genGcmParamsSpec();
// Create a Cipher instance. // Create a Cipher instance.
...@@ -602,7 +831,7 @@ function testAesMultiUpdate() { ...@@ -602,7 +831,7 @@ function testAesMultiUpdate() {
globalGcmParams.authTag = authTag; globalGcmParams.authTag = authTag;
return; return;
}).then(() => { }).then(() => {
// Initialize the cipher environment and start decryption. // Initialize the Cipher instance and start decryption.
let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams); // init let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams); // init
return promiseInit; return promiseInit;
...@@ -632,76 +861,103 @@ function testAesMultiUpdate() { ...@@ -632,76 +861,103 @@ function testAesMultiUpdate() {
} }
``` ```
Example 2: Encrypt and decrypt data using an asymmetric key pair. ### Encrypting and Decrypting Data Using RSA
Encrypt and decrypt data using an RSA asymmetric key pair.
1. Generate an RSA key pair.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA 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. 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. 3. Encrypt and decrypt data.<br>Call **doFinal()** provided by the **Cipher** instance to encrypt data or decrypt data.
```javascript ```js
import cryptoFramework from "@ohos.security.cryptoFramework" import cryptoFramework from "@ohos.security.cryptoFramework"
let plan = "This is cipher test."; let plan = "This is cipher test.";
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str) { function stringToUint8Array(str) {
var arr = []; let arr = [];
for (var i = 0, j = str.length; i < j; ++i) { for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i)); arr.push(str.charCodeAt(i));
} }
var tmpArray = new Uint8Array(arr); return new Uint8Array(arr);
return tmpArray;
} }
// Encrypt the message in promise mode.
function encryptMessageProMise() { function encryptMessageProMise() {
// Create an AsyKeyGenerator instance.
let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
// Create a Cipher instance.
let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
// Generate an asymmetric key pair using the AsyKeyGenerator instance.
let keyGenPromise = rsaGenerator.generateKeyPair(); let keyGenPromise = rsaGenerator.generateKeyPair();
keyGenPromise.then(rsaKeyPair => { keyGenPromise.then(rsaKeyPair => {
let pubKey = rsaKeyPair.pubKey; let pubKey = rsaKeyPair.pubKey;
// Initialize the Cipher instance and use the public key to encrypt the data.
return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null); return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null);
}).then(() => { }).then(() => {
// doFinal
let input = { data : stringToUint8Array(plan) }; let input = { data : stringToUint8Array(plan) };
return cipher.doFinal(input); return cipher.doFinal(input);
}).then(dataBlob => { }).then(dataBlob => {
// Obtain the encrypted data.
console.info("EncryptOutPut is " + dataBlob.data); console.info("EncryptOutPut is " + dataBlob.data);
}); });
} }
// Encrypt the message in callback mode.
function encryptMessageCallback() { function encryptMessageCallback() {
// Create an AsyKeyGenerator instance.
let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
// Create a Cipher instance.
let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
// Generate an asymmetric key pair using the AsyKeyGenerator instance.
rsaGenerator.generateKeyPair(function (err, keyPair) { rsaGenerator.generateKeyPair(function (err, keyPair) {
let pubKey = keyPair.pubKey; let pubKey = keyPair.pubKey;
// Initialize the Cipher instance and use the public key to encrypt the data.
cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, function (err, data) { cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, function (err, data) {
let input = {data : stringToUint8Array(plan) }; let input = {data : stringToUint8Array(plan) };
// doFinal
cipher.doFinal(input, function (err, data) { cipher.doFinal(input, function (err, data) {
// Obtain the encrypted data.
console.info("EncryptOutPut is " + data.data); console.info("EncryptOutPut is " + data.data);
}) })
}) })
}) })
} }
// Encrypt and decrypt the message in promise mode.
function decryptMessageProMise() { function decryptMessageProMise() {
// Create an AsyKeyGenerator instance.
let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
// Create a Cipher instance for encryption.
let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
// Create a Cipher instance for decryption.
let decoder = cryptoFramework.createCipher("RSA1024|PKCS1"); let decoder = cryptoFramework.createCipher("RSA1024|PKCS1");
// Generate an asymmetric key pair using the AsyKeyGenerator instance.
let keyGenPromise = rsaGenerator.generateKeyPair(); let keyGenPromise = rsaGenerator.generateKeyPair();
let keyPair; let keyPair;
let cipherDataBlob; let cipherDataBlob;
let input = { data : stringToUint8Array(plan) }; let input = { data : stringToUint8Array(plan) };
keyGenPromise.then(rsaKeyPair => { keyGenPromise.then(rsaKeyPair => {
keyPair = rsaKeyPair; keyPair = rsaKeyPair;
// Initialize the Cipher instance and use the public key to encrypt the message.
return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null); return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null);
}).then(() => { }).then(() => {
// Call doFinal() to encrypt data.
return cipher.doFinal(input); return cipher.doFinal(input);
}).then(dataBlob => { }).then(dataBlob => {
// Obtain the encrypted information and use it as the input parameter for decryption.
console.info("EncryptOutPut is " + dataBlob.data); console.info("EncryptOutPut is " + dataBlob.data);
AlertDialog.show({message : "output" + dataBlob.data}); AlertDialog.show({message : "output" + dataBlob.data});
cipherDataBlob = dataBlob; cipherDataBlob = dataBlob;
// Initialize the Cipher instance and use the private key to decrypt the message.
return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null); return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null);
}).then(() => { }).then(() => {
// Call doFinal() to decrypt the message.
return decoder.doFinal(cipherDataBlob); return decoder.doFinal(cipherDataBlob);
}).then(decodeData => { }).then(decodeData => {
// Check whether the decrypted data is consistent with the original data.
if (decodeData.data.toString() === input.data.toString()) { if (decodeData.data.toString() === input.data.toString()) {
AlertDialog.show({message : "decrypt success"}); AlertDialog.show({message : "decrypt success"});
return; return;
...@@ -710,27 +966,38 @@ function decryptMessageProMise() { ...@@ -710,27 +966,38 @@ function decryptMessageProMise() {
}); });
} }
// Encrypt and decrypt the message in callback mode.
function decryptMessageCallback() { function decryptMessageCallback() {
// Create an AsyKeyGenerator instance.
let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
// Create a Cipher instance for encryption.
let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
// Create a Cipher instance for decryption.
let decoder = cryptoFramework.createCipher("RSA1024|PKCS1"); let decoder = cryptoFramework.createCipher("RSA1024|PKCS1");
let plainText = "this is cipher text"; let plainText = "this is cipher text";
let input = {data : stringToUint8Array(plainText) }; let input = {data : stringToUint8Array(plainText) };
let cipherData; let cipherData;
let keyPair; let keyPair;
// Generate an asymmetric key pair using the AsyKeyGenerator instance.
rsaGenerator.generateKeyPair(function (err, newKeyPair) { rsaGenerator.generateKeyPair(function (err, newKeyPair) {
keyPair = newKeyPair; keyPair = newKeyPair;
// Initialize the Cipher instance and use the public key to encrypt the message.
cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, function (err, data) { cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, function (err, data) {
// Call doFinal() to encrypt the message.
cipher.doFinal(input, function (err, data) { cipher.doFinal(input, function (err, data) {
// Obtain the encrypted information and use it as the input parameter for decryption.
AlertDialog.show({ message : "EncryptOutPut is " + data.data} ); AlertDialog.show({ message : "EncryptOutPut is " + data.data} );
cipherData = data; cipherData = data;
// Initialize the Cipher instance and use the private key to decrypt the message.
decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, function (err, data) { decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, function (err, data) {
// Call doFinal() to decrypt the message.
decoder.doFinal(cipherData, function (err, data) { decoder.doFinal(cipherData, function (err, data) {
// Check whether the decrypted data is consistent with the original data.
if (input.data.toString() === data.data.toString()) { if (input.data.toString() === data.data.toString()) {
AlertDialog.show({ message : "decrype success"} ); AlertDialog.show({ message : "decryption success"} );
return; return;
} }
AlertDialog.show({ message : "decrype fail"} ); AlertDialog.show({ message : "decryption fail"} );
}); });
}); });
}); });
...@@ -738,17 +1005,25 @@ function decryptMessageCallback() { ...@@ -738,17 +1005,25 @@ function decryptMessageCallback() {
}); });
} }
``` ```
The following example demonstrates how to implement RSA asymmetric encryption and decryption (**doFinal()** is called multiple times).
```javascript ### Encrypting and Decrypting Data Using RSA by Segment
Use an RSA asymmetric key pair to encrypt and decrypt a large amount of data by segment.
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. Encrypt and decrypt data.<br>Call **doFinal()** provided by the **Cipher** instance multiple times to encrypt and decrypt data.
```js
import cryptoFramework from "@ohos.security.cryptoFramework" import cryptoFramework from "@ohos.security.cryptoFramework"
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str) { function stringToUint8Array(str) {
var arr = []; let arr = [];
for (var i = 0, j = str.length; i < j; ++i) { for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i)); arr.push(str.charCodeAt(i));
} }
var tmpArray = new Uint8Array(arr); return new Uint8Array(arr);
return tmpArray;
} }
// Convert byte streams into strings in plaintext. // Convert byte streams into strings in plaintext.
...@@ -784,9 +1059,9 @@ function encryptLongMessagePromise() { ...@@ -784,9 +1059,9 @@ function encryptLongMessagePromise() {
resolve("testRsaMultiDoFinal"); resolve("testRsaMultiDoFinal");
}, 10); }, 10);
}).then(() => { }).then(() => {
return asyKeyGenerator.generateKeyPair(); // Generate an RSA key. return asyKeyGenerator.generateKeyPair(); // Generate an RSA key pair.
}).then(keyPair => { }).then(keyPair => {
globalKeyPair = keyPair; // Save the key to global variables. globalKeyPair = keyPair; // Save the key pair as a global variable.
return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null); return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null);
}).then(async () => { }).then(async () => {
globalCipherOutput = []; globalCipherOutput = [];
...@@ -825,21 +1100,138 @@ function encryptLongMessagePromise() { ...@@ -825,21 +1100,138 @@ function encryptLongMessagePromise() {
> **NOTE** > **NOTE**
> >
> - 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. > - In RSA encryption and decryption, **init()** cannot be repeatedly called to initialize a **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). > - The RSA encryption has a limit on the length of the plaintext to be encrypted. For details, see [Encryption and Decryption](cryptoFramework-overview.md#encryption-and-decryption).
> - 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. > - 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.
## Generating and Verifying a Signature ### Using PKCS1_OAEP in RSA Encryption and Decryption
Use the PKCS1_OAEP padding mode in RSA encryption and decryption in promise mode.
1. Generate an RSA key pair based on the key parameters.<br>Call **createAsyKeyGeneratorBySpec()** to create an **AsyKeyGeneratorBySpec** object and generate an RSA asymmetric key pair. (You can also use **createAsyKeyGenerator()** to randomly generate or convert an RSA key object.)
2. Create a **Cipher** instance.<br>Call **createCipher()** to create a cipher instance, initialize the cipher instance, set the key and encryption/decryption mode, use **setCipherSpec()** to set PKCS1_OAEP **pSource**, and use **update()** to pass in data.
3. Encrypt and decrypt data.<br>Call the **doFinal()** provided by the **Cipher** class to perform encryption or decryption. The **pSource** of the **Cipher** instance to be encrypted must be the same as that decrypted.
```js
import cryptoFramework from "@ohos.security.cryptoFramework"
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str) {
let arr = [];
for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i));
}
return new Uint8Array(arr);
}
// Construct the key parameters of the RSA asymmetric key pair based on the key pair specifications.
function genRsaKeyPairSpec(nIn : bigint, eIn : bigint, dIn : bigint) {
let rsaCommSpec = { n : nIn, algName : "RSA", specType : cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC };
let rsaKeyPairSpec = { params: rsaCommSpec, sk : dIn, pk : eIn, algName : "RSA", specType : cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC };
return rsaKeyPairSpec;
}
// Generate RSA2048 key pair parameters.
function genRsa2048KeyPairSpec() {
let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25");
let eIn = BigInt("0x010001");
let dIn = BigInt("0x6a7df2ca63ead4dda191d614b6b385e0d9056a3d6d5cfe07db1daabee022db08212d97613d3328e0267c9dd23d787abde2afcb306aeb7dfce69246cc73f5c87fdf06030179a2114b767db1f083ff841c025d7dc00cd82435b9a90f695369e94df23d2ce458bc3b3283ad8bba2b8fa1ba62e2dce9accff3799aae7c840016f3ba8e0048c0b6cc4339af7161003a5beb864a0164b2c1c9237b64bc87556994351b27506c33d4bcdfce0f9c491a7d6b0628c7c852be4f0a9c3132b2ed3a2c8881e9aab07e20e17deb074691be677776a78b5c502e05d9bdde72126b3738695e2dd1a0a98a14247c65d8a7ee79432a092cb0721a12df798e44f7cfce0c498147a9b1");
return genRsaKeyPairSpec(nIn, eIn, dIn);
}
function rsaUseSpecDecryptOAEPPromise() {
let plan = "This is cipher test.";
// Obtain the key parameter object of the RSA key pair.
let rsaKeyPairSpec = genRsa2048KeyPairSpec();
// Generate an RSA key pair based on the RSA key parameters.
let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec);
let keyGenPromise = rsaGeneratorSpec.generateKeyPair();
let cipher = cryptoFramework.createCipher("RSA|PKCS1_OAEP|SHA256|MGF1_SHA1");
let decoder = cryptoFramework.createCipher("RSA|PKCS1_OAEP|SHA256|MGF1_SHA1");
let keyPair;
let cipherDataBlob;
// Set the pSource, which defines the encoding input P filled by OAEP.
let pSource = new Uint8Array([1,2,3,4]);
let input = { data : stringToUint8Array(plan) };
// Generate the key pair.
keyGenPromise.then(rsaKeyPair => {
keyPair = rsaKeyPair;
// Initialize the Cipher instance for encryption.
return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null);
}).then(() => {
// Set and obtain the cipher specifications after the initialization.
cipher.setCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR, pSource);
let retP = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR);
// Check whether the obtained PSource is the same as the PSource set.
if (retP.toString() != pSource.toString()) {
AlertDialog.show({message : "error init pSource" + retP});
} else {
console.info("pSource changed ==" + retP);
}
// Obtain other OAEP parameters.
let md = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MD_NAME_STR);
console.info("md == " + md);
let mgf = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF_NAME_STR);
console.info("mgf == " + mgf);
let mgf1Md = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_MD_STR);
console.info("mgf1Md == " + mgf1Md);
return cipher.doFinal(input);
}).then(dataBlob => {
console.info("EncryptOutPut is " + dataBlob.data);
cipherDataBlob = dataBlob;
// The get() and set() operations can be performed before the init() operation of the Cipher object and are equivalent to those after the init() operation. For example, set and get the decoder.
decoder.setCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR, pSource);
let retP = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR);
// Check whether the obtained PSource is the same as the PSource set.
if (retP.toString() != pSource.toString()) {
AlertDialog.show({message : "error init pSource" + retP});
} else {
console.info("pSource changed ==" + retP);
}
// Obtain other OAEP parameters.
let md = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MD_NAME_STR);
console.info("md == " + md);
let mgf = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF_NAME_STR);
console.info("mgf == " + mgf);
let mgf1Md = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_MD_STR);
console.info("mgf1Md == " + mgf1Md);
// Initialize the decryption operation.
return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null);
}).then(() => {
return decoder.doFinal(cipherDataBlob);
}).then(decodeData => {
// The decryption is successful.
if (decodeData.data.toString() === input.data.toString()) {
console.info("oaep decrypt success");
AlertDialog.show({message : " oaep decrypt success"});
} else {
AlertDialog.show({message : "oeap decrypt fail"});
}
});
}
```
## Signing and Signature Verification
**When to Use** ### 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: A digital signature can be used to verify the authenticity of a message. Typical signing and signature verification operations involve the following:
- Use the RSA to generate and verify a signature. 1. Use RSA to generate a signature and verify the signature.
- Use the ECC to generate and verify a signature. 2. Use ECC to generate a signature and verify the signature.
3. Use RSA to generate a signature and verify the signature. Obtain and set **SignSpecItem** when the PSS padding mode is used.
> **NOTE**
>
> - From API version 10, [SignSpecItem](../reference/apis/js-apis-cryptoFramework.md#signspecitem10) can be set and obtained when the PSS padding mode is used.
> - From API version 10, the string parameter without the key length is supported in signature verification.
**Available APIs** ### Available APIs
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 following table describes the APIs used in typical signing and signature verification operations. For more information about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
> **NOTE**
>
> Due to 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 to ensure correct use of these APIs.
|Instance|API|Description| |Instance|API|Description|
|---|---|---| |---|---|---|
...@@ -850,32 +1242,38 @@ For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cry ...@@ -850,32 +1242,38 @@ For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cry
|Sign|update(data : DataBlob) : Promise\<void>|Updates the data for signing. This API uses a promise to return the result.| |Sign|update(data : DataBlob) : Promise\<void>|Updates the data for signing. This API uses a promise to return the result.|
|Sign|sign(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Signs the data. This API uses an asynchronous callback to return the result.| |Sign|sign(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Signs the data. This API uses an asynchronous callback to return the result.|
|Sign|sign(data : DataBlob) : Promise\<DataBlob>|Signs the data. This API uses a promise to return the result.| |Sign|sign(data : DataBlob) : Promise\<DataBlob>|Signs the data. This API uses a promise to return the result.|
|Sign|getSignSpec(itemType: SignSpecItem): string \| number|Obtains the signing specifications. Currently, only the RSA is supported.|
|Sign|setSignSpec(itemType: SignSpecItem, itemValue: number): void|Sets signing specifications. Currently, only the RSA is supported.|
|cryptoFramework|function createVerify(algName : string) : Verify|Creates a **Verify** instance.| |cryptoFramework|function createVerify(algName : string) : Verify|Creates a **Verify** instance.|
|Verify|init(priKey : PriKey, callback : AsyncCallback\<void>) : void|Sets a key and initializes the **Verify** instance. This API uses an asynchronous callback to return the result.| |Verify|init(pubKey : PubKey, callback : AsyncCallback\<void>) : void|Sets a key and initializes the **Verify** instance. This API uses an asynchronous callback to return the result.|
|Verify|init(priKey : PriKey) : Promise\<void>|Sets a key and initializes the **Verify** instance. This API uses a promise to return the result.| |Verify|init(pubKey : PubKey) : Promise\<void>|Sets a key and initializes the **Verify** instance. This API uses a promise to return the result.|
|Verify|update(data : DataBlob, callback : AsyncCallback\<void>) : void|Updates the data for signature verification. This API uses an asynchronous callback to return the result.| |Verify|update(data : DataBlob, callback : AsyncCallback\<void>) : void|Updates the data for signature verification. This API uses an asynchronous callback to return the result.|
|Verify|update(data : DataBlob) : Promise\<void>|Updates the data for signature verification. This API uses a promise to return the result.| |Verify|update(data : DataBlob) : Promise\<void>|Updates the data for signature verification. This API uses a promise to return the result.|
|Verify|verify(data : DataBlob, signatureData : DataBlob, callback : AsyncCallback\<boolean>) : void|Verifies the signature. This API uses an asynchronous callback to return the result.| |Verify|verify(data : DataBlob, signatureData : DataBlob, callback : AsyncCallback\<boolean>) : void|Verifies a signature. This API uses an asynchronous callback to return the result.|
|Verify|verify(data : DataBlob, signatureData : DataBlob) : Promise\<boolean>|Verifies the signature. This API uses a promise to return the result.| |Verify|verify(data : DataBlob, signatureData : DataBlob) : Promise\<boolean>|Verifies a signature. This API uses a promise to return the result.|
|Verify|getVerifySpec(itemType: SignSpecItem): string \| number|Obtains signature verification specifications. Currently, only the RSA is supported.|
|Verify|setVerifySpec(itemType: SignSpecItem, itemValue: number): void|Sets signature verification specifications. Currently, only the RSA is supported.|
**How to Develop** ### Signing and Signature Verification Using RSA
Use RSA to sign data and 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. 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. 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. 3. Generate a signature.<br>Call **update()** provided by the **Sign** class to pass in 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. 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. 5. Verify the signature.<br> Call **update()** provided by the **Verify** class to pass in the signature data and call **verify()** to verify the signature.
```javascript
```js
import cryptoFramework from "@ohos.security.cryptoFramework" import cryptoFramework from "@ohos.security.cryptoFramework"
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str) { function stringToUint8Array(str) {
var arr = []; let arr = [];
for (var i = 0, j = str.length; i < j; ++i) { for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i)); arr.push(str.charCodeAt(i));
} }
var tmpArray = new Uint8Array(arr); return new Uint8Array(arr);
return tmpArray;
} }
let globalKeyPair; let globalKeyPair;
...@@ -887,7 +1285,7 @@ let input2 = { data : stringToUint8Array(plan2) }; ...@@ -887,7 +1285,7 @@ let input2 = { data : stringToUint8Array(plan2) };
function signMessagePromise() { function signMessagePromise() {
let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256"); let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256"); // From API version 10, a Sign instance can be created by specifying a string parameter defining the key specifications.
let keyGenPromise = rsaGenerator.generateKeyPair(); let keyGenPromise = rsaGenerator.generateKeyPair();
keyGenPromise.then( keyPair => { keyGenPromise.then( keyPair => {
globalKeyPair = keyPair; globalKeyPair = keyPair;
...@@ -917,7 +1315,7 @@ function verifyMessagePromise() { ...@@ -917,7 +1315,7 @@ function verifyMessagePromise() {
function signMessageCallback() { function signMessageCallback() {
let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256"); let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256"); // From API version 10, a Sign instance can be created by specifying a string parameter defining the key specifications.
rsaGenerator.generateKeyPair(function (err, keyPair) { rsaGenerator.generateKeyPair(function (err, keyPair) {
globalKeyPair = keyPair; globalKeyPair = keyPair;
let priKey = globalKeyPair.priKey; let priKey = globalKeyPair.priKey;
...@@ -944,23 +1342,26 @@ function verifyMessageCallback() { ...@@ -944,23 +1342,26 @@ function verifyMessageCallback() {
} }
``` ```
Example 2: Use the ECDSA to generate and verify a signature. ### Signing and Signature Verification Using ECDSA
Use the ECDSA 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. 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. 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. 3. Generate a signature.<br>Call **update()** provided by the **Sign** class to pass in 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. 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. 5. Verify the signature.<br>Call **update()** provided by the **Verify** class to pass in the signature data and call **doFinal()** to verify the signature.
```javascript ```js
import cryptoFramework from "@ohos.security.cryptoFramework" import cryptoFramework from "@ohos.security.cryptoFramework"
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str) { function stringToUint8Array(str) {
var arr = []; let arr = [];
for (var i = 0, j = str.length; i < j; ++i) { for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i)); arr.push(str.charCodeAt(i));
} }
var tmpArray = new Uint8Array(arr); return new Uint8Array(arr);
return tmpArray;
} }
let globalKeyPair; let globalKeyPair;
...@@ -1028,17 +1429,27 @@ function verifyMessageCallback() { ...@@ -1028,17 +1429,27 @@ function verifyMessageCallback() {
}) })
} }
``` ```
The following example demonstrates how to call **update()** multiple times to implement signing and signature verification.
```javascript ### Signing and Signature Verification Using RSA by Segment
Use RSA to sign data and verify the signature by segment.
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 the **update()** provided by the **Sign** class multiple times to pass in data by segment 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 the **update()** provided by the **Verify** class multiple times to pass in data by segment and call **verify()** to verify the signature.
```js
import cryptoFramework from "@ohos.security.cryptoFramework" import cryptoFramework from "@ohos.security.cryptoFramework"
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str) { function stringToUint8Array(str) {
var arr = []; let arr = [];
for (var i = 0, j = str.length; i < j; ++i) { for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i)); arr.push(str.charCodeAt(i));
} }
var tmpArray = new Uint8Array(arr); return new Uint8Array(arr);
return tmpArray;
} }
function signLongMessagePromise() { function signLongMessagePromise() {
...@@ -1056,16 +1467,16 @@ function signLongMessagePromise() { ...@@ -1056,16 +1467,16 @@ function signLongMessagePromise() {
let cipherAlgName = "RSA1024|PKCS1|SHA256"; let cipherAlgName = "RSA1024|PKCS1|SHA256";
let globalKeyPair; let globalKeyPair;
let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object. let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object.
let signer = cryptoFramework.createSign(cipherAlgName); //Create a cipher object for encryption. let signer = cryptoFramework.createSign(cipherAlgName); //Create a Sign object for signing.
let verifier = cryptoFramework.createVerify(cipherAlgName); // Create a Decoder object for decryption. let verifier = cryptoFramework.createVerify(cipherAlgName); // Create a Verify object for signature verification.
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
setTimeout(() => { setTimeout(() => {
resolve("testRsaMultiUpdate"); resolve("testRsaMultiUpdate");
}, 10); }, 10);
}).then(() => { }).then(() => {
return asyKeyGenerator.generateKeyPair(); // Generate an RSA key. return asyKeyGenerator.generateKeyPair(); // Generate an RSA key pair.
}).then(keyPair => { }).then(keyPair => {
globalKeyPair = keyPair; // Save the key to global variables. globalKeyPair = keyPair; // Save the key pair as a global variable.
return signer.init(globalKeyPair.priKey); return signer.init(globalKeyPair.priKey);
}).then(async () => { }).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. // If the plaintext is too large, split the plaintext based on the specified length and cyclically call update() to pass in the plaintext.
...@@ -1095,26 +1506,183 @@ function signLongMessagePromise() { ...@@ -1095,26 +1506,183 @@ function signLongMessagePromise() {
} }
``` ```
## Generating a Digest ### Using PSS in RSA Signing and Signature Verification
**When to Use** Use the PSS padding mode in RSA signing and signature verification in callback mode.
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. 1. Generate an RSA key pair based on the key parameters.<br>Call **createAsyKeyGeneratorBySpec** to create an **AsyKeyGeneratorBySpec** object and generate an RSA asymmetric key pair.
2. Create a **Sign** instance.<br>Call **createSign()** to create a **Sign** object, initialize the **Sign** object, set the private key for signing, and set and obtain PSS parameters.
3. Generate a signature.<br>Call **update()** provided by the **Sign** class to pass in the data for signing and call **sign()** to generate a signature.
4. Create a **Verify** instance.<br>Call **createVerify()** to create a **Verify** object, initialize the object, set the public key for signature verification, and set and obtain PSS parameters. The signature verification is successful if the salt length is the same.
5. Verify the signature.<br>Call **update()** provided by the **Verify** class to pass in the signature data and call **verify()** to verify the signature.
Typical MD operations involve the following: ```js
import cryptoFramework from "@ohos.security.cryptoFramework"
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str) {
let arr = [];
for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i));
}
return new Uint8Array(arr);
}
1. Create an **Md** instance. // Construct the key parameters of the RSA asymmetric key pair based on the key pair specifications.
2. Add one or more segments of data for generating a digest. function genRsaKeyPairSpec(nIn : bigint, eIn : bigint, dIn : bigint) {
3. Compute a digest. let rsaCommSpec = { n : nIn, algName : "RSA", specType : cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC };
4. Obtain the algorithm and length of a digest. let rsaKeyPairSpec = { params: rsaCommSpec, sk : dIn, pk : eIn, algName : "RSA", specType : cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC };
return rsaKeyPairSpec;
}
**Available APIs** // Generate RSA2048 key pair parameters.
function genRsa2048KeyPairSpec() {
let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25");
let eIn = BigInt("0x010001");
let dIn = BigInt("0x6a7df2ca63ead4dda191d614b6b385e0d9056a3d6d5cfe07db1daabee022db08212d97613d3328e0267c9dd23d787abde2afcb306aeb7dfce69246cc73f5c87fdf06030179a2114b767db1f083ff841c025d7dc00cd82435b9a90f695369e94df23d2ce458bc3b3283ad8bba2b8fa1ba62e2dce9accff3799aae7c840016f3ba8e0048c0b6cc4339af7161003a5beb864a0164b2c1c9237b64bc87556994351b27506c33d4bcdfce0f9c491a7d6b0628c7c852be4f0a9c3132b2ed3a2c8881e9aab07e20e17deb074691be677776a78b5c502e05d9bdde72126b3738695e2dd1a0a98a14247c65d8a7ee79432a092cb0721a12df798e44f7cfce0c498147a9b1");
return genRsaKeyPairSpec(nIn, eIn, dIn);
}
function verifyMessageCallbackPSS() {
let plan1 = "This is Sign test plan1";
let plan2 = "This is Sign test plan1";
let input1 = { data : stringToUint8Array(plan1) };
let input2 = { data : stringToUint8Array(plan2) };
let globalKeyPair;
let signMessageBlob;
// Obtain the key parameter object of the RSA key pair.
let rsaKeyPairSpec = genRsa2048KeyPairSpec();
// Create an RSA key pair generator.
let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec);
// Both sign() and verify() support the RSA key with or without the length.
let signer = cryptoFramework.createSign("RSA|PSS|SHA256|MGF1_SHA256");
let verifyer = cryptoFramework.createVerify("RSA2048|PSS|SHA256|MGF1_SHA256");
rsaGeneratorSpec.generateKeyPair(function (err, keyPair) {
globalKeyPair = keyPair;
signer.init(globalKeyPair.priKey, function (err, data) {
// After the initialization, set and obtain the PSS parameters.
let setN = 32;
signer.setSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN);
let saltLen = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM);
console.info("SaltLen == " + saltLen);
let tf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM);
console.info("trailer field == " + tf);
let md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR);
console.info("md == " + md);
let mgf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR);
console.info("mgf == " + mgf);
let mgf1Md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR);
console.info("mgf1Md == " + mgf1Md);
signer.update(input1, function (err, data) {
signer.sign(input2, function (err, data) {
// Before signature verification initialization, set and obtain PSS parameters. The functions are the same as those after initialization.
signMessageBlob = data;
AlertDialog.show({message : "res" + signMessageBlob.data});
let setN = 32;
verifyer.setVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN);
let saltLen = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM);
console.info("SaltLen == " + saltLen);
let tf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM);
console.info("trailer field == " + tf);
let md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR);
console.info("md == " + md);
let mgf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR);
console.info("mgf == " + mgf);
let mgf1Md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR);
console.info("mgf1Md == " + mgf1Md);
verifyer.init(globalKeyPair.pubKey, function (err, data) {
verifyer.update(input1, function(err, data) {
verifyer.verify(input2, signMessageBlob, function(err, data) {
AlertDialog.show({message : "res " + data});
})
});
});
});
});
});
});
}
```
## Key Agreement
### When to Use
Key agreement allows two parties to establish a shared secret over an insecure channel.
> **NOTE**
>
> From API version 10, the string parameter without the key length is supported in key agreement.
### 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).
|Instance|API|Description|
|---|---|---|
|cryptoFramework|createKeyAgreement(algName : string) : KeyAgreement|Creates a **KeyAgreement** instance.|
|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey, callback : AsyncCallback\<DataBlob>) : void|Generates a shared secret. This API uses an asynchronous callback to return the result.|
|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey) : Promise\<DataBlob>|Generates a shared secret. This API uses a promise to return the result.|
### How to Develop
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.
```js
import cryptoFramework from "@ohos.security.cryptoFramework"
let globalKeyPair;
function ecdhPromise() {
let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256"); // ECC is supported for key agreement from API version 10.
let keyGenPromise = eccGenerator.generateKeyPair();
keyGenPromise.then( keyPair => {
globalKeyPair = keyPair;
return eccKeyAgreement.generateSecret(keyPair.priKey, keyPair.pubKey);
}).then((secret) => {
console.info("ecdh output is " + secret.data);
}).catch((error) => {
console.error("ecdh error.");
});
}
function ecdhCallback() {
let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256");
eccGenerator.generateKeyPair(function (err, keyPair) {
globalKeyPair = keyPair;
eccKeyAgreement.generateSecret(keyPair.priKey, keyPair.pubKey, function (err, secret) {
if (err) {
console.error("ecdh error.");
return;
}
console.info("ecdh output is " + secret.data);
});
});
}
```
## Message Digest
### When to Use
A message digest (MD) is a fixed size numeric representation of the content of a message, computed by a hash 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 MD operations involve the following:
1. Create an **Md** instance with the specified digest algorithm (such as SHA-256).
2. Pass in one or more messages for generating a digest, and generate a digest.
3. Obtain the digest algorithm and digest length (in bytes).
### Available APIs
For more information about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
| Instance | API | Description | | Instance | API | Description |
| --------------- | ------------------------------------------------------------ | -------------------------------------------------- | | --------------- | ------------------------------------------------------------ | -------------------------------------------------- |
| cryptoFramework | function createMd(algName : string) : Md; | Creates an **Md** instance. | | cryptoFramework | function createMd(algName : string) : Md; | Creates an **Md** instance with the specified algorithm. |
| Md | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | Updates the data for a digest. This API uses an asynchronous callback to return the result.| | Md | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | Updates the data for a digest. This API uses an asynchronous callback to return the result.|
| Md | update(input : DataBlob) : Promise\<void>; | Updates the data for a digest. This API uses a promise to return the result. | | Md | update(input : DataBlob) : Promise\<void>; | Updates the data for a digest. This API uses a promise to return the result. |
| Md | digest(callback : AsyncCallback\<DataBlob>) : void; | Generates the digest. This API uses an asynchronous callback to return the result. | | Md | digest(callback : AsyncCallback\<DataBlob>) : void; | Generates the digest. This API uses an asynchronous callback to return the result. |
...@@ -1122,226 +1690,155 @@ For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cry ...@@ -1122,226 +1690,155 @@ For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cry
| Md | getMdLength() : number; | Obtains the digest length based on the specified digest algorithm. | | Md | getMdLength() : number; | Obtains the digest length based on the specified digest algorithm. |
| Md | readonly algName : string; | Obtains the digest algorithm. | | Md | readonly algName : string; | Obtains the digest algorithm. |
**How to Develop** ### Generating a Digest
1. Call **createMd()** to create an **Md** instance. 1. Use **createMd()** to create an **Md** instance.
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. 2. Use **update()** to pass in data. **update()** can be called multiple times. The algorithm library does not limit the data length of a single **update()**.
3. Call **digest()** to compute a digest. 3. Use **digest()** to compute a digest.
4. Obtain the digest algorithm and length of the digest generated. 4. Obtain the digest algorithm and length of the digest generated.
```javascript ```js
import cryptoFramework from "@ohos.security.cryptoFramework" import cryptoFramework from "@ohos.security.cryptoFramework"
// Convert string into uint8Arr. // Convert strings in plaintext into byte streams.
function stringToUint8Array(str) { function stringToUint8Array(str) {
var arr = []; let arr = [];
for (var i = 0, j = str.length; i < j; ++i) { for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i)); arr.push(str.charCodeAt(i));
} }
var tmpUint8Array = new Uint8Array(arr); return new Uint8Array(arr);
return tmpUint8Array;
}
// Generate a dataBlob of the given length.
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;
} }
// Compute an MD using promise-based APIs. // Generate a digest in promise mode.
function doMdByPromise(algName) { function doMdByPromise() {
var md; let mdAlgName = "SHA256"; // Digest algorithm name.
let message = "mdTestMessgae"; // Data to be digested.
let md;
let mdOutput;
try { try {
md = cryptoFramework.createMd(algName); md = cryptoFramework.createMd(mdAlgName);
} catch (error) { } catch (error) {
console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
return;
} }
console.error("[Promise]: Md algName is: " + md.algName); console.info("[Promise]: Md algName is: " + md.algName);
// Initial update(). // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter.
var promiseMdUpdate = md.update(GenDataBlob(12)); let promiseMdUpdate = md.update({ data: stringToUint8Array(message) });
promiseMdUpdate.then(() => { promiseMdUpdate.then(() => {
// Call update() multiple times based on service requirements. // Call digest() to return the result.
promiseMdUpdate = md.update(GenDataBlob(12)); let PromiseMdDigest = md.digest();
return promiseMdUpdate;
}).then(mdOutput => {
var PromiseMdDigest = md.digest();
return PromiseMdDigest; return PromiseMdDigest;
}).then(mdOutput => { }).then(digestOutput => {
console.error("[Promise]: MD result: " + mdOutput.data); mdOutput = digestOutput;
var mdLen = md.getMdLength(); console.info("[Promise]: MD result: " + mdOutput.data);
console.error("[Promise]: MD len: " + mdLen); let mdLen = md.getMdLength();
console.info("[Promise]: MD len: " + mdLen);
}).catch(error => { }).catch(error => {
console.error("[Promise]: error: " + error.message); console.error("[Promise]: error: " + error.message);
}); });
} }
// Compute an MD using callback-based APIs. // Generate a digest in callback mode.
function doMdByCallback(algName) { function doMdByCallback() {
var md; let mdAlgName = "SHA256"; // Digest algorithm name.
let message = "mdTestMessgae"; // Data to be digested.
let md;
let mdOutput;
try { try {
md = cryptoFramework.createMd(algName); md = cryptoFramework.createMd(mdAlgName);
} catch (error) { } catch (error) {
console.error("[Callback]: error code: " + error.code + ", message is: " + error.message); console.error("[Callback]: error code: " + error.code + ", message is: " + error.message);
} }
console.error("[Callback]: Md algName is: " + md.algName); console.info("[Callback]: Md algName is: " + md.algName);
// Initial update(). // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter.
md.update(GenDataBlob(12), (err,) => { md.update({ data: stringToUint8Array(message) }, (err,) => {
if (err) { if (err) {
console.error("[Callback]: err: " + err.code); console.error("[Callback]: err: " + err.code);
} }
// Call update() multiple times based on service requirements. md.digest((err1, digestOutput) => {
md.update(GenDataBlob(12), (err1,) => {
if (err1) { if (err1) {
console.error("[Callback]: err: " + err1.code); console.error("[Callback]: err: " + err1.code);
}
md.digest((err2, mdOutput) => {
if (err2) {
console.error("[Callback]: err: " + err2.code);
} else { } else {
console.error("[Callback]: MD result: " + mdOutput.data); mdOutput = digestOutput;
var mdLen = md.getMdLength(); console.info("[Callback]: MD result: " + mdOutput.data);
console.error("[Callback]: MD len: " + mdLen); let mdLen = md.getMdLength();
console.info("[Callback]: MD len: " + mdLen);
} }
}); });
}); });
});
} }
``` ```
The following example demonstrates how to call **update()** multiple times to update the MD.
```javascript
import cryptoFramework from "@ohos.security.cryptoFramework"
async function updateData(index, obj, data) { ### Generating a Digest by Segment
console.error("update " + (index + 1) + " MB data...");
return obj.update(data);
}
1. Use **createMd()** to create an **Md** instance.
2. Use **update()** multiple times to pass in by segment.
3. Use **digest()** to compute a digest.
4. Obtain the digest algorithm and length of the digest generated.
```js
import cryptoFramework from "@ohos.security.cryptoFramework"
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str) { function stringToUint8Array(str) {
var arr = []; let arr = [];
for (var i = 0, j = str.length; i < j; ++i) { for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i)); arr.push(str.charCodeAt(i));
} }
var tmpUint8Array = new Uint8Array(arr); return new Uint8Array(arr);
return tmpUint8Array;
} }
function GenDataBlob(dataBlobLen) { // Generate a digest by segment in promise mode.
var dataBlob; async function doLoopMdPromise() {
if (dataBlobLen == 12) { let mdAlgName = "SHA256"; // Digest algorithm name.
dataBlob = {data: stringToUint8Array("my test data")}; let md;
} else { let mdOutput;
console.error("GenDataBlob: dataBlobLen is invalid"); try {
dataBlob = {data: stringToUint8Array("my test data")}; md = cryptoFramework.createMd(mdAlgName);
} catch (error) {
console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
return;
} }
return dataBlob; console.info("[Promise]: Md algName is: " + md.algName);
} let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the message is of 43 bytes.
let messageArr = [];
let updateLength = 20; // For example, pass in 20 bytes in each update().
function LoopMdPromise(algName, loopSize) { for (let i = 0; i <= messageText.length; i++) {
var md; if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) {
let message = new Uint8Array(messageArr);
let messageBlob = { data : message };
// Use await to process the update() in the for() loop.
try { try {
md = cryptoFramework.createMd(algName); await md.update (messageBlob); // Call update() to process data by segment.
} catch (error) { } catch (error) {
console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); console.error("await update error code: " + error.code + ", message is: " + error.message);
return; return;
} }
console.error("[Promise]: Md algName is: " + md.algName); messageArr = [];
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(); // Pad messageArr based on the segment length.
return PromiseMdDigest; if (i < messageText.length) {
}).then(mdOutput => { messageArr.push(messageText.charCodeAt(i));
console.error("[Promise]: MD result: " + mdOutput.data); }
var mdLen = md.getMdLength(); }
console.error("[Promise]: MD len: " + mdLen); let PromiseMdDigest = md.digest();
PromiseMdDigest.then(digestOutput => {
mdOutput = digestOutput;
console.info("[Promise]: MD result: " + mdOutput.data);
let mdLen = md.getMdLength();
console.info("[Promise]: MD len: " + mdLen);
}).catch(error => { }).catch(error => {
console.error("[Promise]: error: " + error.message); console.error("[Promise]: error: " + error.message);
}); });
} }
``` ```
## Performing Key Agreement ## HMAC
**When to Use**
Key agreement allows two parties to establish a shared secret over an insecure channel.
**Available APIs**
For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
|Instance|API|Description|
|---|---|---|
|cryptoFramework|createKeyAgreement(algName : string) : KeyAgreement|Creates a **KeyAgreement** instance.|
|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey, callback : AsyncCallback\<DataBlob>) : void|Generates a shared secret. This API uses an asynchronous callback to return the result.|
|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey) : Promise\<DataBlob>|Generates a shared secret. This API uses a promise to return the result.|
**How to Develop**
1. Use **createKeyAgreement()** to create a **KeyAgreement** object for subsequent key agreement operations.
2. Use **generateSecret()** provided by **KeyAgreement** to pass in the peer ECC public key object and the ECC private key object generated locally.
```javascript
import cryptoFramework from "@ohos.security.cryptoFramework"
let globalSelfPriKey;
let globalPeerPubKey;
function ecdhPromise() {
let peerPubKeyArray = 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 peerPubKeyBlob = { data: peerPubKeyArray };
let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256");
eccGenerator.convertKey(peerPubKeyBlob, null).then((peerKeyPair) => {
globalPeerPubKey = peerKeyPair.pubKey;
return eccGenerator.generateKeyPair();
}).then((keyPair) => {
globalSelfPriKey = keyPair.priKey;
return eccKeyAgreement.generateSecret(globalSelfPriKey, globalPeerPubKey);
}).then((secret) => {
console.info("ecdh promise output is " + secret.data);
}).catch((error) => {
console.error("ecdh error.");
});
}
function ecdhCallback() {
let peerPubKeyArray = 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 peerPubKeyBlob = { data: peerPubKeyArray };
let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256");
eccGenerator.convertKey(peerPubKeyBlob, null, function (err, peerKeyPair) {
globalPeerPubKey = peerKeyPair.pubKey;
eccGenerator.generateKeyPair(function (err, keyPair) {
globalSelfPriKey = keyPair.priKey;
eccKeyAgreement.generateSecret(globalSelfPriKey, globalPeerPubKey, function (err, secret) {
if (err) {
console.error("ecdh error.");
return;
}
console.info("ecdh callback output is " + secret.data);
});
});
})
}
```
## Generating a MAC
**When to Use** ### When to Use
A message authentication code (MAC) can be used to verify both the integrity and authenticity of a message using a shared secret. A hash-based message authentication code (HMAC) can be used to verify both the integrity and authenticity of a message using a shared secret.
Typical MAC operations involve the following: Typical MAC operations involve the following:
...@@ -1349,15 +1846,15 @@ Typical MAC operations involve the following: ...@@ -1349,15 +1846,15 @@ Typical MAC operations involve the following:
2. Initialize the **Mac** instance, add one or more segments of data for generating a MAC, and generate a MAC. 2. Initialize the **Mac** instance, add one or more segments of data for generating a MAC, and generate a MAC.
3. Obtain the algorithm and length of a MAC. 3. Obtain the algorithm and length of a MAC.
**Available APIs** ### 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).
| Instance | API | Description | | Instance | API | Description |
| --------------- | ------------------------------------------------------------ | --------------------------------------------------- | | --------------- | ------------------------------------------------------------ | --------------------------------------------------- |
| cryptoFramework | function createMac(algName : string) : Mac; | Creates a **Mac** instance. | | cryptoFramework | function createMac(algName : string) : Mac; | Creates a **Mac** instance. |
| Mac | init(key : SymKey, callback : AsyncCallback\<void>) : void; | Initializes the MAC operation. This API uses an asynchronous callback to return the result.| | Mac | init(key : SymKey, callback : AsyncCallback\<void>) : void; | Initializes the **Mac** instance. This API uses an asynchronous callback to return the result. |
| Mac | init(key : SymKey) : Promise\<void>; | Initializes the MAC operation. This API uses a promise to return the result. | | Mac | init(key : SymKey) : Promise\<void>; | Initializes the **Mac** instance. This API uses a promise to return the result. |
| Mac | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | Updates the data for the MAC operation. This API uses an asynchronous callback to return the result. | | Mac | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | Updates the data for the MAC operation. This API uses an asynchronous callback to return the result. |
| Mac | update(input : DataBlob) : Promise\<void>; | Updates the data for the MAC operation. This API uses a promise to return the result. | | Mac | update(input : DataBlob) : Promise\<void>; | Updates the data for the MAC operation. This API uses a promise to return the result. |
| Mac | doFinal(callback : AsyncCallback\<DataBlob>) : void; | Finalizes the MAC operation to generate a MAC. This API uses an asynchronous callback to return the result. | | Mac | doFinal(callback : AsyncCallback\<DataBlob>) : void; | Finalizes the MAC operation to generate a MAC. This API uses an asynchronous callback to return the result. |
...@@ -1365,88 +1862,84 @@ For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cry ...@@ -1365,88 +1862,84 @@ For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cry
| Mac | getMacLength() : number; | Obtains the length of the MAC based on the specified algorithm. | | Mac | getMacLength() : number; | Obtains the length of the MAC based on the specified algorithm. |
| Mac | readonly algName : string; | Obtains the digest algorithm. | | Mac | readonly algName : string; | Obtains the digest algorithm. |
**How to Develop** ### Generating an HMAC
1. Call **createMac()** to create a **Mac** instance. 1. Use **createMac()** to create a **Mac** instance.
2. Call **init()** to initialize the **Mac** instance with the symmetric key passed in. 2. Use **init()** to initialize the **Mac** instance with the symmetric key passed in.
3. Call **update()** one or more times to add the data for computing a MAC. 3. Use **update()** to pass in the data for computing an HMAC.
4. Call **doFinal()** to generate a MAC. 4. Use **doFinal()** to generate an HMAC.
5. Obtain the algorithm and length of the MAC. 5. Obtain the algorithm and length of the HMAC.
```javascript ```js
import cryptoFramework from "@ohos.security.cryptoFramework" import cryptoFramework from "@ohos.security.cryptoFramework"
// Convert string into uint8Arr. // Convert strings in plaintext into byte streams.
function stringToUint8Array(str) { function stringToUint8Array(str) {
var arr = []; let arr = [];
for (var i = 0, j = str.length; i < j; ++i) { for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i)); arr.push(str.charCodeAt(i));
} }
var tmpUint8Array = new Uint8Array(arr); return new Uint8Array(arr);
return tmpUint8Array;
}
// Generate a blob.
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 doHmacByPromise(algName) { // Generate an HMAC in promise mode.
var mac; function doHmacByPromise() {
let macAlgName = "SHA256"; // Digest algorithm name.
let message = "hmacTestMessgae"; // Data used to generate an HMAC.
let macOutput;
let mac;
try { try {
mac = cryptoFramework.createMac(algName); mac = cryptoFramework.createMac(macAlgName);
} catch (error) { } catch (error) {
console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
} }
console.error("[Promise]: Mac algName is: " + mac.algName); console.info("[Promise]: Mac algName is: " + mac.algName);
var KeyBlob = { let KeyBlob = {
// 128-bit key
data : stringToUint8Array("12345678abcdefgh") data : stringToUint8Array("12345678abcdefgh")
} }
var symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
var promiseConvertKey = symKeyGenerator.convertKey(KeyBlob); // Convert the binary data into a key.
let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob);
promiseConvertKey.then(symKey => { promiseConvertKey.then(symKey => {
var promiseMacInit = mac.init(symKey); let promiseMacInit = mac.init(symKey);
return promiseMacInit; return promiseMacInit;
}).then(() => { }).then(() => {
// Initial update(). // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter.
var promiseMacUpdate = mac.update(GenDataBlob(12)); let promiseMacUpdate = mac.update({ data: stringToUint8Array(message) });
return promiseMacUpdate; return promiseMacUpdate;
}).then(() => { }).then(() => {
// Call update() multiple times based on service requirements. let PromiseMacDoFinal = mac.doFinal();
var promiseMacUpdate = mac.update(GenDataBlob(12));
return promiseMacUpdate;
}).then(() => {
var PromiseMacDoFinal = mac.doFinal();
return PromiseMacDoFinal; return PromiseMacDoFinal;
}).then(macOutput => { }).then(output => {
console.error("[Promise]: HMAC result: " + macOutput.data); macOutput = output;
var macLen = mac.getMacLength(); console.info("[Promise]: HMAC result: " + macOutput.data);
console.error("[Promise]: MAC len: " + macLen); let macLen = mac.getMacLength();
console.info("[Promise]: MAC len: " + macLen);
}).catch(error => { }).catch(error => {
console.error("[Promise]: error: " + error.message); console.error("[Promise]: error: " + error.message);
}); });
} }
// Generate a MAC using callback-based APIs. // Generate an HMAC in callback mode.
function doHmacByCallback(algName) { function doHmacByCallback() {
var mac; let macAlgName = "SHA256"; // Digest algorithm name.
let message = "hmacTestMessgae"; // Data used to generate an HMAC.
let macOutput;
let mac;
try { try {
mac = cryptoFramework.createMac(algName); mac = cryptoFramework.createMac(macAlgName);
} catch (error) { } catch (error) {
AlertDialog.show({message: "[Callback]: error code: " + error.code + ", message is: " + error.message}); AlertDialog.show({message: "[Callback]: error code: " + error.code + ", message is: " + error.message});
console.error("[Callback]: error code: " + error.code + ", message is: " + error.message); console.error("[Callback]: error code: " + error.code + ", message is: " + error.message);
} }
var KeyBlob = { console.info("[Promise]: Mac algName is: " + mac.algName);
let KeyBlob = {
// 128-bit key
data : stringToUint8Array("12345678abcdefgh") data : stringToUint8Array("12345678abcdefgh")
} }
var symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
// Convert the binary data into a key.
symKeyGenerator.convertKey(KeyBlob, (err, symKey) => { symKeyGenerator.convertKey(KeyBlob, (err, symKey) => {
if (err) { if (err) {
console.error("[Callback]: err: " + err.code); console.error("[Callback]: err: " + err.code);
...@@ -1455,127 +1948,138 @@ function doHmacByCallback(algName) { ...@@ -1455,127 +1948,138 @@ function doHmacByCallback(algName) {
if (err1) { if (err1) {
console.error("[Callback]: err: " + err1.code); console.error("[Callback]: err: " + err1.code);
} }
// Initial update(). // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter.
mac.update(GenDataBlob(12), (err2, ) => { mac.update({ data: stringToUint8Array(message) }, (err2, ) => {
if (err2) { if (err2) {
console.error("[Callback]: err: " + err2.code); console.error("[Callback]: err: " + err2.code);
} }
// Call update() multiple times based on service requirements. mac.doFinal((err3, output) => {
mac.update(GenDataBlob(12), (err3, ) => {
if (err3) { if (err3) {
console.error("[Callback]: err: " + err3.code); console.error("[Callback]: err: " + err3.code);
}
mac.doFinal((err4, macOutput) => {
if (err4) {
console.error("[Callback]: err: " + err4.code);
} else { } else {
macOutput = output;
console.error("[Callback]: HMAC result: " + macOutput.data); console.error("[Callback]: HMAC result: " + macOutput.data);
var macLen = mac.getMacLength(); let macLen = mac.getMacLength();
console.error("[Callback]: MAC len: " + macLen); console.error("[Callback]: MAC len: " + macLen);
} }
}); });
}); });
}); });
}); });
});
} }
``` ```
The following example demonstrates how to call **update()** multiple times to update the MAC.
```javascript
import cryptoFramework from "@ohos.security.cryptoFramework"
async function updateData(index, obj, data) { ### Generating an HMAC by Segment
console.error("update " + (index + 1) + " MB data...");
return obj.update(data); Generate an HMAC by segment.
}
1. Use **createMac()** to create a **Mac** instance.
2. Use **init()** to initialize the **Mac** instance with the symmetric key passed in.
3. Call **update()** multiple times to pass in data by segment.
4. Use **doFinal()** to generate an HMAC.
5. Obtain the algorithm and length of the HMAC.
```js
import cryptoFramework from "@ohos.security.cryptoFramework"
function stringToUint8Array(str) { function stringToUint8Array(str) {
var arr = []; let arr = [];
for (var i = 0, j = str.length; i < j; ++i) { for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i)); arr.push(str.charCodeAt(i));
} }
var tmpUint8Array = new Uint8Array(arr); return 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) { function doLoopHmacPromise() {
var mac; let macAlgName = "SHA256"; // Digest algorithm name.
let macOutput;
let mac;
try { try {
mac = cryptoFramework.createMac(algName); mac = cryptoFramework.createMac(macAlgName);
} catch (error) { } catch (error) {
console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
return; return;
} }
console.error("[Promise]: Mac algName is: " + mac.algName); console.info("[Promise]: Mac algName is: " + mac.algName);
var KeyBlob = { let KeyBlob = {
// 128-bit key
data : stringToUint8Array("12345678abcdefgh") data : stringToUint8Array("12345678abcdefgh")
} }
var symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the message is of 43 bytes.
var promiseConvertKey = symKeyGenerator.convertKey(KeyBlob); let updateLength = 20; // For example, pass in 20 bytes in each update().
let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
// Convert the binary data into a key.
let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob);
promiseConvertKey.then(symKey => { promiseConvertKey.then(symKey => {
var promiseMacInit = mac.init(symKey); let promiseMacInit = mac.init(symKey);
return promiseMacInit; return promiseMacInit;
}).then(async () => { }).then(async () => {
for (var i = 0; i < loopSize; i++) { let promiseMacUpdate;
await updateData(i, mac, GenDataBlob(12)); let messageArr = [];
for (let i = 0; i <= messageText.length; i++) {
if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) {
let message = new Uint8Array(messageArr);
let messageBlob = { data : message };
// Use await to process the update() in the for() loop.
try {
promiseMacUpdate = await mac.update(messageBlob); // Invoke update() multiple times.
} catch (error) {
console.error("await update error code: " + error.code + ", message is: " + error.message);
return;
}
messageArr = [];
}
// Pad messageArr based on the segment length.
if (i < messageText.length) {
messageArr.push(messageText.charCodeAt(i));
}
} }
var promiseMacUpdate = mac.update(GenDataBlob(12));
return promiseMacUpdate; return promiseMacUpdate;
}).then(() => { }).then(() => {
var PromiseMacDoFinal = mac.doFinal(); let PromiseMacDoFinal = mac.doFinal();
return PromiseMacDoFinal; return PromiseMacDoFinal;
}).then(macOutput => { }).then(output => {
console.error("[Promise]: HMAC result: " + macOutput.data); macOutput = output;
var macLen = mac.getMacLength(); console.log("[Promise]: HMAC result: " + macOutput.data);
console.error("[Promise]: MAC len: " + macLen); let macLen = mac.getMacLength();
console.log("[Promise]: MAC len: " + macLen);
}).catch(error => { }).catch(error => {
console.error("[Promise]: error: " + error.message); console.error("[Promise]: error: " + error.message);
}); });
} }
``` ```
## Random Number
## Generating a Random Number ### When to Use
**When to Use**
Typical random number operations involve the following: Typical random number operations involve the following:
- Generate a random number. 1. Create a **Random** instance and specify the length (in bytes) of the random number to generate a secure random number of the specified length (ranging from **1** to **INT_MAX**).
- Set a seed based on the random number generated. 2. Set a seed based on the random number generated.
**Available APIs** ### Available APIs
For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). For more information about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
| Instance | API | Description | | Instance | API | Description |
| --------------- | ------------------------------------------------------------ | ---------------------------------------------- | | --------------- | ------------------------------------------------------------ | ------------------------------------------ |
| cryptoFramework | function createRandom() : Random; | Creates a **Random** instance. | | cryptoFramework | function createRandom() : Random; | Creates a **Random** instance. |
| Random | generateRandom(len : number, callback: AsyncCallback\<DataBlob>) : void; | Generates a random number. This API uses an asynchronous callback to return the result. | | Random | generateRandom(len : number, callback: AsyncCallback\<DataBlob>) : void; | Generates a random number. This API uses an asynchronous callback to return the result.|
| Random | generateRandom(len : number) : Promise\<DataBlob>; | Generates a random number. This API uses a promise to return the result. | | Random | generateRandom(len : number) : Promise\<DataBlob>; | Generates a random number. This API uses a promise to return the result. |
| Random | generateRandomSync(len: number): DataBlob; | Generates a random number of the specified length synchronously. |
| Random | setSeed(seed : DataBlob) : void; | Sets a seed. | | Random | setSeed(seed : DataBlob) : void; | Sets a seed. |
**How to Develop** ### How to Develop
1. Call **createRandom()** to create a **Random** instance. 1. Use **createRandom()** to create a **Random** instance.
2. Call **generateRandom()** to generate a random number of the given length. 2. Use **generateRandom()** to generate a random number of the given length.
3. Call **setSeed()** to set a seed. 3. Use **setSeed()** to set a seed.
```javascript ```js
import cryptoFramework from "@ohos.security.cryptoFramework" import cryptoFramework from "@ohos.security.cryptoFramework"
// Generate a random number and set a seed using promise-based APIs. // Generate a random number in promise mode.
function doRandByPromise(len) { function doRandByPromise(len) {
var rand; var rand;
try { try {
...@@ -1596,7 +2100,7 @@ function doRandByPromise(len) { ...@@ -1596,7 +2100,7 @@ function doRandByPromise(len) {
}); });
} }
// Generate a random number and set a seed using callback-based APIs. // Generate a random number in callback mode.
function doRandByCallback(len) { function doRandByCallback(len) {
var rand; var rand;
try { try {
...@@ -1617,4 +2121,25 @@ function doRandByCallback(len) { ...@@ -1617,4 +2121,25 @@ function doRandByCallback(len) {
} }
}); });
} }
// Generate a random number synchronously.
function doRandBySync(len) {
var rand;
try {
rand = cryptoFramework.createRandom();
} catch (error) {
console.error("[Sync]: error code: " + error.code + ", message is: " + error.message);
}
try {
let randData = rand.generateRandomSync(len);
if (randData != null) {
console.info("[Sync]: rand result: " + randData.data);
} else {
console.error("[Sync]: get rand result fail!");
}
} catch (error) {
console.error("[Sync]: error: " + error.message);
}
}
``` ```
# Crypto Framework Overview # Crypto Framework Overview
The cryptographic (crypto for shot) framework shields the implementation differences of third-party cryptographic algorithm libraries and implements encryption and decryption, signing and signature verification, and operations of the message authentication code (MAC), hashes, and secure random numbers. You can use the APIs provided by this framework to implement cipher development quickly. The Cryptographic (Crypto for shot) Framework shields the implementation differences of third-party cryptographic algorithm libraries and implements encryption and decryption, digital signature and signature verification, message authentication code (MAC) generation, hashes, and generation of secure random numbers. You can use the APIs provided by this framework to implement cipher development quickly.
> **NOTE** > **NOTE**
> >
> The crypto framework provides cryptographic operations on keys, but not key management. It is used when the application keeps the key securely (for example, temporary session keys are used only in the memory or the application implements secure key storage). If the system is required to provide key management (such as key storage), use the [HUKS](huks-overview.md). > The Crypto Framework provides cryptographic operations, but not key management. It can be used when temporary session keys are used only in the memory or the applications implement secure key storage. If the system is required to provide key management (such as key storage), use the [HUKS](huks-overview.md).
## Working Principles ## Working Principles
The crypto framework provides components in the following layers:
- Interface layer: provides unified JS interface externally. The Crypto Framework provides components in the following layers:
- Interface layer: provides unified JavaScript interfaces externally.
- Plug-in layer: implements third-party algorithm libraries. - Plug-in layer: implements third-party algorithm libraries.
- Framework layer: loads plug-ins at the plug-in layer to adapt to third-party algorithm libraries and shield implementation differences between these libraries. - Framework layer: flexibly loads plug-ins at the plug-in layer to adapt to third-party algorithm libraries and shield differences between these libraries.
## Basic Concepts ## Basic Concepts
**Symmetric Key**
### Symmetric Key
A symmetric key is a key used both to encrypt and decrypt data. In symmetric encryption, the sender converts information in plaintext into ciphertext using a key and certain algorithm for security purposes. The receiver converts the ciphertext into plaintext using the same key and algorithm. A symmetric key is a key used both to encrypt and decrypt data. In symmetric encryption, the sender converts information in plaintext into ciphertext using a key and certain algorithm for security purposes. The receiver converts the ciphertext into plaintext using the same key and algorithm.
- AES - **AES key**
Advanced Encryption Standard (AES) is the most common symmetric encryption algorithm. AES is a block cipher, which divides plaintext into fixed-length groups of bits, called blocks. A block is encrypted each time until the entire plaintext is encrypted. The block size in AES is 128 bits. That is, each block contains 16 bytes (8 bits/byte). The AES key length can be 128 bits, 192 bits, or 256 bits.
- **3DES key**
Triple Data Encryption Standard (3DES), also called 3DESede or Triple DES, applies the DES cipher three times to each data block. It uses three 64-bit keys to encrypt a data block three times. Compared with DES, 3DES provides higher security due to longer key length, but lower processing speed. AES is faster and more secure than 3DES.
### Asymmetric Key
In the asymmetric cryptography, a private and public key pair is required. The private key is used to encrypt the plaintext, and the public key is used to decrypt the ciphertext. The public key is public and open to anyone in the system, while the private key is private. For digital signature and signature verification, the private key is used to sign the plaintext, and the public key is used to verify the signature data.
- **RSA key**
Rivest-Shamir-Adleman (RSA) is an asymmetric encryption algorithm widely used for secure data transmission. The security of RSA depends on the practical difficulty of factoring the product of two large prime numbers.
The RSA key parameters include the following integers:
**n**: modulus, which is a public parameter of the private key and public key.
Advanced Encryption Standard (AES) is the most common symmetric encryption algorithm. AES is a block cipher. A block cipher divides plaintext into fixed-length groups of bits, called blocks. A block is encrypted each time until the entire plaintext is encrypted. The block size in AES is 128 bits. That is, each block contains 16 bytes (8 bits/byte). The key length can be 128 bits, 192 bits, or 256 bits. **sk**: private exponent, which is often written as **d** in the formula.
- 3DES
Triple Data Encryption Standard (3DES), also called 3DESede or Triple DES, applies the DES cipher three times to each data block. It uses three 64-bit keys to encrypt a data block three times. Compared with DES, 3DES provides higher security due to longer key length, but its processing speed is lower. The AES is faster and more secure than 3DES. **pk**: public exponent, which is often written as **e** in the formula.
**Asymmetric Key** - **ECC key**
In the asymmetric cryptography, a private and public key pair is required. The private key is used to encrypt the plaintext, and the public key is used to decrypt the ciphertext. The public key is public and open to anyone in the system, while the private key is private. For signing and signature verification, the private key is used to sign the plaintext, and the public key is used to verify the signature data. Elliptic-curve cryptography (ECC) is a public-key encryption algorithm based on elliptic curve mathematics. It security is based on the assumption that it is infeasible to find the discrete logarithm of a random elliptic curve element with respect to a publicly known base point. The Crypto Framework provides capabilities for generating a variety of ECC keys.
- RSA key The ECC algorithm can be regarded as an operation of numbers defined in a special set. Currently, the Crypto Framework supports elliptic curves in **Fp** fields, where **p** is prime. The **Fp** fields are also called the prime fields.
The security of RSA relies on the factoring problem, that is, the difficulty of factoring the product of two large prime numbers. The keys for the RSA algorithm are generated as follows: The ECC key parameters in the **Fp** fields include the following:
1. Generate two large prime numbers **p** and **q**. **p**: prime number used to determine **Fp**.
2. Compute **n** = **p** x **q**. **a**, **b**: determine the elliptic curve equation.
**n** is used as the modulus for both the public and private keys, and is released as part of the public key. **g**: base point of the elliptic curve, which can be represented as **gx** or **gy**.
3. Choose an integer **e** such that 1 < **e** < (**p** - 1) x (**q** - 1), that is, **e** and (**p** - 1) x (**q** - 1) are coprime. **n**: order of the base point **g**.
4. Compute **d**. **e** x **d** - 1 is a multiple of (**p** - 1) and (**q** - 1). **h**: cofactor.
The public key consists of the modulus **n** and the public exponent **e**. The private key consists of **n** and the private exponent **d**. **sk**: private key, which is a random integer less than **n**.
In addition to the default RSA key generation from two primes, the crypto framework provides key generation from multiple primes. You can set the **primes** parameter (PRIMES_2, PRIMES_3, PRIMES_4, PRIMES_5) to specify the number of primes during key generation. The keys generated from multiple primes help reduce the computation workload in decryption and signing (Chinese remainder theorem). However, such keys are weak. The algorithm library defines specifications based on the rules for using OpenSSL prime numbers. For details, see [**Constraints**](#constraints). **pk**: public key, which is a point on the elliptic curve. **pk** = **sk** x **g**.
- ECC key - **DSA key**
Elliptic-Curve Cryptography (ECC) is a public-key encryption based on the algebraic structure of elliptic curve over finite fields. The crypto framework provides a variety of ECC key generation capabilities. Digital Signature Algorithm (DSA) is a public-key algorithm based on the modular exponentiation and discrete logarithm problem. It is used for digital signatures and signature verification, but not for encryption and decryption. The Crypto Framework provides the capability of generating DSA keys of different lengths.
**Encryption and Decryption** The DSA key parameters include the following:
- Symmetric AES encryption and decryption **p**: a prime modulus, whose length is an integer multiple of 64.
**q**: prime factor of p – 1. The length varies depending on the length of **p**.
**g**: g = (h ^ ((p - 1) / q)) mod p, where **h** is any integer that meets 1 < h < p -1.
**sk**: private key, which is a randomly generated integer and complies with 0 < sk < q.
**pk**: public key. pk = (g ^ sk) mod p
### Encryption and Decryption
- **Symmetric AES encryption and decryption**
The algorithm library provides the following cipher modes of operation for AES: ECB, CBC, OFB, CFB, CTR, GCM, and CCM. AES is a block cipher, with a fixed block size of 128 bits. In actual applications, the last block of plaintext may be less than 128 bits and needs to be padded. The padding options are as follows: The algorithm library provides the following cipher modes of operation for AES: ECB, CBC, OFB, CFB, CTR, GCM, and CCM. AES is a block cipher, with a fixed block size of 128 bits. In actual applications, the last block of plaintext may be less than 128 bits and needs to be padded. The padding options are as follows:
- **NoPadding**: no padding. - **NoPadding**: no padding.
- **PKCS5**: pads a block cipher with a block size of 8 bytes - **PKCS5**: pads a block cipher with a block size of 8 bytes.
- **PKCS7**: The PKCS #7 padding scheme is the same as that of PKCS #5 padding except that PKCS #5 padding is defined for 8-byte block sizes, while PKCS #5 padding works for any block size from 1 to 255 bytes. - **PKCS7**: pads any block size from 1 to 255 bytes. The PKCS #7 padding scheme is the same as that of PKCS #5.
> **NOTE**<br>In ECB and CBC, the plaintext must be padded if its length is not an integer multiple of 128 bits. Since the plaintext is padded to the block size, the PKCS #5 and PKCS #7 used in the algorithm library use the block size as the padding length. That is, data is padded to 16 bytes in AES encryption. > **NOTE**
>
> In ECB and CBC modes, the plaintext must be padded if its length is not an integer multiple of 128 bits.<br>
> Since the plaintext is padded to the block size, the PKCS #5 and PKCS #7 used in the algorithm library use the block size as the padding length. That is, data is padded to 16 bytes in AES encryption.
- **Symmetric 3DES Encryption and Decryption** - **Symmetric 3DES encryption and decryption**
3DES encryption and decryption apply the DES cipher three times to each data block to obtain the ciphertext or plaintext. 3DES encryption and decryption apply the DES cipher three times to each data block to obtain the ciphertext or plaintext.
The algorithm library provides the following cipher modes of operation for 3DES encryption and decryption: ECB, CBC, OFB, and CFB. DES is a block cipher, with a fixed block size of 64 bits. In actual applications, the last block of plaintext may be less than 64 bits and needs to be padded. The padding options are as follows: The algorithm library provides the following cipher modes of operation for 3DES encryption and decryption: ECB, CBC, OFB, and CFB. DES is a block cipher, with a fixed block size of 64 bits. In actual applications, the last block of plaintext may be less than 64 bits and needs to be padded. The padding options are as follows:
- **NoPadding**: no padding. - **NoPadding**: no padding.
- **PKCS5**: pads a block cipher with a block size of 8 bytes - **PKCS5**: pads a block cipher with a block size of 8 bytes.
- **PKCS7**: The PKCS #7 padding scheme is the same as that of PKCS #5 padding except that PKCS #5 padding is defined for 8-byte block sizes, while PKCS #5 padding works for any block size from 1 to 255 bytes. - **PKCS7**: pads any block size from 1 to 255 bytes. The PKCS #7 padding scheme is the same as that of PKCS #5.
> **NOTE**<br>In ECB and CBC, the plaintext must be padded if its length is not an integer multiple of 64 bits. <br>Since the plaintext is padded to the block size, the PKCS #5 and PKCS #7 used in the algorithm library use the block size as the padding length. That is, data is padded to 8 bytes in 3DES encryption. > **NOTE**
>
> In ECB and CBC modes, the plaintext must be padded if its length is not an integer multiple of 64 bits.
> Since the plaintext is padded to the block size, the PKCS #5 and PKCS #7 used in the algorithm library use the block size as the padding length. That is, data is padded to 8 bytes in 3DES encryption.
- **Asymmetric RSA Encryption and Decryption** - **Asymmetric RSA encryption and decryption**
After the RSA public key (n, e) and private key (n, d) are held, the RSA encryption process is as follows: RSA is a block cipher, with fixed-length blocks. In actual applications, diverse padding modes are used. Currently, the Crypto Framework provides the following padding modes:
- **NoPadding**: no padding. The length of the input or output data must be the same as that of the RSA key modulus.
Ciphertext = Plaintext ^ **e** mod **n** - **PKCS1**: RSAES-PKCS1-V1_5 mode in RFC3447 (corresponding to RSA_PKCS1_PADDING in OpenSSL). The RSA converts the source data D into an encryption block (EB). In encryption, the length of the input data must be less than or equal to the RSA key modulus minus 11. The length of the output data is the same as that of the RSA key modulus.
The decryption process is as follows: - **PKCS1_OAEP**: RSAES-OAEP mode in RFC 3447 (corresponding to RSA_PKCS1_OAEP_PADDING in OpenSSL). It is a new padding mode developed by PKCS#1. In this mode, two digests (**md** and **mgf1_md**) need to be set. During encryption, the length of the input data must meet the following requirements:
Plaintext = Ciphertext ^ **d** mod **n** Input data length < RSA key modulus – **md** length (bytes) – **mgf1_md** length (bytes) – 2
The algorithm library provides the following modes of operation for RSA encryption and decryption: **PKCS1**, **PKCS1_ OAEP**, and **NoPadding**. RSA is a block cipher, with fixed-length blocks. In actual applications, diverse padding modes are used. The padding options are as follows: The length of the output data is the same as that of the RSA key modulus. In this mode, you can also set the **pSource** byte stream to define the encoding input **P** filled by OAEP and obtain the parameters related to PKCS1_OAEP.
- **NoPadding**: No padding is required. The length of the input or output data must be the same as that of the RSA key modulus. The **PKCS1_OAEP** parameters include the following:
- **PKCS1**: PKCS #1 v1.5 is the default padding mode for RSA encryption and decryption. The length of the input data must be less than or equal to the RSA key modulus minus 11, and the length of the output data must be the same as that of the RSA key modulus. **md**: message digest algorithm.<br>
- **PKCS1_OAEP**: The RSA_PKCS1_OAEP_PADDING is a new padding mode provided by PKCS #1. In this mode, two digests (**md** and **mgf1_md**) must be set. The length of the input data must be less than RSA key modulus length minus the **md** length, **mgf1_md** length, and two. The length of the output data must be the same as that of the RSA key modulus. **mgf**: mask generation algorithm. Currently, only MGF1 is supported.<br>
**mgf1_md**: mgf1 digest algorithm.<br>
**pSource**: byte stream, which is the source for encoding input P in OAEP padding.
> **NOTE** > **NOTE**
> >
> Length of the RSA key modulus = (Number of RSA bits + 7)/8 > RSA key modulus = (RSA bits + 7)/8
**Signing and Signature Verification**
- RSA signing and signature verification ### Signing and Signature Verification
After the RSA public key (n, e) and private key (n, d) are held, the RSA signature is generated as follows: - **RSA signing and signature verification**
Signature = Message ^ **d** mod **n** The Crypto Framework provides the following padding modes for RSA signing and signature verification:
- **PKCS1**: RSASSA-PKCS1-V1_5 mode in RFC3447 (corresponding to RSA_PKCS1_PADDING in OpenSSL). When this mode is used for signing and signature verification, the digest (**md**) must be set, the digest algorithm output length (bytes) must be less than the RSA key modulus.
- **PSS**: RSASSA-PSS mode in RFC 3447 (corresponding to RSA_PKCS1_PSS_PADDING in OpenSSL). In this mode, two digests (**md** and **mgf1_md**) must be set, and the total length (bytes) of **md** and **mgf1_md** must be less than the RSA key modulus. In this mode, the salt length (**saltLen**, in bytes) can also be set, and PSS-related parameters can be obtained.<br>
The PSS parameters include the following:<br>
**md**: message digest algorithm.<br>
**mgf**: mask generation algorithm. Currently, only MGF1 is supported.<br>
**mgf1_md**: digest algorithm used in the MGF1 algorithm.<br>
**saltLen**: salt length, in bytes.<br>
**trailer_field**: integer used for encoding. The value must be **1**.
The signature verification process is as follows: > **NOTE**
>
> RSA key modulus = (RSA bits + 7)/8
Message = Signature ^ **d** mod **n** - **ECDSA**
The sender sends the message and the signature signed by the private key. The receiver decrypts the signature using the public key to verify the signature. Generally, the message sent is longer than the RSA key modulus. Therefore, the crypto framework provides two padding modes to extract the hash value of the message digest before signing the message. The crypto framework provides the following padding modes for signing and signature verification: The Elliptic Curve Digital Signature Algorithm (ECDSA) is a digital signature algorithm that uses the ECC. Compared with the ordinary Discrete Logarithm Problem (DLP) and Integer Factorization Problem (IFP), the ECC provides a higher unit bit strength than other public-key cryptographic systems. The Crypto Framework provides the ECDSA that combines multiple elliptic curves and digest algorithms.
- **PKCS1**: PKCS #1 v1.5 is the default padding mode for RSA encryption and decryption. When this mode is used, the digest (**md**) must be set. - **DSA**
- **PSS**: The PSS mode is a padding algorithm based on the RSA algorithm. When it is used, the digest (**md**) and mask function (**mgf1_md**) are required.
- ECDSA The DSA security is based on the difficulty of the DLP in integer finite field. The DSA features high compatibility and applicability.
The Elliptic Curve Digital Signature Algorithm (ECDSA) is a Digital Signature Algorithm (DSA) that uses the ECC. Compared with the ordinary Discrete Logarithm Problem (DLP) and Integer Factorization Problem (IFP), the ECC provides a higher unit bit strength than other public-key cryptographic systems. The crypto framework provides the ECDSA that combines multiple elliptic curve and digest algorithms. ### Key Agreement
**Key Agreement** **ECDH**
- **ECDH** Elliptic Curve Diffie-Hellman (ECDH) allows two parties to establish a shared secret over an insecure channel. The Crypto Framework provides a variety of ECDH capabilities based on the open-source algorithm library.
Elliptic Curve Diffie-Hellman (ECDH) allows two parties to establish a shared secret over an insecure channel. The crypto framework provides a variety of ECDH capabilities based on the open-source algorithm library. ### Message Digest
**Digest** The message digest (MD) algorithm allows a fixed-length digest to be generated from data of arbitrary size by using the hash algorithm. It is used for sensitive information encryption because it is infeasible to invert or reverse the computation. The MD algorithm is also referred to as a hash algorithm or a one-way hash algorithm.
The message digest algorithm allows a fixed-length digest to be generated from data of arbitrary size by using the hash algorithm. It is used for sensitive information encryption because it is infeasible to invert or reverse the computation. The MD algorithm is also referred to as a hash algorithm or a one-way hash algorithm.
When the same digest algorithm is used, the generated digest (hash value) has the following features: When the same digest algorithm is used, the generated digest (hash value) has the following features:
- The same message always results in the same hash value. - The same message always results in the same hash value.
- The digest generated is of the fixed length no matter the length of messages. (The digest length is determined by the algorithm used). - The digest generated is of the fixed length no matter the length of messages. (The digest length is determined by the algorithm used).
- It is almost impossible to find two different messages with the same hash value. (The probability still exists, depending on the length of the digest.) - It is almost impossible to find two different messages with the same hash value. (The probability still exists, depending on the length of the digest.)
There are three types of message digest algorithms: MD, SHA, and MAC. For details, see **HMAC**. There are three types of message digest algorithms: MD, SHA, and MAC. For details, see section "HMAC".
MD algorithms include MD2, MD4, and MD5. MD algorithms include MD2, MD4, and MD5.
Major SHA algorithms include SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512. Major SHA algorithms include SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512.
**HMAC** ### HMAC
Hash-based Message Authentication Code (HMAC) is a key-based message authentication code algorithm. HMAC provides authentication using a shared secret instead of using a digital signature. The MAC generated can be used to verify the integrity and authenticity of the message. The length of the MAC generated by HMAC is fixed. Compared with MAC, HMAC introduces the shared secret, which ensures data correctness. Hash-based Message Authentication Code (HMAC) is a key-based message authentication code algorithm. It provides authentication using a shared secret instead of using a digital signature. The MAC generated can be used to verify the integrity and authenticity of the message. The length of the MAC generated by HMAC is fixed. Compared with MAC, HMAC introduces the shared secret, which ensures data correctness.
**Random Number** ### Random Number
Random numbers are mainly used to generate temporary session keys or keys in asymmetric encryption. They are generated by a hardware random number generator or software-based pseudo-random number generator. In encryption and decryption, a secure random number generator must feature randomness, unrepeatability, and unpredictability. The random numbers generated by the Cryptography Secure Random Number Generator (CSPRNG) meet the requirements of cryptography security pseudo-randomness. Random numbers are mainly used to generate temporary session keys or keys in asymmetric encryption. They are generated by a hardware random number generator or software-based pseudo-random number generator. In encryption and decryption, a secure random number generator must feature randomness, unrepeatability, and unpredictability. The random numbers generated by the Cryptography Secure Random Number Generator (CSPRNG) meet the requirements of cryptography security pseudo-randomness.
- Internal state<br>A value in the random number generator memory. The same internal state produces the same sequence of the random number. - Internal state<br>A value in the random number generator memory. The same internal state produces the same sequence of the random number.
- Seed<br>A number used to initialize the internal state of a pseudorandom number generator. The random number generator generates a series of random sequences based on the seeds. - Seed<br>A number used to initialize the internal state of a pseudorandom number generator. The random number generator generates a series of random sequences based on the seeds.
## Constraints ## Constraints
- The crypto framework does not support concurrent operations of multiple threads. - The Crypto Framework does not support concurrent operations of multiple threads.
- Currently, the algorithm library supports only OpenSSL. - Currently, the algorithm library supports only OpenSSL.
- For a key generated based on key parameters, the bigint type must be a positive number in big-endian format.
- The Crypto Framework algorithm library provides common algorithms. Some algorithms and specifications, such as MD5, are not applicable to security scenarios. You need to select the proper algorithms as required.
### Key Generation Specifications ## Key Generation Specifications
**Symmetric Key Generation Specifications** A key can be generated based on either of the following specifications:
- String parameter: provides the specifications of the key to be generated in the form of a string.
- Key parameters: constructs a key object using the specific cryptography information.
- The following parameters are supported: ### AES Key Generation Specifications
|Symmetric Key Algorithm|Key Length (Bit)|String Parameter| The AES key can be generated based on a string parameter.
|---|---|---|
|3DES|192|3DES192| |Symmetric Key Algorithm|Key Length (Bit)|String Parameter|
|AES|128|AES128| |---|---|---|
|AES|192|AES192| |AES|128|AES128|
|AES|256|AES256| |AES|192|AES192|
|AES|256|AES256|
> **NOTE**
>
> As a combination of the symmetric key algorithm and the key length, the string parameter specifies the key specifications when a symmetric key generator is created.
> **NOTE**<br>**String Parameter** is a combination of **Symmetric Key Algorithm** and **Key Length**. It specifies the key specifications when a symmetric key generator is created. ### 3DES Key Generation Specifications
**Asymmetric Key Generation Specifications** The 3DES key can be generated based on a string parameter.
- **RSA key generation**
The following parameters are supported: |Symmetric Key Algorithm|Key Length (Bit)|String Parameter|
|---|---|---|
|3DES|192|3DES192|
|Asymmetric Key Type|Number of Primes|String Parameter| > **NOTE**
>
> As a combination of the symmetric key algorithm and the key length, the string parameter specifies the key specifications when a symmetric key generator is created.
### RSA Key Generation Specifications
> **NOTE**
>
> The RSA keys can be generated based on key parameters from API version 10.
- The RSA key can be generated based on a string parameter.
|RSA Key Type|Number of Primes|String Parameter|
|---|---|---| |---|---|---|
|RSA512|2|RSA512\|PRIMES_2| |RSA512|2|RSA512\|PRIMES_2|
|RSA768|2|RSA768\|PRIMES_2| |RSA768|2|RSA768\|PRIMES_2|
...@@ -187,48 +256,154 @@ Random numbers are mainly used to generate temporary session keys or keys in asy ...@@ -187,48 +256,154 @@ Random numbers are mainly used to generate temporary session keys or keys in asy
|RSA8192|4|RSA8192\|PRIMES_4| |RSA8192|4|RSA8192\|PRIMES_4|
|RSA8192|5|RSA8192\|PRIMES_5| |RSA8192|5|RSA8192\|PRIMES_5|
> **NOTE**<br>When an RSA asymmetric key is generated, the default prime number is 2, and **PRIMES_2** is optional. > **NOTE**
>
> As a combination of the RSA key type and the number of primes, the string parameter specifies the key specifications when an asymmetric key generator is created.
>
> The default number of primes for generating the RSA asymmetric key is 2, and **PRIMES_2** can be omitted.
- The RSA key can also be generated based on key parameters. The following table lists the types of key parameters and cryptography specifications of each key parameter.
- **ECC key generation** | |Common Parameter|Public Key Parameter|Private Key Parameter|Public/Private Key Pair Parameter|
|---|---------|---|---|---|
|n |× |√ |× |√ |
|pk| |√ | |√ |
|sk| | |× |√ |
The following parameters are supported: > **NOTE**
>
> The key parameters are used to specify the key specifications when an asymmetric key generator is created.
>
The preceding table describes the public and private key parameters supported by the Crypto Framework algorithm library for generating RSA keys.<br>**√** indicates that properties needs to be specified to construct the key parameter.<br>x indicates that the Crypto Framework currently does not support key generation based on this parameter.
|Asymmetric Key Algorithm|Key Length| > **CAUTION**
|---|---| >
|ECC|ECC224| > - RSA does not support random key generation by specifying the public parameter (**n**).
|ECC|ECC256| >
|ECC|ECC384| > - RSA does not support generation of the private key by specifying private key parameters (**n**, **sk**).
|ECC|ECC521|
### ECC Key Generation Specifications
> **NOTE**
>
> The ECC key can be generated based on key parameters from API version 10.
- The ECC key can be generated based on a string parameter.
|Asymmetric Key Algorithm|Key Length (Bit)|Curve Name|String Parameter|
|---|---|---|---|
|ECC|224|NID_secp224r1|ECC224|
|ECC|256|NID_X9_62_prime256v1|ECC256|
|ECC|384|NID_secp384r1|ECC384|
|ECC|521|NID_secp521r1|ECC521|
> **NOTE**
>
> As a combination of the asymmetric key algorithm and the key Length, the string parameter specifies the key specifications when an asymmetric key generator is created.
>
> Currently, only ECC Fp curves are supported.
- The ECC key can also be generated based on key parameters. The following table lists the types of key parameters and cryptography specifications of each key parameter.
| |Common Parameter|Public Key Parameter|Private Key Parameter|Public/Private Key Pair Parameter|
|---|---|---|---|---|
|fieldType| √| √| √| √|
|p | √| √| √| √|
|a | √| √| √| √|
|b | √| √| √| √|
|g | √| √| √| √|
|n | √| √| √| √|
|h | √| √| √| √|
|pk | | √| | √|
|sk | | | √| √|
### Encryption and Decryption Specifications > **NOTE**
>
> The key parameters specify the key specifications when an asymmetric key generator is created.
>
> The preceding table describes the public and private key parameters supported by the Crypto Framework algorithm library for generating ECC keys. √ indicates that properties need to be specified to construct the key parameter.
**Symmetric Encryption and Decryption** > **CAUTION**
>
> - Currently, the ECC supports only the **Fp** fields. Therefore, **fieldType** has a fixed value of **Fp**. **fieldType** and **p** constitute the property **field**, which currently supports only [ECFieldFp](../reference/apis/js-apis-cryptoFramework.md#ecfieldfp10).
> - **g** and **pk** are points on the ECC curve and belong to the [Point](../reference/apis/js-apis-cryptoFramework.md#point10) type. You need to specify the X and Y coordinates.
- The following symmetric encryption algorithms are supported: ### DSA Key Generation Specifications
|Algorithm|Block Cipher Mode| String Parameter | > **NOTE**
>
> From API version 10, the DSA algorithm is supported for key generation, signing, and signature verification.
- The DSA key can be generated based on a string parameter.
|Asymmetric Key Algorithm|Key Length (Bit)|String Parameter|
|---|---|---| |---|---|---|
|3DES|ECB|3DES192\|ECB\|[NoPadding\|PKCS5\|PKCS7]| |DSA|1024|DSA1024|
|3DES|CBC|3DES192\|CBC\|[NoPadding\|PKCS5\|PKCS7]| |DSA|2048|DSA2048|
|3DES|OFB|3DES192\|OFB\|[NoPadding\|PKCS5\|PKCS7]| |DSA|3072|DSA3072|
|3DES|CFB|3DES192\|CFB\|[NoPadding\|PKCS5\|PKCS7]|
|AES|ECB|AES[128\|192\|256]\|ECB\|[NoPadding\|PKCS5\|PKCS7]| > **NOTE**
|AES|CBC|AES[128\|192\|256]\|CBC\|[NoPadding\|PKCS5\|PKCS7]| >
|AES|CTR|AES[128\|192\|256]\|CTR\|[NoPadding\|PKCS5\|PKCS7]| > As a combination of the asymmetric key algorithm and the key length, the string parameter specifies the key specifications when an asymmetric key generator is created.
|AES|OFB|AES[128\|192\|256]\|OFB\|[NoPadding\|PKCS5\|PKCS7]|
|AES|CFB|AES[128\|192\|256]\|CFB\|[NoPadding\|PKCS5\|PKCS7]| - The DSA key can also be generated based on key parameters. The following table lists the types of key parameters and cryptography specifications of each key parameter.
|AES|GCM|AES[128\|192\|256]\|GCM\|[NoPadding\|PKCS5\|PKCS7]|
|AES|CCM|AES[128\|192\|256]\|CCM\|[NoPadding\|PKCS5\|PKCS7]| | |Common Parameter|Public Key Parameter|Private Key Parameter|Public/Private Key Pair Parameter|
|---|---------|---|---|---|
|p |√ |√ |× |√ |
|q |√ |√ |× |√ |
|g |√ |√ |× |√ |
|pk | |√ | |√ |
|sk | | |× |√ |
> **NOTE**
>
> The key parameters specify the key specifications when an asymmetric key generator is created.
>
> The preceding table describes the public and private key parameters supported by the Crypto Framework algorithm library for generating DSA keys.
>
> **√** indicates that properties needs to be specified to construct the key parameter.<br>x indicates that the Crypto Framework currently does not support key generation based on this parameter.
> **CAUTION**
>
> - DSA does not support generation of the private key by specifying the private key parameters (**p**, **q**, **g**, **sk**).
> - When common parameters (**p**, **q**, **g**) are specified to generate a DSA key pair, the DSA key length must be at least 1024 bits.
## Encryption and Decryption Specifications
### Symmetric Encryption and Decryption
> **NOTE**
>
> The APIs support specifications without the key length for symmetric encryption and decryption from API version 10.
The following symmetric encryption algorithms are supported.
|Symmetric Encryption and Decryption Algorithm|Block Cipher Mode|String Parameter |
|---|---|---|
|3DES|ECB|3DES192\|ECB\|[NoPadding\|PKCS5\|PKCS7]|
|3DES|CBC|3DES192\|CBC\|[NoPadding\|PKCS5\|PKCS7]|
|3DES|OFB|3DES192\|OFB\|[NoPadding\|PKCS5\|PKCS7]|
|3DES|CFB|3DES192\|CFB\|[NoPadding\|PKCS5\|PKCS7]|
|AES|ECB|AES[128\|192\|256]\|ECB\|[NoPadding\|PKCS5\|PKCS7]|
|AES|CBC|AES[128\|192\|256]\|CBC\|[NoPadding\|PKCS5\|PKCS7]|
|AES|CTR|AES[128\|192\|256]\|CTR\|[NoPadding\|PKCS5\|PKCS7]|
|AES|OFB|AES[128\|192\|256]\|OFB\|[NoPadding\|PKCS5\|PKCS7]|
|AES|CFB|AES[128\|192\|256]\|CFB\|[NoPadding\|PKCS5\|PKCS7]|
|AES|GCM|AES[128\|192\|256]\|GCM\|[NoPadding\|PKCS5\|PKCS7]|
|AES|CCM|AES[128\|192\|256]\|CCM\|[NoPadding\|PKCS5\|PKCS7]|
> **NOTE** > **NOTE**
> >
> - The options included in the square brackets ([]) are mutually exclusive. > - The options included in the square brackets ([]) are mutually exclusive.
> - **String Parameter** is a combination of **Algorithm** (including the key length), **Block Cipher Mode**, and padding mode. It specifies the symmetric encryption/decryption algorithm specifications when a symmetric encryption/decryption instance is created. > - As a combination of the algorithm (including the key length), block cipher mode, and padding mode, the string parameter specifies the symmetric encryption/decryption algorithm specifications when a symmetric encryption/decryption instance is created.
**Asymmetric RSA Encryption and Decryption** ### Asymmetric RSA Encryption and Decryption
> **NOTE**
>
> The APIs support specifications without the key length for asymmetric RSA encryption and decryption from API version 10.
The crypto framework provides three padding modes for RSA encryption/decryption: **NoPadding**, **PKCS1**, and **PKCS1_OAEP**. The Crypto Framework provides three padding modes for RSA encryption/decryption: **NoPadding**, **PKCS1**, and **PKCS1_OAEP**.
- Parameters for **NoPadding** - If **NoPadding** is used, the following parameters can be specified.
|Asymmetric Key Type| Padding Mode| String Parameter| |Asymmetric Key Type| Padding Mode| String Parameter|
|---|---|---| |---|---|---|
...@@ -239,8 +414,14 @@ The crypto framework provides three padding modes for RSA encryption/decryption: ...@@ -239,8 +414,14 @@ The crypto framework provides three padding modes for RSA encryption/decryption:
|RSA3072|NoPadding|RSA3072\|NoPadding| |RSA3072|NoPadding|RSA3072\|NoPadding|
|RSA4096|NoPadding|RSA4096\|NoPadding| |RSA4096|NoPadding|RSA4096\|NoPadding|
|RSA8192|NoPadding|RSA8192\|NoPadding| |RSA8192|NoPadding|RSA8192\|NoPadding|
|RSA|NoPadding|RSA\|NoPadding|
- Parameters for **PKCS1** > **NOTE**
>
> - As a combination of the asymmetric key type and the padding mode, the string parameter specifies the asymmetric encryption/decryption algorithm specifications when an asymmetric encryption/decryption instance is created.
> - The RSA key type in the last row of the preceding table does not contain the key length to ensure compatibility with the key generated based on the key parameters. The encryption/decryption operation varies depending on the actual key length.
- If **PKCS1** is used, the following parameters can be specified.
|Asymmetric Key Type| Padding Mode| String Parameter| |Asymmetric Key Type| Padding Mode| String Parameter|
|---|---|---| |---|---|---|
...@@ -251,174 +432,277 @@ The crypto framework provides three padding modes for RSA encryption/decryption: ...@@ -251,174 +432,277 @@ The crypto framework provides three padding modes for RSA encryption/decryption:
|RSA3072|PKCS1|RSA3072\|PKCS1| |RSA3072|PKCS1|RSA3072\|PKCS1|
|RSA4096|PKCS1|RSA4096\|PKCS1| |RSA4096|PKCS1|RSA4096\|PKCS1|
|RSA8192|PKCS1|RSA8192\|PKCS1| |RSA8192|PKCS1|RSA8192\|PKCS1|
|RSA|PKCS1|RSA\|PKCS1|
> **NOTE**
>
> - As a combination of the asymmetric key type and the padding mode, the string parameter specifies the asymmetric encryption/decryption algorithm specifications when an asymmetric encryption/decryption instance is created.
> - The RSA key type in the last row of the preceding table does not contain the key length to ensure compatibility with the key generated based on the key parameters. The encryption/decryption operation varies depending on the actual key length.
- If **PKCS1_OAEP** is used, the following parameters can be specified.
| Asymmetric Key Type| Padding Mode| Digest| Mask Digest|
|---|---|---|---|
|RSA512|PKCS1_OAEP|MD5| [MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]|
|RSA512|PKCS1_OAEP|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]|
|RSA512|PKCS1_OAEP|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]|
|RSA512|PKCS1_OAEP|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224]
|RSA768|PKCS1_OAEP|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA768|PKCS1_OAEP|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA768|PKCS1_OAEP|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA768|PKCS1_OAEP|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384]|
|RSA768|PKCS1_OAEP|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]|
|RSA768|PKCS1_OAEP|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224]|
|RSA1024|PKCS1_OAEP|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PKCS1_OAEP|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PKCS1_OAEP|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PKCS1_OAEP|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PKCS1_OAEP|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PKCS1_OAEP|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384]|
|RSA2048|PKCS1_OAEP|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PKCS1_OAEP|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PKCS1_OAEP|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PKCS1_OAEP|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PKCS1_OAEP|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PKCS1_OAEP|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PKCS1_OAEP|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PKCS1_OAEP|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PKCS1_OAEP|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PKCS1_OAEP|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PKCS1_OAEP|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PKCS1_OAEP|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PKCS1_OAEP|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PKCS1_OAEP|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PKCS1_OAEP|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PKCS1_OAEP|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PKCS1_OAEP|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PKCS1_OAEP|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PKCS1_OAEP|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PKCS1_OAEP|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PKCS1_OAEP|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PKCS1_OAEP|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PKCS1_OAEP|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PKCS1_OAEP|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA|PKCS1_OAEP|Digest algorithm that meets the requirements for length|MGF1_ digest algorithm that meets the requirements for length|
- Parameters for **PKCS1_OAEP**
> **NOTE** > **NOTE**
> >
> - The options included in the square brackets ([]) are mutually exclusive. The options outside the square brackets are fixed values. > - The options included in the square brackets ([]) are mutually exclusive. The options outside the square brackets are fixed values.
> - Combine the asymmetric key type, padding mode, digest, and mask digest, with a vertical bar (|) in between. For example, **RSA2048|PKCS1_OAEP|SHA256|MGF1_SHA256**. > - As a combination of the asymmetric key type, padding mode, digest, and mask digest with a vertical bar (|) in between, the string parameter specifies the asymmetric encryption/decryption algorithm specifications when an asymmetric encryption/decryption instance is created. For example, **RSA2048|PKCS1_OAEP|SHA256|MGF1_SHA256**.
> - The RSA key type in the last row of the preceding table does not contain the key length to ensure compatibility with the key generated based on the key parameters. The encryption/decryption operation varies depending on the actual key length.
| Asymmetric Key Type| Padding Mode| Digest| Mask Digest| > - The input data must meet the following requirement:<br>Input data length < RSA key modulus - **md** length - **mgf1_md** length - 2<br>For example, if the RSA key is 512 bits, SHA-512 is not supported. For details about the definition of the RSA key modulus and digest length, see "Asymmetric RSA encryption and decryption" in [Encryption and Decryption](#encryption-and-decryption).
|---|---|---|---|
|RSA512|PKCS1_OAEP|MD5| [MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]| - If **PKCS1_OAEP** is used, you can obtain the [OAEP cipher parameter](../reference/apis/js-apis-cryptoFramework.md#cipherspecitem10) and set the encoding input P for OAEP padding.
|RSA512|PKCS1_OAEP|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]|
|RSA512|PKCS1_OAEP|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]| | OAEP Parameter|Enum Value| Get()| Set()|
|RSA512|PKCS1_OAEP|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224]| |---|---|---|---|
|RSA768|PKCS1_OAEP|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]| |md|OAEP_MD_NAME_STR |√|
|RSA768|PKCS1_OAEP|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]| |mgf|OAEP_MGF_NAME_STR|√|
|RSA768|PKCS1_OAEP|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]| |mgf1_md|OAEP_MGF1_MD_STR |√|
|RSA768|PKCS1_OAEP|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384]| |pSource|OAEP_MGF1_PSRC_UINT8ARR|√|√|
|RSA768|PKCS1_OAEP|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]|
|RSA768|PKCS1_OAEP|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224]| > **NOTE**
|RSA1024|PKCS1_OAEP|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]| >
|RSA1024|PKCS1_OAEP|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]| > The preceding table presents the **Get()** and **Set()** capabilities for OAEP parameters supported by the Crypto Framework. **√** indicates that the parameter can be obtained or set.
|RSA1024|PKCS1_OAEP|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PKCS1_OAEP|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]| ## Signing and Signature Verification Specifications
|RSA1024|PKCS1_OAEP|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PKCS1_OAEP|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384]| ### RSA Signing and Signature Verification
|RSA2048|PKCS1_OAEP|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PKCS1_OAEP|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]| > **NOTE**
|RSA2048|PKCS1_OAEP|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]| >
|RSA2048|PKCS1_OAEP|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]| > The APIs support specifications without the key length for RSA signing and signature verification from API version 10.
|RSA2048|PKCS1_OAEP|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PKCS1_OAEP|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]| The Crypto Framework provides two padding modes for RSA signing and signature verification: **PKCS1** and **PSS**.
|RSA3072|PKCS1_OAEP|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PKCS1_OAEP|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]| - If **PKCS1** is used, the following parameters can be specified.
|RSA3072|PKCS1_OAEP|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PKCS1_OAEP|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PKCS1_OAEP|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PKCS1_OAEP|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PKCS1_OAEP|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PKCS1_OAEP|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PKCS1_OAEP|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PKCS1_OAEP|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PKCS1_OAEP|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PKCS1_OAEP|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PKCS1_OAEP|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PKCS1_OAEP|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PKCS1_OAEP|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PKCS1_OAEP|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512 ]|
|RSA8192|PKCS1_OAEP|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PKCS1_OAEP|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
### Signing and Signature Verification Specifications
**RSA Signing and Signature Verification**
The crypto framework provides two padding modes for RSA signing and signature verification: **PKCS1** and **PSS**.
- Parameters for **PKCS1**
| Asymmetric Key Type| Padding Mode| Digest| String Parameter| | Asymmetric Key Type| Padding Mode| Digest| String Parameter|
|---|---|---|---| |---|---|---|---|
|RSA512|PKCS1|[MD5\|SHA1\|SHA224\|SHA256\|SHA384]|RSA512\|PKCS1\| [MD5\|SHA1\|SHA224\|SHA256\|SHA384]| |RSA512|PKCS1|[MD5\|SHA1\|SHA224\|SHA256\|SHA384]|RSA512\|PKCS1\|[MD5\|SHA1\|SHA224\|SHA256\|SHA384]|
|RSA768|PKCS1|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|RSA768\|PKCS1\|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]| |RSA768|PKCS1|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|RSA768\|PKCS1\|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
|RSA1024|PKCS1|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|RSA1024\|PKCS1\|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]| |RSA1024|PKCS1|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|RSA1024\|PKCS1\|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
|RSA2048|PKCS1|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|RSA2048\|PKCS1\|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]| |RSA2048|PKCS1|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|RSA2048\|PKCS1\|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
|RSA3072|PKCS1|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|RSA3072\|PKCS1\|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]| |RSA3072|PKCS1|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|RSA3072\|PKCS1\|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
|RSA4096|PKCS1|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|RSA4096\|PKCS1\|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]| |RSA4096|PKCS1|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|RSA4096\|PKCS1\|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
|RSA8192|PKCS1|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|RSA8192\|PKCS1\|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]| |RSA8192|PKCS1|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|RSA8192\|PKCS1\|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
|RSA|PKCS1|Digest algorithm that meets the requirements for length|RSA\|PKCS1\|Digest algorithm that meets the requirements for length|
- Parameters for **PSS**
> **NOTE** > **NOTE**
> >
> - The options included in the square brackets ([]) are mutually exclusive. The options outside the square brackets are fixed values. > - The options included in the square brackets ([]) are mutually exclusive. The options outside the square brackets are fixed values.
> - Combine the asymmetric key type, padding mode, digest, and mask digest, with a vertical bar (|) in between. For example, **RSA2048|PSS|SHA256|MGF1_SHA256**. > - The RSA key type in the last row of the preceding table does not contain the key length to ensure compatibility with the key generated based on the key parameters. The signing or signature verification operation varies depending on the actual key length.
> - During RSA signature verification, the output length of the digest algorithm must be less than the RSA key modulus. For example, if the RSA key is 512 bits, SHA-512 is not supported. For details, see "RSA signing and signature verification" in [Signing and Signature Verification](#signing-and-signature-verification).
| Asymmetric Key Type| Padding Mode| Digest| Mask Digest|
|---|---|---|---|
|RSA512|PSS|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]|
|RSA512|PSS|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]|
|RSA512|PSS|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]|
|RSA512|PSS|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224]|RSA512\|PSS\|SHA256\|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224]|
|RSA768|PSS|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA768|PSS|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA768|PSS|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA768|PSS|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384]|
|RSA768|PSS|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]|
|RSA768|PSS|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224]|
|RSA1024|PSS|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PSS|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PSS|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PSS|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PSS|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PSS|SHA512| [MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384]|
|RSA2048|PSS|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PSS|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PSS|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PSS|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PSS|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PSS|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PSS|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PSS|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PSS|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PSS|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PSS|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PSS|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PSS|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PSS|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PSS|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PSS|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PSS|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PSS|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PSS|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PSS|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PSS|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PSS|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PSS|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PSS|SHA512| [MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
**ECDSA Signing and Signature Verification**
- The following ECDSA parameters are supported:
|Asymmetric Key Algorithm|Supported Type|
|---|---|
|ECC|ECC224|
|ECC|ECC256|
|ECC|ECC384|
|ECC|ECC521|
|Digest Algorithm|Supported Type| - If **PSS** is used, the following parameters can be specified.
|---|---|
|HASH|SHA1|
|HASH|SHA224|
|HASH|SHA256|
|HASH|SHA384|
|HASH|SHA512|
### Key Agreement Specifications | Asymmetric Key Type| Padding Mode| Digest| Mask Digest|
|---|---|---|---|
|RSA512|PSS|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]|
|RSA512|PSS|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]|
|RSA512|PSS|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]|
|RSA512|PSS|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224]|RSA512\|PSS\|SHA256\|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224]|
|RSA768|PSS|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA768|PSS|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA768|PSS|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA768|PSS|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384]|
|RSA768|PSS|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256]|
|RSA768|PSS|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224]|
|RSA1024|PSS|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PSS|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PSS|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PSS|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PSS|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA1024|PSS|SHA512| [MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384]|
|RSA2048|PSS|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PSS|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PSS|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PSS|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PSS|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA2048|PSS|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PSS|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PSS|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PSS|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PSS|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PSS|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA3072|PSS|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PSS|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PSS|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PSS|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PSS|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PSS|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA4096|PSS|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PSS|MD5|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PSS|SHA1|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PSS|SHA224|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PSS|SHA256|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PSS|SHA384|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA8192|PSS|SHA512|[MGF1_MD5\|MGF1_SHA1\|MGF1_SHA224\|MGF1_SHA256\|MGF1_SHA384\|MGF1_SHA512]|
|RSA|PSS|Digest algorithm that meets the requirements for length|MGF1_ digest algorithm that meets the requirements for length|
**ECDH** > **NOTE**
>
> - The options included in the square brackets ([]) are mutually exclusive. The options outside the square brackets are fixed values.
> - As a combination of the asymmetric key type, padding mode, digest, and mask digest with a vertical bar (|) in between, the string parameter specifies the asymmetric signing or signature verification algorithm specifications when an asymmetric signing or signature verification instance is created. For example, **RSA2048|PSS|SHA256|MGF1_SHA256**.
> - The RSA key type in the last row of the preceding table does not contain the key length to ensure compatibility with the key generated based on the key parameters. The signing or signature verification operation varies depending on the actual key length.
> - If the PSS padding mode is used in RSA signing or signature verification, the total length (in bytes) of **md** and **mgf1_md** must be less than the RSA key modulus. For example, if the RSA key is 512 bits, **md** and **mgf1_md** cannot be SHA256 at the same time. For details about the definition of the RSA key modulus and digest length, see "RSA signing and signature verification" in [Signing and Signature Verification](#signing-and-signature-verification).
- If the PSS mode is used, you can obtain the PSS [parameter](../reference/apis/js-apis-cryptoFramework.md#signspecitem10) for signing or signature verification, and set the salt length (**saltLen**, in bytes) for the PSS.
| PSS Parameter|Enum Value| Get()| Set()|
|---|---|---|---|
|md|PSS_MD_NAME_STR |√|
|mgf|PSS_MGF_NAME_STR|√|
|mgf1_md|PSS_MGF1_MD_STR |√|
|saltLen|PSS_SALT_LEN_NUM|√|√|
|trailer_field|PSS_TRAILER_FIELD_NUM|√|
> **NOTE**
>
> The preceding table presents the **Get()** and **Set()** capabilities for PSS parameters supported by the Crypto Framework. **√** indicates that the parameter can be obtained or set.
### ECDSA Signing and Signature Verification
> **NOTE**
> The APIs support specifications without the key length for ECDSA signing and signature verification from API version 10.
- The following ECDSA parameters are supported.
|Asymmetric Key Type|Digest|String Parameter|
|---|---|---|
|ECC224|[SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|ECC224\|[SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
|ECC256|[SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|ECC256\|[SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
|ECC384|[SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|ECC384\|[SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
|ECC521|[SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|ECC521\|[SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
|ECC|[SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|ECC\|[SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
> **NOTE**
>
> - The options included in the square brackets ([]) are mutually exclusive. The options outside the square brackets are fixed values.
> - As a combination of the asymmetric key type and digest with a vertical bar (|) in between, the string parameter specifies the asymmetric signing or signature verification algorithm specifications when an asymmetric signing or signature verification instance is created. For example, **ECC224|SHA256**.
> - The ECC key type in the last row of the preceding table does not contain the key length to ensure compatibility with the key generated based on the key parameters. The ECDSA signing or signature verification operation varies depending on the actual key length.
### DSA Signing and Signature Verification
> **NOTE**
>
> DSA signing and signature verification specifications are supported from API version 10.
- The following DSA parameters are supported.
|Asymmetric Key Type|Digest|String Parameter|
|---|---|---|
|DSA1024|[NoHash\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|DSA1024\|[NoHash\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
|DSA2048|[NoHash\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|DSA2048\|[NoHash\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
|DSA3072|[NoHash\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|DSA3072\|[NoHash\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
|DSA|[NoHash\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|DSA\|[NoHash\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512]|
> **NOTE**
>
> - The options included in the square brackets ([]) are mutually exclusive. The options outside the square brackets are fixed values.
> - As a combination of the asymmetric key type and digest with a vertical bar (|) in between, the string parameter specifies the asymmetric signing or signature verification algorithm specifications when an asymmetric signing or signature verification instance is created. For example, **DSA1024|SHA256**.
> - The DSA key type in the last row of the preceding table does not contain the key length to ensure compatibility with the key generated based on the key parameters. The signing or signature verification operation varies depending on the actual key length.
## Key Agreement Specifications
- The following ECDH parameters are supported: ### ECDH
|Asymmetric Key Algorithm|Supported Type| > **NOTE**
>
> The APIs support specifications without the key length for ECDH from API version 10.
- The following ECDH parameters are supported.
|Asymmetric Key Algorithm|String Parameter|
|---|---| |---|---|
|ECC|ECC224| |ECC|ECC224|
|ECC|ECC256| |ECC|ECC256|
|ECC|ECC384| |ECC|ECC384|
|ECC|ECC521| |ECC|ECC521|
|ECC|ECC|
### MD Algorithm Specifications > **NOTE**
- The crypto framework supports the following MD algorithm parameters: >
> - The string parameter specifies the key agreement algorithm specifications when a key agreement instance is created.
> - The ECC key type in the last row of the preceding table does not contain the key length to ensure compatibility with the key generated based on the key parameters. The ECDH key agreement operation varies depending on the actual key length.
|Digest Algorithm|Supported Type|
|---|---|
|HASH|SHA1|
|HASH|SHA224|
|HASH|SHA256|
|HASH|SHA384|
|HASH|SHA512|
|HASH|MD5|
### HMAC Algorithm Specifications ## MD Algorithm Specifications
- The crypto framework supports the following HMAC algorithm parameters:
|Digest Algorithm|Supported Type| The Crypto Framework supports the following MD algorithm parameters.
|---|---|
|HASH|SHA1| |Digest algorithm|Supported Type|
|HASH|SHA224| |---|---|
|HASH|SHA256| |HASH|SHA1|
|HASH|SHA384| |HASH|SHA224|
|HASH|SHA512| |HASH|SHA256|
|HASH|SHA384|
|HASH|SHA512|
|HASH|MD5|
> **NOTE**
>
> **Supported Type** specifies the MD algorithm specifications when an MD instance is created.
## HMAC Algorithm Specifications
The Crypto Framework supports the following HMAC algorithm parameters.
|Digest algorithm|Supported Type|
|---|---|
|HASH|SHA1|
|HASH|SHA224|
|HASH|SHA256|
|HASH|SHA384|
|HASH|SHA512|
> **NOTE**
>
> **Supported Type** specifies the HMAC algorithm specifications when an HMAC instance is created.
## Random Number
Currently, the Crypto Framework supports only the CTR_DRBG algorithm.
> **NOTE**
>
> - Currently, only secure random numbers with length of 1 to **INT_MAX** bytes are supported.
> - The random number generation algorithm uses the **RAND_priv_bytes** interface of OpenSSL to generate secure random numbers.
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册