-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
113 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)。 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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模式最近业界研究比较多,也指出了原论文中的Bugs:On 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 Nandi’s 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```,**用的最广的还是填充方式 1:PKCS7填充**。 | ||
|
||
您如果使用实现了```cipher.BlockMode```接口的分组加密工作模式,那您也必须与相关方协调好填充模式。JAVA库的对称加密算法字符串名就包含了所有信息,譬如**AES/CBC/PKCS7Padding**。 | ||
|
||
# 密文及其相关参数的传输和存储 | ||
如果是自描述的,那肯定有相关标准,定义相关ASN.1结构,并且给分组密码算法、工作模式、填充方式都赋予一个OID。 | ||
|
||
如果是内部服务之间,可能是在应用/服务级别自定义所使用分组密码算法、工作模式、填充方式的标识,作为应用的METADATA,也就是加密用的METADATA和密文分离。 | ||
|
||
也可能是隐式使用一致的分组密码算法、工作模式、填充方式,也就是代码知道,还有文档知道? | ||
|
||
具体使用哪种方式,取决于应用场景。 | ||
|
||
另外一个就是必须和密文一起存储/传输的参数,譬如,如果使用CBC工作模式,那IV怎么办?如果是GCM模式,那Nonce、Nonce长度、Tag长度怎么办?这通常也有两种方案: | ||
* 使用预定义的ASN.1结构 | ||
* 和密文简单拼接:譬如CBC工作模式:IV||ciphertext;GCM模式(使用默认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)。 | ||
|