From 3abd065fb15b89c657d31ac3a12f3b41d82788a5 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Thu, 12 May 2016 17:08:38 +0200 Subject: [PATCH] =?UTF-8?q?Updated=20SM2=E6=95=B0=E5=AD=97=E7=AD=BE?= =?UTF-8?q?=E5=90=8D=20(markdown)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SM2数字签名.md | 81 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/SM2数字签名.md b/SM2数字签名.md index fb103a0..5ae03a2 100644 --- a/SM2数字签名.md +++ b/SM2数字签名.md @@ -1,7 +1,86 @@ -SM2数字签名是国密数字签名标准, +## SM2数字签名 SM2数字签名方案中被签名的杂凑值不仅仅是消息的杂凑值,而是签名者身份信息串联上消息的杂凑值,其中签名者身份信息是签名者的可辨别标识字串、椭圆曲线方程系数、生成元和签名者公钥串联后字串的杂凑值。SM2标准中并未说明签名者的可辨别标识字串格式及获得方式,应用可以采用X.509证书中的Subject字段、CN (CommonName)或自行规定。 ### SM2参数选择 SM2标准中规定采用256比特的椭圆曲线域参数,并采用256比特的密码杂凑算法,并规定某些步骤中须采用SM3。GmSSL的实现支持灵活的参数设定,并支持内置的所有密码杂凑算法,因此应用可以选择安全程度更高的椭圆曲线域参数和密码杂凑算法,如521比特的域参数和SHA-512算法。 + + +## SM2公钥加密 + +SM2公钥加密算法国密公钥加密标准之一,由国家密码管理局与2010年12月公布。SM2公钥加密是一种椭圆曲线公钥加密方案,具体规范可参考《SM2椭圆曲线公钥密码算法 第4部分:公钥加密算法》文本。 + +SM2公钥加密适用于加密长度较短的数据,如会话密钥和消息报文。SM2公钥加密不仅对数据加密,还提供防篡改的特性,即被篡改的或伪造的密文可以在解密的过程中被检查发现,因此通过SM2公钥加密的消息无需格外的校验机制。消息经过SM2公钥加密后长度会增加不到100字节的长度,加密方在准备缓冲区时需要加以留意。 + +GmSSL提供了SM2公钥加密的实现。应用应优先通过EVP API调用SM2公钥加密的功能,具体接口使用方法请参考手册页中的`EVP_PKEY_encrypt(3)`、`EVP_PKEY_decrypt(3)`等相关函数。 + +下面给出通过EVP API调用SM2公钥加密的例子: + +``` c +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + EC_KEY *ec_key = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + char *msg = "Hello world!"; + unsigned char ptbuf[256]; + unsigned char ctbuf[256]; + size_t ptlen, ctlen, i; + + /* 生成 SM2 EVP_PKEY 对象 */ + ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1); + pkey = EVP_PKEY_new(); + EC_KEY_generate_key(ec_key); + EVP_PKEY_set1_SM2(pkey, ec_key); + + ctx = EVP_PKEY_CTX_new(pkey, NULL); + + /* 加密 */ + EVP_PKEY_encrypt_init(ctx); + ctlen = sizeof(ctbuf); + bzero(ctbuf, ctlen); + EVP_PKEY_encrypt(ctx, ctbuf, &ctlen, (unsigned char *)msg, strlen(msg) + 1); + + printf("encrypted message (%zu bytes) : ", ctlen); + for (i = 0; i < ctlen; i++) { + printf("%02x", ctbuf[i]); + } + printf("\n"); + + /* 解密 */ + EVP_PKEY_decrypt_init(ctx); + ptlen = sizeof(ptbuf); + bzero(ptbuf, ptlen); + if (!EVP_PKEY_decrypt(ctx, ptbuf, &ptlen, ctbuf, ctlen)) { + fprintf(stderr, "sm2 decrypt failed.\n"); + } + + printf("decrypted message : %s\n", ptbuf); + + EVP_PKEY_free(pkey); + EC_KEY_free(ec_key); + EVP_PKEY_CTX_free(ctx); + return 0; +} +``` + +### 密文编码问题 + +SM2密文由C1、C2、C3三部分构成,如何对SM2密文进行编码在已经公布的两个标准中有所不同,在早期公布的《SM2椭圆曲线公钥密码算法 第4部分:公钥加密算法》中,SM2密文中的三部分依次输出,没有采用如Tag-Length-Value形式的编码,我们称其为Plain编码。在之后公布的GM/T国标中,SM2密文采用ASN.1/DER方式编码。 + +GmSSL通过`SM2_CIPHERTEXT_VALUE`对象来表示密文数据结构,函数`SM2_do_encrypt()`和`SM2_do_decrypt()`可以生成`SM2_CIPHERTEXT_VALUE`对象及对其解密,函数`SM2_CIPHERTEXT_VALUE_encode()`和`SM2_CIPHERTEXT_VALUE_decode()`实现该对象的Plain编解码。GmSSL预计还会通过函数`i2d_SM2_CIPHERTEXT_VALUE()`和`d2i_SM2_CIPHERTEXT_VALUE()`实现该密文对象的ASN.1/DER编解码,以支持最新的GM/T国密标准。 + +GmSSL的`SM2_encrypt()`和`SM2_decrypt()`在加解密的同时也完成`SM2_CIPHERTEXT_VALUE`对象的编解码。目前采用Plain编解码,在相应功能完成后会替换为ASN.1/DER编码方案。 + +## SM2密钥交换 + + +