From fefb280170e626b029ef72dd79f25a4307f15869 Mon Sep 17 00:00:00 2001 From: Sun Yimin Date: Wed, 13 Dec 2023 08:02:22 +0800 Subject: [PATCH] =?UTF-8?q?doc:=20=E9=87=8D=E6=96=B0=E7=BC=96=E6=8E=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/sm2.md | 22 ++++++++++++---------- docs/sm3.md | 9 +++++---- docs/sm4.md | 24 +++++++++++++----------- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/docs/sm2.md b/docs/sm2.md index 2c98e17c..a4a9af15 100644 --- a/docs/sm2.md +++ b/docs/sm2.md @@ -1,4 +1,6 @@ -# 参考标准 +# SM2椭圆曲线公钥密码算法应用指南 + +## 参考标准 * 《GB/T 32918.1-2016 信息安全技术 SM2椭圆曲线公钥密码算法 第1部分:总则》 * 《GB/T 32918.2-2016 信息安全技术 SM2椭圆曲线公钥密码算法 第2部分:数字签名算法》 * 《GB/T 32918.3-2016 信息安全技术 SM2椭圆曲线公钥密码算法 第3部分:密钥交换协议》 @@ -8,7 +10,7 @@ 您可以从[国家标准全文公开系统](https://openstd.samr.gov.cn/)在线阅读这些标准。 -# 概述 +## 概述 既然是椭圆曲线公钥密码算法,它就和NIST P系列椭圆曲线公钥密码算法类似,特别是P-256。NIST P 系列椭圆曲线公钥密码算法主要用于数字签名和密钥交换,NIST没有定义基于椭圆曲线的公钥加密算法标准,[SEC 1: Elliptic Curve Cryptography](https://www.secg.org/sec1-v2.pdf)第五章定义了“Elliptic Curve Integrated Encryption Scheme (ECIES)”,不过应用不广。感兴趣的同学可以进一步对比一下: | SM2 | SEC 1 | @@ -17,10 +19,10 @@ | 密钥交换协议 | ECMQV | | 公钥加密算法 | ECIES | -# SM2公私钥对 +## SM2公私钥对 SM2公私钥对的话,要么是自己产生,要么是别的系统产生后通过某种方式传输给您的。 -## SM2公私钥对的生成 +### SM2公私钥对的生成 您可以通过调用```sm2.GenerateKey```方法产生SM2公私钥对,SM2的私钥通过组合方式扩展了```ecdsa.PrivateKey```,用于定义一些SM2特定的方法: ```go // PrivateKey represents an ECDSA SM2 private key. @@ -31,7 +33,7 @@ type PrivateKey struct { ``` SM2的公钥类型沿用了```ecdsa.PublicKey```结构。 -## SM2公钥的解析、构造 +### SM2公钥的解析、构造 通常情况下,公钥是通过PEM编码的文本传输的,您可以通过两步获得公钥: * 获得PEM中的block * 解析block中的公钥 @@ -57,7 +59,7 @@ func getPublicKey(pemContent []byte) (any, error) { ``` 当然,您也可以使用ecdh包下的方法```ecdh.P256().NewPublicKey```来构造,目前只支持非压缩方式。 -## SM2私钥的解析、构造 +### SM2私钥的解析、构造 私钥的封装格式主要有以下几种,[相关讨论](https://github.com/emmansun/gmsm/issues/104): * RFC 5915 / SEC1 - http://www.secg.org/sec1-v2.pdf * PKCS#12 @@ -89,7 +91,7 @@ func getPublicKey(pemContent []byte) (any, error) { ``` 当然,你也可以使用ecdh包的方法```ecdh.P256().NewPrivateKey```来构造私钥,您要确保输入的字节数组是256位(16字节)的,如果不是,请先自行处理。 -# 数字签名算法 +## 数字签名算法 您可以直接使用sm2私钥的签名方法```Sign```: ```go // This is a reference method to force SM2 standard with SDK [crypto.Signer]. @@ -138,10 +140,10 @@ func ExampleVerifyASN1WithSM2() { } ``` -# 密钥交换协议 +## 密钥交换协议 这里有两个实现,一个是传统实现,位于sm2包中;另外一个参考最新go语言的实现在ecdh包中。在这里不详细介绍使用方法,一般只有tls/tlcp才会用到,普通应用通常不会涉及这一块,感兴趣的话可以参考github.com/Trisia/gotlcp中的应用。 -# 公钥加密算法 +## 公钥加密算法 请牢记,非对称加密算法通常不用于加密大量数据,而是用来加密对称加密密钥,我们在tlcp以及信封加密机制中能找到这种用法。 SM2公钥加密算法支持的密文编码格式有两种: @@ -204,7 +206,7 @@ func ExamplePrivateKey_Decrypt() { 具体API文档请参考:[API Document](https://godoc.org/github.com/emmansun/gmsm) -# 与KMS集成 +## 与KMS集成 国内云服务商的KMS服务大都提供SM2密钥,我们一般调用其API进行签名和解密,而验签和加密操作,一般在本地用公钥即可完成。不过需要注意的是,KMS提供的签名通常需要您在本地进行hash操作,而sm2签名的hash又比较特殊,下面示例供参考(将在下个发布版本**v0.24.0**中公开此函数```sm2.CalculateSM2Hash```): ```go func calculateSM2Hash(pub *ecdsa.PublicKey, data, uid []byte) ([]byte, error) { diff --git a/docs/sm3.md b/docs/sm3.md index b41c6759..3a11f855 100644 --- a/docs/sm3.md +++ b/docs/sm3.md @@ -1,12 +1,13 @@ -# 参考标准 +# SM3密码杂凑算法 +## 参考标准 * 《GB/T 32905-2016 信息安全技术 SM3密码杂凑算法》 您可以从[国家标准全文公开系统](https://openstd.samr.gov.cn/)在线阅读此标准。 -# 概述 +## 概述 SM3密码杂凑算法,或者叫SM3哈希算法,它是一个输出结果为256位(32字节)的哈希算法。在本软件库中,SM3的实现(方法签名)与Go语言中的哈希算法,特别是SHA256保持一致,所以用法也是一样的。具体API文档,包括Example,请参考:[API Document](https://godoc.org/github.com/emmansun/gmsm)。 -# 常用用法示例 +## 常用用法示例 ```go // 直接使用sm3.Sum方法 func ExampleSum() { @@ -40,6 +41,6 @@ func ExampleNew_file() { } ``` -# 性能 +## 性能 请参考[SM3密码杂凑算法性能优化](https://github.com/emmansun/gmsm/wiki/SM3%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96)。 diff --git a/docs/sm4.md b/docs/sm4.md index d28dff17..fbb08b7c 100644 --- a/docs/sm4.md +++ b/docs/sm4.md @@ -1,13 +1,14 @@ -# 参考标准 +# SM4分组密码算法应用指南 +## 参考标准 * 《GB/T 32907-2016 信息安全技术 SM4分组密码算法》 * 《GB/T 17964-2021 信息安全技术 分组密码算法的工作模式》 您可以从[国家标准全文公开系统](https://openstd.samr.gov.cn/)在线阅读这些标准。 -# 概述 +## 概述 SM4分组密码算法,其地位类似NIST中的AES分组密码算法,密钥长度128位(16字节),分组大小也是128位(16字节)。在本软件库中,SM4的实现与Go语言中的AES实现一致,也实现了```cipher.Block```接口,所以,所有Go语言中实现的工作模式(CBC/GCM/CFB/OFB/CTR),都能与SM4组合使用。 -# [工作模式](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation) +## [工作模式](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation) Go语言实现的工作模式,主要有三类: * 基于分组的工作模式 ```cipher.BlockMode```,譬如CBC。 * 带有关联数据的认证加密工作模式```cipher.AEAD```,譬如GCM。 @@ -28,10 +29,11 @@ Go语言实现的工作模式,主要有三类: 目前,本软件库的SM4针对ECB/CBC/GCM/XTS工作模式进行了绑定组合性能优化,暂时没有计划使用汇编优化HCTR模式(HCTR模式可以采用和GCM类似的方法进行汇编优化)。 -**使用建议**:常用的对称加解密应用场合,推荐优先使用GCM模式,其次CBC模式(一些安全扫描工具,也会把CBC工作模式列为安全性不高的工作模式)。我能想到的GCM模式的缺点是:加解密的相关方不支持GCM模式,或者实现性能不好。 +### 使用建议 +常用的对称加解密应用场合,推荐优先使用GCM模式,其次CBC模式(一些安全扫描工具,也会把CBC工作模式列为安全性不高的工作模式)。我能想到的GCM模式的缺点是:加解密的相关方不支持GCM模式,或者实现性能不好。 -# 填充(padding) +## 填充(padding) 有些分组密码算法的工作模式(譬如实现了```cipher.BlockMode```接口的模式)的输入要求是其长度必须是分组大小的整数倍。《GB/T 17964-2021 信息安全技术 分组密码算法的工作模式》附录C中列出了以下几种填充模式: * 填充方式 1,对应本软件库的```padding.NewPKCS7Padding``` * 填充方式 2,对应本软件库的```padding.NewISO9797M2Padding``` @@ -41,7 +43,7 @@ Go语言实现的工作模式,主要有三类: 您如果使用实现了```cipher.BlockMode```接口的分组加密工作模式,那您也必须与相关方协调好填充模式。JAVA库的对称加密算法字符串名就包含了所有信息,譬如**AES/CBC/PKCS7Padding**。 -# 密文及其相关参数的传输和存储 +## 密文及其相关参数的传输和存储 如果是自描述的,那肯定有相关标准,定义相关ASN.1结构,并且给分组密码算法、工作模式、填充方式都赋予一个OID。 如果是内部服务之间,可能是在应用/服务级别自定义所使用分组密码算法、工作模式、填充方式的标识,作为应用的METADATA,也就是加密用的METADATA和密文分离。 @@ -56,10 +58,10 @@ Go语言实现的工作模式,主要有三类: 至于要将二进制转为文本传输、存储,编个码就行:标准base64 / URL base64 / HEX,事先协调、定义好就可以了。这里顺便推荐一下[性能更好的BASE64实现](https://github.com/emmansun/base64)。 -# API文档及示例 +## API文档及示例 这里只列出GCM/CBC的例子,其余请参考[API Document](https://godoc.org/github.com/emmansun/gmsm)。 -## GCM示例 +### GCM示例 ```go func Example_encryptGCM() { // Load your secret key from a safe place and reuse it across multiple @@ -120,7 +122,7 @@ func Example_decryptGCM() { } ``` -## CBC示例 +### CBC示例 ```go func Example_encryptCBC() { // Load your secret key from a safe place and reuse it across multiple @@ -192,7 +194,7 @@ func Example_decryptCBC() { // Output: sm4 exampleplaintext } ``` -# 性能 +## 性能 SM4分组密码算法的软件高效实现,不算CPU指令支持的话,已知有如下几种方法: * S盒和L转换预计算 * SIMD并行处理:并行查表 @@ -201,7 +203,7 @@ SM4分组密码算法的软件高效实现,不算CPU指令支持的话,已 当然,这些与有CPU指令支持的AES算法相比,性能差距依然偏大,要是工作模式不支持并行,差距就更巨大了。 -# 与KMS集成 +## 与KMS集成 可能您会说,如果我在KMS中创建了一个SM4对称密钥,就不需要本地加解密了,这话很对,不过有种场景会用到: * 在KMS中只创建非对称密钥(KEK); * 对称加解密在本地进行;