doc: sm3/sm4应用指南

This commit is contained in:
Sun Yimin 2023-12-12 11:51:34 +08:00 committed by GitHub
parent 880691746d
commit 97ddcab4b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 113 additions and 1 deletions

View File

@ -40,6 +40,8 @@
## 文档
* [SM2椭圆曲线公钥密码算法应用指南](./docs/sm2.md)
* [SM3密码杂凑算法应用指南](./docs/sm3.md)
* [SM4分组密码算法应用指南](./docs/sm4.md)
## 相关项目
* **[Trisia/TLCP](https://github.com/Trisia/gotlcp)** - 一个《GB/T 38636-2020 信息安全技术 传输层密码协议》Go语言实现项目。

View File

@ -75,7 +75,7 @@ func getPublicKey(pemContent []byte) (any, error) {
| PKCS#8 | ```smx509.ParsePKCS8PrivateKey```可以处理未加密的;```pkcs8.ParsePKCS8PrivateKeySM2```可以处理未加密的,也可以处理加密的 |
| PKCS#7 | Cryptographic Message Syntax, 可以参考github.com/emmansun/pkcs7/sign_enveloped_test.go中的```TestParseSignedEvnvelopedData```,测试数据来自 https://www.gmcert.org/ |
| CFCA自定义封装 | 顾名思义这个封装是CFCA特定的修改自PKCS#12,使用```cfca.ParseSM2```方法来解析 |
|《GB/T 35276-2017 信息安全技术 SM2密码算法使用规范》| 这个规范还比较新可能实现的系统比较少而且加密方是使用您已知的SM2公钥加密对称加密密钥的类似信封加密而不是基于密码的KDF方法来产生对称加密密钥。使用```sm2.ParseEnvelopedPrivateKey```解析 |
|《GB/T 35276-2017 信息安全技术 SM2密码算法使用规范》| 这个规范还比较新可能实现的系统比较少而且加密方是使用您已知的SM2公钥加密对称加密密钥的类似信封加密而不是基于密码/口令的KDF方法来产生对称加密密钥。使用```sm2.ParseEnvelopedPrivateKey```解析 |
有些系统可能会直接存储、得到私钥的字节数组,那么您可以使用如下方法来构造私钥:
```go

45
docs/sm3.md Normal file
View File

@ -0,0 +1,45 @@
# 参考标准
* 《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() {
sum := sm3.Sum([]byte("hello world\n"))
fmt.Printf("%x", sum)
// Output: 4cc2036b86431b5d2685a04d289dfe140a36baa854b01cb39fcd6009638e4e7a
}
// 先创建sm3 hash实例再进行hash计算
func ExampleNew() {
h := sm3.New()
h.Write([]byte("hello world\n"))
fmt.Printf("%x", h.Sum(nil))
// Output: 4cc2036b86431b5d2685a04d289dfe140a36baa854b01cb39fcd6009638e4e7a
}
// 计算文件内容hash
func ExampleNew_file() {
f, err := os.Open("file.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
h := sm3.New()
if _, err := io.Copy(h, f); err != nil {
log.Fatal(err)
}
fmt.Printf("%x", h.Sum(nil))
}
```
# 性能
请参考[SM3密码杂凑算法性能优化](https://github.com/emmansun/gmsm/wiki/SM3%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96)。

65
docs/sm4.md Normal file
View File

@ -0,0 +1,65 @@
# 参考标准
* 《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组合使用。
# 工作模式
在实际加解密操作中,我们一般不会直接使用```cipher.Block```必须结合分组密码算法的工作模式使用。除了Go语言自带的工作模式CBC/GCM/CFB/OFB/CTR本软件库也实现了下列工作模式
* ECB - 电码本模式
* BC - 分组链接模式
* HCTR - 带泛杂凑函数的计数器模式
* XTS - 带密文挪用的XEX可调分组密码模式
* OFBNLF - 带非线性函数的输出反馈模式
* CCM - 分组密码链接-消息认证码组合模式
其中ECB/BC/HCTR/XTS/OFBNLF是《GB/T 17964-2021 信息安全技术 分组密码算法的工作模式》列出的工作模式。BC/OFBNLF模式是商密中的遗留工作模式**不建议**在新的应用中使用。XTS/HCTR模式适用于对磁盘加密其中HCTR模式是《GB/T 17964-2021 信息安全技术 分组密码算法的工作模式》最新引入的HCTR模式最近业界研究比较多也指出了原论文中的BugsOn modern processors HCTR [WFW05](https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.470.5288) is one of the most efficient constructions for building a tweakable super-pseudorandom permutation. However, a bug in the specification and another in Chakraborty and Nandis security proof [CN08](https://www.iacr.org/cryptodb/archive/2008/FSE/paper/15611.pdf) invalidate the claimed security bound.
不知道这个不足是否会影响到这个工作模式的采用。很奇怪《GB/T 17964-2021 信息安全技术 分组密码算法的工作模式》为何没有纳入GCM工作模式难道是版权问题
引入CCM模式只是为了有些标准还用到该模式。ECB模式也不建议单独使用。
目前本软件库的SM4针对ECB/CBC/GCM/XTS工作模式进行了绑定组合性能优化暂时没有计划使用汇编优化HCTR模式HCTR模式可以采用和GCM类似的方法进行汇编优化
**使用建议**常用的对称加解密应用场合推荐优先使用GCM模式其次CBC模式一些安全扫描工具也会把CBC工作模式列为安全性不高的工作模式。我能想到的GCM模式的缺点是加解密的相关方不支持GCM模式或者实现性能不好。
# 填充padding
有些分组密码算法的工作模式(譬如实现了```cipher.BlockMode```接口的模式的输入要求是其长度必须是分组大小的整数倍。《GB/T 17964-2021 信息安全技术 分组密码算法的工作模式》附录C中列出了以下几种填充模式
* 填充方式 1对应本软件库的```padding.NewPKCS7Padding```
* 填充方式 2对应本软件库的```padding.NewISO9797M2Padding```
* 填充方式 3目前没有实现它对应ISO/IEC_9797-1 padding method 3
本软件库也实现了ANSI X9.23标准中定义的填充方式```padding.NewANSIX923Padding```**用的最广的还是填充方式 1PKCS7填充**。
您如果使用实现了```cipher.BlockMode```接口的分组加密工作模式那您也必须与相关方协调好填充模式。JAVA库的对称加密算法字符串名就包含了所有信息譬如**AES/CBC/PKCS7Padding**。
# 密文及其相关参数的传输和存储
如果是自描述的那肯定有相关标准定义相关ASN.1结构并且给分组密码算法、工作模式、填充方式都赋予一个OID。
如果是内部服务之间,可能是在应用/服务级别自定义所使用分组密码算法、工作模式、填充方式的标识作为应用的METADATA也就是加密用的METADATA和密文分离。
也可能是隐式使用一致的分组密码算法、工作模式、填充方式,也就是代码知道,还有文档知道?
具体使用哪种方式,取决于应用场景。
另外一个就是必须和密文一起存储/传输的参数譬如如果使用CBC工作模式那IV怎么办如果是GCM模式那Nonce、Nonce长度、Tag长度怎么办这通常也有两种方案
* 使用预定义的ASN.1结构
* 和密文简单拼接譬如CBC工作模式IV||ciphertextGCM模式使用默认Tag长度和Nonce长度Nonce||ciphertext。
至于要将二进制转为文本传输、存储编个码就行标准base64 / URL base64 / HEX事先协调、定义好就可以了。
# 性能
SM4分组密码算法的软件高效实现不算CPU指令支持的话已知有如下几种方法
* S盒和L转换预计算
* SIMD并行处理并行查表
* SIMD并行处理借助CPU的AES指令本软件库采用该方法
* SIMD并行处理位切边(bitslicing)[参考实现](https://github.com/emmansun/sm4bs)
当然这些与有CPU指令支持的AES算法相比性能差距依然偏大要是工作模式不支持并行差距就更巨大了。
# API文档及示例
详见[API Document](https://godoc.org/github.com/emmansun/gmsm)。