From 491a711ed37fdd5632b73552a15004623ff3c43b Mon Sep 17 00:00:00 2001
From: wutiantian_gitee <1159609162@qq.com>
Date: Tue, 4 Jul 2023 17:46:30 +0800
Subject: [PATCH] modify doc of cryptFramework
Signed-off-by: wutiantian_gitee <1159609162@qq.com>
---
.../security/cryptoFramework-guidelines.md | 15 +-
.../reference/apis/js-apis-cryptoFramework.md | 22 +-
.../security/cryptoFramework-guidelines.md | 375 +++++++++++++++++-
.../security/cryptoFramework-overview.md | 129 +++++-
4 files changed, 511 insertions(+), 30 deletions(-)
diff --git a/en/application-dev/security/cryptoFramework-guidelines.md b/en/application-dev/security/cryptoFramework-guidelines.md
index f1a037f2bb..bea49347b3 100644
--- a/en/application-dev/security/cryptoFramework-guidelines.md
+++ b/en/application-dev/security/cryptoFramework-guidelines.md
@@ -58,12 +58,11 @@ function generateAsyKey() {
// Use the key generator to randomly generate an asymmetric key pair.
let keyGenPromise = rsaGenerator.generateKeyPair();
keyGenPromise.then( keyPair => {
- globalKeyPair = keyPair;
- let pubKey = globalKeyPair.pubKey;
- let priKey = globalKeyPair.priKey;
+ let pubKey = keyPair.pubKey;
+ let priKey = keyPair.priKey;
// Obtain the binary data of the asymmetric key pair.
- pkBlob = pubKey.getEncoded();
- skBlob = priKey.getEncoded();
+ let pkBlob = pubKey.getEncoded();
+ let skBlob = priKey.getEncoded();
AlertDialog.show({ message : "pk bin data" + pkBlob.data} );
AlertDialog.show({ message : "sk bin data" + skBlob.data} );
})
@@ -145,7 +144,7 @@ function convertEccAsyKey() {
let priKeyArray = new Uint8Array([48,49,2,1,1,4,32,115,56,137,35,207,0,60,191,90,61,136,105,210,16,27,4,171,57,10,61,123,40,189,28,34,207,236,22,45,223,10,189,160,10,6,8,42,134,72,206,61,3,1,7]);
let pubKeyBlob = { data: pubKeyArray };
let priKeyBlob = { data: priKeyArray };
- let generator = cryptoFrameWork.createAsyKeyGenerator("ECC256");
+ let generator = cryptoFramework.createAsyKeyGenerator("ECC256");
generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => {
if (error) {
AlertDialog.show({message : "Convert keypair fail"});
@@ -884,7 +883,7 @@ function stringToUint8Array(str) {
}
// Encrypt the message in promise mode.
-function encryptMessageProMise() {
+function encryptMessagePromise() {
// Create an AsyKeyGenerator instance.
let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
// Create a Cipher instance.
@@ -927,7 +926,7 @@ function encryptMessageCallback() {
}
// Encrypt and decrypt the message in promise mode.
-function decryptMessageProMise() {
+function decryptMessagePromise() {
// Create an AsyKeyGenerator instance.
let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
// Create a Cipher instance for encryption.
diff --git a/zh-cn/application-dev/reference/apis/js-apis-cryptoFramework.md b/zh-cn/application-dev/reference/apis/js-apis-cryptoFramework.md
index b44328c930..73bff799e5 100644
--- a/zh-cn/application-dev/reference/apis/js-apis-cryptoFramework.md
+++ b/zh-cn/application-dev/reference/apis/js-apis-cryptoFramework.md
@@ -58,7 +58,7 @@ buffer数组。
| 名称 | 类型 | 可读 | 可写 | 说明 |
| ---- | --------------------- | ---- | ---- | ------------------------------------------------------------ |
-| iv | [DataBlob](#datablob) | 是 | 是 | 指明加解密参数iv。常见取值如下:
- AES的CBC\|CTR\|OFB\|CFB模式:iv长度为16字节
- 3DES的CBC\|OFB\|CFB模式:iv长度为8字节 |
+| iv | [DataBlob](#datablob) | 是 | 是 | 指明加解密参数iv。常见取值如下:
- AES的CBC\|CTR\|OFB\|CFB模式:iv长度为16字节
- 3DES的CBC\|OFB\|CFB模式:iv长度为8字节
- SM4的CBC\|CTR\|OFB\|CFB模式:iv长度为16字节。 |
> **说明:**
>
@@ -1297,7 +1297,7 @@ createCipher(transformation: string): Cipher
> **说明:**
>
> 1. 目前对称加解密中,PKCS5和PKCS7的实现相同,其padding长度和分组长度保持一致(即PKCS5和PKCS7在3DES中均按照8字节填充,在AES中均按照16字节填充),另有NoPadding表示不填充。
开发者需要自行了解密码学不同分组模式的差异,以便选择合适的参数规格。例如选择ECB和CBC模式时,建议启用填充,否则必须确保明文长度是分组大小的整数倍;选择其他模式时,可以不启用填充,此时密文长度和明文长度一致(即可能不是分组大小的整数倍)。
-> 2. 使用RSA进行非对称加解密时,必须创建两个Cipher对象分别进行加密和解密操作,而不能对同一个Cipher对象进行加解密。对称加解密没有此要求(即只要算法规格一样,可以对同一个Cipher对象进行加解密操作)。
+> 2. 使用RSA、SM2进行非对称加解密时,必须创建两个Cipher对象分别进行加密和解密操作,而不能对同一个Cipher对象进行加解密。对称加解密没有此要求(即只要算法规格一样,可以对同一个Cipher对象进行加解密操作)。
**返回值:**
@@ -1335,7 +1335,7 @@ try {
一次完整的加/解密流程在对称加密和非对称加密中略有不同:
- 对称加解密:init为必选,update为可选(且允许多次update加/解密大数据),doFinal为必选;doFinal结束后可以重新init开始新一轮加/解密流程。
-- RSA非对称加解密:init为必选,不支持update操作,doFinal为必选(允许连续多次doFinal加/解密大数据);RSA不支持重复init,切换加解密模式或填充方式时,需要重新创建Cipher对象。
+- RSA、SM2非对称加解密:init为必选,不支持update操作,doFinal为必选(允许连续多次doFinal加/解密大数据);RSA不支持重复init,切换加解密模式或填充方式时,需要重新创建Cipher对象。
### 属性
@@ -1447,7 +1447,7 @@ update(data: DataBlob, callback: AsyncCallback\): void
> 2. 根据数据量,可以不调用update(即[init](#init-2)完成后直接调用[doFinal](#dofinal-2))或多次调用update。
> 算法库目前没有对update(单次或累计)的数据量设置大小限制,建议对于大数据量的对称加解密,采用多次update的方式传入数据。
> AES使用多次update操作的示例代码详见开发指导“[使用加解密操作](../../security/cryptoFramework-guidelines.md#使用加解密操作)”。
-> 3. RSA非对称加解密不支持update操作。
+> 3. RSA、SM2非对称加解密不支持update操作。
**系统能力:** SystemCapability.Security.CryptoFramework
@@ -1508,7 +1508,7 @@ update(data: DataBlob): Promise\
> 2. 根据数据量,可以不调用update(即[init](#init-2)完成后直接调用[doFinal](#dofinal-2))或多次调用update。
> 算法库目前没有对update(单次或累计)的数据量设置大小限制,建议对于大数据量的对称加解密,可以采用多次update的方式传入数据。
> AES使用多次update操作的示例代码详见开发指导“[使用加解密操作](../../security/cryptoFramework-guidelines.md#使用加解密操作)”。
-> 3. RSA非对称加解密不支持update操作。
+> 3. RSA、SM2非对称加解密不支持update操作。
**系统能力:** SystemCapability.Security.CryptoFramework
@@ -1570,14 +1570,14 @@ doFinal(data: DataBlob, callback: AsyncCallback\): void
- 对于GCM和CCM模式的对称加密:一次加密流程中,如果将每一次update和doFinal的结果拼接起来,会得到“密文+authTag”,即末尾的16字节(GCM模式)或12字节(CCM模式)是authTag,而其余部分均为密文。(也就是说,如果doFinal的data参数传入null,则doFinal的结果就是authTag)
authTag需要填入解密时的[GcmParamsSpec](#gcmparamsspec)或[CcmParamsSpec](#ccmparamsspec);密文则作为解密时的入参data。
- 对于其他模式的对称加解密、GCM和CCM模式的对称解密:一次加/解密流程中,每一次update和doFinal的结果拼接起来,得到完整的明文/密文。
-(2)在RSA非对称加解密中,doFinal加/解密本次传入的数据,通过注册回调函数获取加密或者解密数据。如果数据量较大,可以多次调用doFinal,拼接结果得到完整的明文/密文。
+(2)在RSA、SM2非对称加解密中,doFinal加/解密本次传入的数据,通过注册回调函数获取加密或者解密数据。如果数据量较大,可以多次调用doFinal,拼接结果得到完整的明文/密文。
> **说明:**
>
> 1. 对称加解密中,调用doFinal标志着一次加解密流程已经完成,即[Cipher](#cipher)实例的状态被清除,因此当后续开启新一轮加解密流程时,需要重新调用[init()](init-2)并传入完整的参数列表进行初始化
(比如即使是对同一个Cipher实例,采用同样的对称密钥,进行加密然后解密,则解密中调用init的时候仍需填写params参数,而不能直接省略为null)。
> 2. 如果遇到解密失败,需检查加解密数据和[init](#init-2)时的参数是否匹配,包括GCM模式下加密得到的authTag是否填入解密时的GcmParamsSpec等。
> 3. doFinal的结果可能为null,因此使用.data字段访问doFinal结果的具体数据前,请记得先判断结果是否为null,避免产生异常。
-> 4. RSA非对称加解密时多次doFinal操作的示例代码详见开发指导“[使用加解密操作](../../security/cryptoFramework-guidelines.md#使用加解密操作)”。
+> 4. RSA、SM2非对称加解密时多次doFinal操作的示例代码详见开发指导“[使用加解密操作](../../security/cryptoFramework-guidelines.md#使用加解密操作)”。
**系统能力:** SystemCapability.Security.CryptoFramework
@@ -1626,14 +1626,14 @@ doFinal(data: DataBlob): Promise\
- 对于GCM和CCM模式的对称加密:一次加密流程中,如果将每一次update和doFinal的结果拼接起来,会得到“密文+authTag”,即末尾的16字节(GCM模式)或12字节(CCM模式)是authTag,而其余部分均为密文。(也就是说,如果doFinal的data参数传入null,则doFinal的结果就是authTag)
authTag需要填入解密时的[GcmParamsSpec](#gcmparamsspec)或[CcmParamsSpec](#ccmparamsspec);密文则作为解密时的入参data。
- 对于其他模式的对称加解密、GCM和CCM模式的对称解密:一次加/解密流程中,每一次update和doFinal的结果拼接起来,得到完整的明文/密文。
-(2)在RSA非对称加解密中,doFinal加/解密本次传入的数据,通过Promise获取加密或者解密数据。如果数据量较大,可以多次调用doFinal,拼接结果得到完整的明文/密文。
+(2)在RSA、SM2非对称加解密中,doFinal加/解密本次传入的数据,通过Promise获取加密或者解密数据。如果数据量较大,可以多次调用doFinal,拼接结果得到完整的明文/密文。
> **说明:**
>
> 1. 对称加解密中,调用doFinal标志着一次加解密流程已经完成,即[Cipher](#cipher)实例的状态被清除,因此当后续开启新一轮加解密流程时,需要重新调用[init()](init-2)并传入完整的参数列表进行初始化
(比如即使是对同一个Cipher实例,采用同样的对称密钥,进行加密然后解密,则解密中调用init的时候仍需填写params参数,而不能直接省略为null)。
> 2. 如果遇到解密失败,需检查加解密数据和[init](#init-2)时的参数是否匹配,包括GCM模式下加密得到的authTag是否填入解密时的GcmParamsSpec等。
> 3. doFinal的结果可能为null,因此使用.data字段访问doFinal结果的具体数据前,请记得先判断结果是否为null,避免产生异常。
-> 4. RSA非对称加解密时多次doFinal操作的示例代码详见开发指导“[使用加解密操作](../../security/cryptoFramework-guidelines.md#使用加解密操作)”。
+> 4. RSA、SM2非对称加解密时多次doFinal操作的示例代码详见开发指导“[使用加解密操作](../../security/cryptoFramework-guidelines.md#使用加解密操作)”。
**系统能力:** SystemCapability.Security.CryptoFramework
@@ -1820,7 +1820,7 @@ Sign实例生成。
支持的规格详见框架概述“[签名验签规格]
| 参数名 | 类型 | 必填 | 说明 |
| ------- | ------ | ---- | ------------------------------------------------------------ |
-| algName | string | 是 | 指定签名算法:RSA,ECC或DSA。使用RSA PKCS1模式时需要设置摘要,使用RSA PSS模式时需要设置摘要和掩码摘要。 |
+| algName | string | 是 | 指定签名算法:RSA,SM2,ECC或DSA。使用RSA PKCS1模式时需要设置摘要,使用RSA PSS模式时需要设置摘要和掩码摘要。 |
**返回值**:
@@ -2207,7 +2207,7 @@ Verify实例生成。
支持的规格详见框架概述“[签名验签规
| 参数名 | 类型 | 必填 | 说明 |
| ------- | ------ | ---- | ------------------------------------------------------------ |
-| algName | string | 是 | 指定签名算法:RSA,ECC或DSA。使用RSA PKCS1模式时需要设置摘要,使用RSA PSS模式时需要设置摘要和掩码摘要。 |
+| algName | string | 是 | 指定签名算法:RSA,SM2,ECC或DSA。使用RSA PKCS1模式时需要设置摘要,使用RSA PSS模式时需要设置摘要和掩码摘要。 |
**返回值**:
diff --git a/zh-cn/application-dev/security/cryptoFramework-guidelines.md b/zh-cn/application-dev/security/cryptoFramework-guidelines.md
index 0959464d69..239686e323 100644
--- a/zh-cn/application-dev/security/cryptoFramework-guidelines.md
+++ b/zh-cn/application-dev/security/cryptoFramework-guidelines.md
@@ -60,12 +60,11 @@ function generateAsyKey() {
// 通过非对称密钥生成器,随机生成非对称密钥
let keyGenPromise = rsaGenerator.generateKeyPair();
keyGenPromise.then( keyPair => {
- globalKeyPair = keyPair;
- let pubKey = globalKeyPair.pubKey;
- let priKey = globalKeyPair.priKey;
+ let pubKey = keyPair.pubKey;
+ let priKey = keyPair.priKey;
// 获取非对称密钥的二进制数据
- pkBlob = pubKey.getEncoded();
- skBlob = priKey.getEncoded();
+ let pkBlob = pubKey.getEncoded();
+ let skBlob = priKey.getEncoded();
AlertDialog.show({ message : "pk bin data" + pkBlob.data} );
AlertDialog.show({ message : "sk bin data" + skBlob.data} );
})
@@ -147,7 +146,7 @@ function convertEccAsyKey() {
let priKeyArray = new Uint8Array([48,49,2,1,1,4,32,115,56,137,35,207,0,60,191,90,61,136,105,210,16,27,4,171,57,10,61,123,40,189,28,34,207,236,22,45,223,10,189,160,10,6,8,42,134,72,206,61,3,1,7]);
let pubKeyBlob = { data: pubKeyArray };
let priKeyBlob = { data: priKeyArray };
- let generator = cryptoFrameWork.createAsyKeyGenerator("ECC256");
+ let generator = cryptoFramework.createAsyKeyGenerator("ECC256");
generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => {
if (error) {
AlertDialog.show({message : "Convert keypair fail"});
@@ -209,6 +208,94 @@ function testConvertAesKey() {
}
```
+### 随机生成SM2密钥对,并获得二进制数据
+
+示例6:随机生成非对称密钥KeyPair,并获得二进制数据(场景1、3)
+
+1. 创建非对称密钥生成器。
+2. 通过非对称密钥生成器随机生成非对称密钥。
+3. 获取密钥对象的二进制数据。
+
+以使用Promise方式随机生成SM2密钥(256位)为例:
+
+```js
+import cryptoFramework from '@ohos.security.cryptoFramework';
+
+function generateAsyKey() {
+ // 创建非对称密钥生成器
+ let rsaGenerator = cryptoFramework.createAsyKeyGenerator("SM2_256");
+ // 通过非对称密钥生成器,随机生成非对称密钥
+ let keyGenPromise = rsaGenerator.generateKeyPair();
+ keyGenPromise.then( keyPair => {
+ let pubKey = keyPair.pubKey;
+ let priKey = keyPair.priKey;
+ // 获取非对称密钥的二进制数据
+ let pkBlob = pubKey.getEncoded();
+ let skBlob = priKey.getEncoded();
+ AlertDialog.show({ message : "pk bin data" + pkBlob.data} );
+ AlertDialog.show({ message : "sk bin data" + skBlob.data} );
+ })
+}
+```
+
+### 随机生成SM4密钥,并获得二进制数据
+
+示例7:随机生成对称密钥SymKey,并获得二进制数据(场景1、3)
+
+1. 创建对称密钥生成器。
+2. 通过对称密钥生成器随机生成对称密钥。
+3. 获取算法库密钥对象的二进制数据。
+
+以使用Promise方式随机生成SM4密钥(128位)为例:
+
+```js
+import cryptoFramework from '@ohos.security.cryptoFramework';
+
+// 字节流以16进制输出
+function uint8ArrayToShowStr(uint8Array) {
+ return Array.prototype.map
+ .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
+ .join('');
+}
+
+function testGenerateAesKey() {
+ // 创建对称密钥生成器
+ let symKeyGenerator = cryptoFramework.createSymKeyGenerator("SM4_128");
+ // 通过密钥生成器随机生成对称密钥
+ let promiseSymKey = symKeyGenerator.generateSymKey();
+ promiseSymKey.then( key => {
+ // 获取对称密钥的二进制数据,输出长度为256bit的字节流
+ let encodedKey = key.getEncoded();
+ console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data));
+ })
+}
+```
+
+### 根据SM2密钥二进制数据,生成密钥对
+
+示例8:根据指定的SM2非对称密钥二进制数据,生成KeyPair对象(场景2、3)
+
+1. 获取SM2二进制密钥数据,封装成DataBlob对象。
+2. 调用convertKey方法,传入公钥二进制和私钥二进制(二者非必选项,可只传入其中一个),转换为KeyPair对象。
+
+```js
+import cryptoFramework from '@ohos.security.cryptoFramework';
+
+function convertSM2AsyKey() {
+ let pubKeyArray = new Uint8Array([48,89,48,19,6,7,42,134,72,206,61,2,1,6,8,42,129,28,207,85,1,130,45,3,66,0,4,90,3,58,157,190,248,76,7,132,200,151,208,112,230,96,140,90,238,211,155,128,109,248,40,83,214,78,42,104,106,55,148,249,35,61,32,221,135,143,100,45,97,194,176,52,73,136,174,40,70,70,34,103,103,161,99,27,187,13,187,109,244,13,7]);
+ let priKeyArray = new Uint8Array([48,49,2,1,1,4,32,54,41,239,240,63,188,134,113,31,102,149,203,245,89,15,15,47,202,170,60,38,154,28,169,189,100,251,76,112,223,156,159,160,10,6,8,42,129,28,207,85,1,130,45]);
+ let pubKeyBlob = { data: pubKeyArray };
+ let priKeyBlob = { data: priKeyArray };
+ let generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
+ generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => {
+ if (error) {
+ AlertDialog.show({message : "Convert keypair fail"});
+ }
+ AlertDialog.show({message : "Convert KeyPair success"});
+ })
+}
+```
+
## 非对称密钥对象根据参数生成与获取参数
### 场景说明
@@ -884,7 +971,7 @@ function stringToUint8Array(str) {
}
// 以Promise方式加密
-function encryptMessageProMise() {
+function encryptMessagePromise() {
// 生成非对称密钥生成器
let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
// 生成加解密生成器
@@ -927,7 +1014,7 @@ function encryptMessageCallback() {
}
// 以Promise方式加解密
-function decryptMessageProMise() {
+function decryptMessagePromise() {
// 生成非对称密钥生成器
let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
// 生成加解密生成器,用于加密
@@ -1211,6 +1298,220 @@ function rsaUseSpecDecryptOAEPPromise() {
}
```
+### SM2加解密开发步骤
+
+示例7:使用SM2非对称密钥的加解密操作
+
+1. 生成SM2密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成SM2非对称密钥。
+2. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式。
+3. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文。
+
+```js
+import cryptoFramework from "@ohos.security.cryptoFramework"
+
+let plan = "This is cipher test.";
+
+// 可理解的字符串转成字节流
+function stringToUint8Array(str) {
+ let arr = [];
+ for (let i = 0, j = str.length; i < j; ++i) {
+ arr.push(str.charCodeAt(i));
+ }
+ return new Uint8Array(arr);
+}
+
+// 以Promise方式加密
+function encryptMessagePromise() {
+ // 生成非对称密钥生成器
+ let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
+ // 生成加解密生成器
+ let cipher = cryptoFramework.createCipher("SM2_256|SM3");
+ // 通过非对称秘钥生成器生成非对称密钥对
+ let keyGenPromise = sm2Generator.generateKeyPair();
+ keyGenPromise.then(sm2KeyPair => {
+ let pubKey = sm2KeyPair.pubKey;
+ // 初始化加解密操作环境:使用公钥开始加密
+ return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null);
+ }).then(() => {
+ // doFinal
+ let input = { data : stringToUint8Array(plan) };
+ return cipher.doFinal(input);
+ }).then(dataBlob => {
+ // 获取加密后的信息
+ console.info("EncryptOutPut is " + dataBlob.data);
+ });
+}
+
+// 以Callback方式加密
+function encryptMessageCallback() {
+ // 生成非对称密钥生成器
+ let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
+ // 生成加解密生成器
+ let cipher = cryptoFramework.createCipher("SM2_256|SM3");
+ // 通过非对称秘钥生成器生成非对称密钥对
+ sm2Generator.generateKeyPair(function (err, keyPair) {
+ let pubKey = keyPair.pubKey;
+ // 初始化加解密操作环境:使用公钥开始加密
+ cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, function (err, data) {
+ let input = {data : stringToUint8Array(plan) };
+ // doFinal
+ cipher.doFinal(input, function (err, data) {
+ // 获取加密后的信息
+ console.info("EncryptOutPut is " + data.data);
+ })
+ })
+ })
+}
+
+// 以Promise方式加解密
+function decryptMessagePromise() {
+ // 生成非对称密钥生成器
+ let rsaGenerator = cryptoFramework.createAsyKeyGenerator("SM2_256");
+ // 生成加解密生成器,用于加密
+ let cipher = cryptoFramework.createCipher("SM2_256|SM3");
+ // 生成加解密生成器,用于解密
+ let decoder = cryptoFramework.createCipher("SM2_256|SM3");
+ // 通过非对称秘钥生成器生成非对称密钥对
+ let keyGenPromise = rsaGenerator.generateKeyPair();
+ let keyPair;
+ let cipherDataBlob;
+ let input = { data : stringToUint8Array(plan) };
+ keyGenPromise.then(rsaKeyPair => {
+ keyPair = rsaKeyPair;
+ // 初始化加解密操作环境:使用公钥开始加密
+ return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null);
+ }).then(() => {
+ // 加密doFinal
+ return cipher.doFinal(input);
+ }).then(dataBlob => {
+ // 获取加密后的信息,并用于解密的入参
+ console.info("EncryptOutPut is " + dataBlob.data);
+ AlertDialog.show({message : "output" + dataBlob.data});
+ cipherDataBlob = dataBlob;
+ // 初始化加解密操作环境:使用私钥开始解密
+ return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null);
+ }).then(() => {
+ // 解密doFinal
+ return decoder.doFinal(cipherDataBlob);
+ }).then(decodeData => {
+ // 验证解密后,数据与原先数据是否保持一致
+ if (decodeData.data.toString() === input.data.toString()) {
+ AlertDialog.show({message : "decrypt success"});
+ return;
+ }
+ AlertDialog.show({message : "decrypt fail"});
+ });
+}
+
+// 以Callback方式加解密
+function decryptMessageCallback() {
+ // 生成非对称密钥生成器
+ let rsaGenerator = cryptoFramework.createAsyKeyGenerator("SM2_256");
+ // 生成加解密生成器,用于加密
+ let cipher = cryptoFramework.createCipher("SM2_256|SM3");
+ // 生成加解密生成器,用于解密
+ let decoder = cryptoFramework.createCipher("SM2_256|SM3");
+ let plainText = "this is cipher text";
+ let input = {data : stringToUint8Array(plainText) };
+ let cipherData;
+ let keyPair;
+ // 通过非对称秘钥生成器生成非对称密钥对
+ rsaGenerator.generateKeyPair(function (err, newKeyPair) {
+ keyPair = newKeyPair;
+ // 初始化加解密操作环境:使用公钥开始加密
+ cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, function (err, data) {
+ // 加密doFinal
+ cipher.doFinal(input, function (err, data) {
+ // 获取加密后的信息,并用于解密的入参
+ AlertDialog.show({ message : "EncryptOutPut is " + data.data} );
+ cipherData = data;
+ // 初始化加解密操作环境:使用私钥开始解密
+ decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, function (err, data) {
+ // 解密doFinal
+ decoder.doFinal(cipherData, function (err, data) {
+ // 验证解密后,数据与原先数据是否保持一致
+ if (input.data.toString() === data.data.toString()) {
+ AlertDialog.show({ message : "decrype success"} );
+ return;
+ }
+ AlertDialog.show({ message : "decrype fail"} );
+ });
+ });
+ });
+ });
+ });
+}
+```
+
+### SM4 ECB以callback方式加解密开发步骤:
+
+示例8:使用SM4对称密钥的加解密操作
+
+1. 创建对称密钥生成器。
+2. 通过已有二进制数据生成密钥。
+3. 创建加解密生成器。
+4. 通过加解密生成器加密或解密数据。
+
+```js
+import cryptoFramework from '@ohos.security.cryptoFramework';
+
+function stringToUint8Array(str) {
+ let arr = [];
+ for (let i = 0, j = str.length; i < j; ++i) {
+ arr.push(str.charCodeAt(i));
+ }
+ return new Uint8Array(arr);
+}
+
+// 字节流转成可理解的字符串
+function uint8ArrayToString(array) {
+ let arrayString = '';
+ for (let i = 0; i < array.length; i++) {
+ arrayString += String.fromCharCode(array[i]);
+ }
+ return arrayString;
+}
+
+// SM4 ECB模式示例,callback写法
+function testSM4Ecb() {
+ // 生成非对称密钥生成器
+ let rsaGenerator = cryptoFramework.createSymKeyGenerator('SM4_128');
+ // 生成加解密生成器,用于加密
+ let cipher = cryptoFramework.createCipher("SM4_128|ECB|PKCS7");
+ // 生成加解密生成器,用于解密
+ let decoder = cryptoFramework.createCipher("SM4_128|ECB|PKCS7");
+ let plainText = "this is cipher text";
+ let input = {data : stringToUint8Array(plainText) };
+ let cipherData;
+ let key;
+ // 通过非对称秘钥生成器生成非对称密钥对
+ rsaGenerator.generateSymKey(function (err, newKey) {
+ key = newKey;
+ // 初始化加解密操作环境:使用公钥开始加密
+ cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, key, null, function (err, data) {
+ // 加密doFinal
+ cipher.doFinal(input, function (err, data) {
+ // 获取加密后的信息,并用于解密的入参
+ AlertDialog.show({ message : "EncryptOutPut is " + data.data} );
+ cipherData = data;
+ // 初始化加解密操作环境:使用私钥开始解密
+ decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, key, null, function (err, data) {
+ // 解密doFinal
+ decoder.doFinal(cipherData, function (err, data) {
+ // 验证解密后,数据与原先数据是否保持一致
+ if (input.data.toString() === data.data.toString()) {
+ AlertDialog.show({ message : "decrype success"} );
+ return;
+ }
+ AlertDialog.show({ message : "decrype fail"} );
+ });
+ });
+ });
+ });
+ });
+}
+```
+
## 使用签名验签操作
### 场景说明
@@ -1219,6 +1520,7 @@ function rsaUseSpecDecryptOAEPPromise() {
1. 使用RSA签名验签操作
2. 使用ECC签名验签操作
3. 使用RSA签名验签,PSS模式时,获取、设置SignSpecItem参数。
+4. 使用SM2签名验签操作
> **说明:**
>
@@ -1600,6 +1902,63 @@ function verifyMessageCallbackPSS() {
}
```
+### SM2签名验签开发步骤
+
+示例5:使用SM2操作
+
+1. 生成SM2密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成SM2非对称密钥。
+2. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。
+3. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用doFinal接口生成数据的签名。
+4. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。
+5. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用doFinal接口传入签名进行验签。
+
+```js
+import cryptoFramework from "@ohos.security.cryptoFramework"
+
+// 可理解的字符串转成字节流
+function stringToUint8Array(str) {
+ var arr = [];
+ for (var i = 0, j = str.length; i < j; ++i) {
+ arr.push(str.charCodeAt(i));
+ }
+ var tmpArray = new Uint8Array(arr);
+ return tmpArray;
+}
+
+let globalKeyPair;
+let SignMessageBlob;
+let plan1 = "This is Sign test plan1";
+let plan2 = "This is Sign test plan2";
+let input1 = { data: stringToUint8Array(plan1) };
+let input2 = { data: stringToUint8Array(plan2) };
+
+function signAndVerify() {
+ let rsaGenerator = cryptoFramework.createAsyKeyGenerator("SM2_256");
+ let signer = cryptoFramework.createSign("SM2_256|SM3");
+ rsaGenerator.generateKeyPair(function (err, keyPair) {
+ globalKeyPair = keyPair;
+ let priKey = globalKeyPair.priKey;
+ signer.init(priKey, function (err, data) {
+ signer.update(input1, function (err, data) {
+ signer.sign(input2, function (err, data) {
+ SignMessageBlob = data;
+ console.info("sign output is " + SignMessageBlob.data);
+ let verifyer = cryptoFramework.createVerify("SM2_256|SM3");
+ verifyer.init(globalKeyPair.pubKey, function (err, data) {
+ verifyer.update(input1, function (err, data) {
+ verifyer.verify(input2, SignMessageBlob, function (err, data) {
+ console.info("verify result is " + data);
+ AlertDialog.show({message:"decrype success"})
+ });
+ });
+ })
+ });
+ });
+ });
+ });
+}
+```
+
## 使用密钥协商操作
### 场景说明
diff --git a/zh-cn/application-dev/security/cryptoFramework-overview.md b/zh-cn/application-dev/security/cryptoFramework-overview.md
index d705b3244a..2c8dc02a48 100644
--- a/zh-cn/application-dev/security/cryptoFramework-overview.md
+++ b/zh-cn/application-dev/security/cryptoFramework-overview.md
@@ -23,6 +23,10 @@
3DES,也称为 3DESede 或 TripleDES,是三重数据加密算法,相当于是对每个数据块应用三次DES的对称加密算法,它使用3个64位的密钥对数据块进行三次加密。相比DES,3DES因密钥长度变长,安全性有所提高,但其处理速度不高。因此又出现了AES加密算法,AES较于3DES速度更快、安全性更高。
+- **SM4密钥**
+
+ SM4密码算法是一个分组算法,该算法的分组长度为128位,密钥的长度为128位。加密算法与密钥扩展算法都采用32轮非线性迭代结构,数据解密和数据加密的算法结构相同,只是轮密钥的使用顺序相反,解密轮密钥是加密轮密钥的逆序。
+
### 非对称密钥
非对称密钥使用公钥和私钥两个密钥来进行算法操作,公钥对外公开,私钥对外保密。对于加解密操作,一般使用公钥对明文进行加密形成密文,持有私钥的人即可对密文解密形成明文。对于签名验签操作,使用私钥对明文进行签名,公钥持有者可以通过公钥对签名数据做验签,验证数据是否被篡改。
@@ -77,6 +81,26 @@
pk:公钥,pk = (g ^ sk) mod p。
+- **SM2密钥**
+
+ SM2算法是一种基于椭圆曲线的公钥密码算法,其密钥长度为256位。SM2算法采用的是Fp域上的椭圆曲线。
+
+ Fp域下的SM2密钥参数,包括:
+
+ p: 大于3的素数,用于确定Fp。
+
+ a, b: 定义椭圆曲线的方程。
+
+ g: 椭圆曲线的一个基点(base point),可由gx,gy表示。
+
+ n: 基点g的阶(order)。
+
+ h: 余因子(cofactor)。
+
+ sk: 私钥,是一个随机整数,小于n。
+
+ pk: 公钥,是椭圆曲线上的一个点, pk = sk * g。
+
### 加解密
- **对称AES加解密**
@@ -105,6 +129,19 @@
> ECB、CBC加密模式,明文长度不是64位整数倍,必须使用填充方法补足。
> 由于需要填充至分组大小,所以实际算法库中的PKCS5和PKCS7都是以分组大小作为填充长度的,即3DES加密填充至8字节。
+- **对称SM4加解密**
+
+ 算法库目前提供了SM4加解密常用的6种加密模式:ECB、CBC、CTR、OFB、CFB和CFB128。SM4为分组加密算法,分组长度大小为128位。实际应用中明文最后一组可能不足128位,不足数据可以使用各种padding模式做数据填充。下文中描述了各个padding的区别:
+
+ - NoPadding:不带填充。
+ - PKCS5:填充字符由一个字节序列组成,每个字节填充该填充字节序列的长度,规定是8字节填充。
+ - PKCS7:填充字符和PKCS5填充方法一致,但是可以在1-255字节之间任意填充。
+
+ > **说明:**
+ >
+ > ECB、CBC加密模式,明文长度不是128位整数倍,必须使用填充方法补足。
+ > 由于需要填充至分组大小,所以实际算法库中的PKCS5和PKCS7都是以分组大小作为填充长度的,即SM4加密填充至16字节。
+
- **非对称RSA加解密**
RSA为块加密算法,加密长度需要在固定长度进行,实际应用中会使用各种padding模式做数据填充。算法库目前提供了RSA加解密常用的三种模式:NoPadding、PKCS1和PKCS1_OAEP。下文中描述了各个padding的区别:
@@ -121,6 +158,11 @@
>
> RSA钥模 = (RSA的bits + 7) / 8
+ - **非对称SM2加解密**
+
+ SM2为块加密算法,加密长度需要在固定长度进行。OpenSSL中SM2算法加解密时使用零填充模式,如果数据长度不足32字节,则需要进行填充,填充的方式是在数据后面添加若干个0x00字节,直到数据长度达到32字节为止。
+ SM2加密过程中,首先需要生成一个随机数k,并使用公钥对kG进行加密,得到C1。然后,将明文数据进行SM3摘要计算,得到摘要值,并将摘要值与C1进行拼接,得到C3。接着,使用k和摘要值作为参数,对明文数据进行加密,得到C2。最后,将C1、C3、C2按顺序拼接起来,得到最终的加密结果。通过加入摘要值,增强了加密结果的安全性,同时也方便了解密过程中的验证。
+
### 签名验签
- **RSA签名验签**
@@ -155,15 +197,16 @@
### 摘要
-消息摘要MD算法是一种能将任意长度的输入消息,通过哈希算法生成长度固定的摘要的算法。消息摘要算法通过其不可逆的特性能被用于敏感信息的加密。消息摘要算法也被称为哈希算法或单向散列算法。
+消息摘要算法是一种能将任意长度的输入消息,通过哈希算法生成长度固定的摘要的算法。消息摘要算法通过其不可逆的特性能被用于敏感信息的加密。消息摘要算法也被称为哈希算法或单向散列算法。
在摘要算法相同时,生成的摘要值主要有下列特点:
- 当输入消息相同时,生成摘要序列相同。
- 当输入消息的长度不一致时,生成摘要序列长度固定(摘要长度由算法决定)。
- 当输入消息不一致时,生成摘要序列几乎不会相同(依然存在相同概率,由摘要长度决定相同概率)。
-消息摘要算法主要分为三类:MD,SHA与MAC(详见HMAC章节)。
-MD算法包括MD2,MD4和MD5。
+消息摘要算法主要分为两类:SHA和SM3。
+SM3包括MD和MAC(详见HMAC章节)。
+SM3中MD算法包括MD2,MD4和MD5。
SHA算法主要包括SHA1,SHA224,SHA256,SHA384,SHA512。
### 消息验证码
@@ -350,6 +393,39 @@ HMAC(Hash-based Message Authentication Code)是一种基于密钥的消息
> 1. DSA不支持通过指定私钥参数(p, q, g, sk)来生成私钥。
> 2. 当使用公共参数(p, q, g)来生成DSA密钥对时,DSA密钥长度至少需要1024位。
+
+### SM2密钥生成规格
+
+> **说明:**
+>
+> 从API version 10开始, 支持使用密钥参数来生成SM2密钥.
+
+- 支持以字符串参数来生成SM2密钥,其生成参数如下表所示:
+
+ |非对称密钥算法|密钥长度(bit)|字符串参数|
+ |---|---|---|
+ |SM2|256|SM2_256|
+
+ > **说明:**
+ >
+ > “字符串参数”是“非对称密钥算法”和“密钥长度”使用连接符号“_”拼接而成,用于在创建非对称密钥生成器时,指定密钥规格。
+
+### SM4密钥生成规格
+
+> **说明:**
+>
+> 从API version 10开始, 支持使用密钥参数来生成SM4密钥.
+
+- 支持以字符串参数来生成SM4密钥,其生成参数如下表所示:
+
+ |对称密钥算法|密钥长度(bit)|字符串参数|
+ |---|---|---|
+ |SM4|128|SM4_128|
+
+ > **说明:**
+ >
+ > “字符串参数”是“对称密钥算法”和“密钥长度”使用连接符号“_”拼接而成,用于在创建对称密钥生成器时,指定密钥规格。
+
## 加解密规格
### 对称加解密
@@ -372,11 +448,18 @@ HMAC(Hash-based Message Authentication Code)是一种基于密钥的消息
|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]|
+ |SM4|ECB|SM4_128\|ECB\|[NoPadding\|PKCS5\|PKCS7]|
+ |SM4|CBC|SM4_128\|CBC\|[NoPadding\|PKCS5\|PKCS7]|
+ |SM4|CTR|SM4_128\|CTR\|[NoPadding\|PKCS5\|PKCS7]|
+ |SM4|OFB|SM4_128\|OFB\|[NoPadding\|PKCS5\|PKCS7]|
+ |SM4|CFB|SM4_128\|CFB\|[NoPadding\|PKCS5\|PKCS7]|
+ |SM4|CFB128|SM4_128\|CFB128\|[NoPadding\|PKCS5\|PKCS7]|
> **说明:**
>
> 1. []中只能任选一项。
> 2. “字符串参数”是“对称加解密算法(含密钥长度)”、“分组模式”、“填充模式”拼接而成,用于在创建对称加解密实例时,指定对称加解密算法规格。
+ > 3. “字符串参数”中“SM4”和密钥长度间需要添加下划线
### 非对称RSA加解密
@@ -488,6 +571,24 @@ RSA加解密时,涉及三种填充模式:NoPadding, PKCS1和PKCS1_OAEP。
>
> 上表说明了算法库对于OAEP参数的获取和设置支持情况,打√的表示需要对该参数具有获取或设置的能力。
+
+### 非对称SM2加解密
+
+> **说明:**
+>
+> 从API version 10开始, 支持非对称SM2加解密不带密钥长度的规格。
+
+SM2加解密时,仅支持C1C3C2密文排列组合模式。SM2非对称加密的结果由C1,C2,C3三部分组成。其中C1是根据生成的随机数计算出的椭圆曲线点,C2是密文数据,C3是通过指定摘要算法计算的值。国密新标准以C1,C3,C2顺序存放,不支持无摘要加密。
+- 支持的加密算法:
+
+ | 非对称密钥类型 | 摘要 | 字符串参数 |
+ |---|---|---|
+ |SM2_256|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512\|SM3]|SM2_256\|[MD5\|SHA1\|SHA224\|SHA256\|SHA384\|SHA512\|SM3]|
+
+ > **说明:**
+ >
+ > “字符串参数”是“非对称密钥类型”、“填充模式”拼接而成,用于在创建非对称加解密实例时,指定非对称加解密算法规格。
+
## 签名验签规格
### RSA签名验签
@@ -628,6 +729,26 @@ RSA签名验签时,涉及两种填充模式:PKCS1和PSS。
> 例如:"DSA1024|SHA256"
> 3. 在上表最后一行,为了兼容由密钥参数生成的密钥,DSA签名验签参数输入密钥类型时支持不带长度,签名验签运算取决于实际输入的密钥长度。
+
+### SM2签名验签
+
+> **说明:**
+>
+> 从API version 10开始, 支持SM2签名验签规格。
+
+- 支持的SM2参数:
+
+ |非对称密钥类型|摘要|字符串参数|
+ |---|---|---|
+ |SM2_256|SM3|SM2_256\|SM3|
+ |SM2|SM3|SM2\|SM3|
+
+ > **说明:**
+ >
+ > 1. []内的参数只能任选一项,非[]内的为固定值。
+ > 2. 使用时请从表格中选择非对称密钥类型、摘要二个数据,用|拼接成“字符串参数”,用于在创建非对称签名验签实例时,指定非对称签名验签算法规格。
+ > SM2签名时只支持SM3摘要。
+
## 密钥协商规格
### ECDH
@@ -664,6 +785,7 @@ RSA签名验签时,涉及两种填充模式:PKCS1和PSS。
|HASH|SHA384|
|HASH|SHA512|
|HASH|MD5|
+ |HASH|SM3|
> **说明:**
>
@@ -680,6 +802,7 @@ RSA签名验签时,涉及两种填充模式:PKCS1和PSS。
|HASH|SHA256|
|HASH|SHA384|
|HASH|SHA512|
+ |HASH|SM3|
> **说明:**
>
--
GitLab