mirror of
https://github.com/emmansun/gmsm.git
synced 2025-05-11 03:26:17 +08:00
Updated SM2性能优化 (markdown)
parent
ae918c9eb6
commit
e4cbf0a186
32
SM2性能优化.md
32
SM2性能优化.md
@ -1 +1,31 @@
|
||||
//TODO
|
||||
最近项目/产品有可能要用到国密商密的SM2加解密及签名验签,看了标准文档,参考了有关实现,发现SM2/SM3本身并不复杂,主要是SM2用到的椭圆曲线优化实现比较有难度。网上大部分Golang的SM2椭圆曲线优化实现,其实大部分都是那个“神兽压阵”的基于Golang NIST P256纯Go语言实现版本,并且比较难读。我想要自己实现一遍,切实体会一下实现的难度。
|
||||
|
||||
通过阅读Golang NIST P256那个generic的源码,并且比较NIST P256和SM2 256曲线参数的异同,逐步尝试。
|
||||
* 首先,我要替换掉p256.go中的所有常量,这个过程中遇到的最大难点在于**p256Zero31**的求解。
|
||||
* 其次, 开始解决加法(p256Sum)和减法(p256Diff)的正确性,其难点在于解决进位问题(p256ReduceCarry)
|
||||
* 然后就是解决乘法(p256Mul)的正确性,其最大难点在于蒙哥马利约简实现(p256ReduceDegree),这个花费了很多时间,也是和那个“神兽压阵”实现的最大不同。
|
||||
* 最后就是求模P的乘法逆元(p256Invert),基于费马小定理(Fermat's Little Theorem),这个就是用平方和乘法算出a^{p-2} = a^{-1} (mod p),关键是凑出p-2。
|
||||
|
||||
我保留了那些如何求取那些常量和预计算的函数在p256.go中而没有删除,供后来者参考。期间,也和ALI KMS作了集成测试,主要是SM2本地加密,ALI KMS解密; ALI KMS签名,本地验签。
|
||||
|
||||
这个实现的性能,据我测试,在amd64下大概是elliptic.CurveParams默认实现性能的**5**倍。对于这个性能,我还是不甚满意,所以开始学习Golang中NIST P256的特定优化实现,但是这里面有GO ASM,我从来没有接触过。经过一段时间的学习,开始跃跃欲试,我只有amd64,所以从amd64下手,还是从替换曲线参数开始:
|
||||
* 首先,替换掉p256_asm.go和p256_asm_amd64.s中的常量,这一步还是比较顺利,毕竟有一定经验了。
|
||||
* 接着,就是要修改p256_asm_amd64.s中的实现了,主要是蒙哥马利约简,模P的和模N的实现,原本的实现都是基于NIST P256的参数P和N进行优化的,改造起来困难挺大,为了验证结果,对每个主要的asm实现方法都写了测试,保证正确性。本以为有了32位generic实现的改造经验会比较顺利,实际情况是在这一步反反复复,几度曾想放弃。说老实话,到目前为止,我也还是不能认清p256_asm_amd64.s中用到的所有Golang ASM的命令。
|
||||
* p256_asm.go中p256Inverse的改造,因为有经验,比较顺利。
|
||||
* 然后,测试两个多倍点算法ScalarMult/ScalarBaseMult的正确性,通过和elliptic.CurveParams默认实现结果比较来鉴定。到此,sm2的加解密已经可以验证了!
|
||||
* 最后,修改实现`(curve p256Curve) Inverse(k *big.Int) *big.Int`,这个是第一次改造,费了点功夫,通过学习[算法](https://briansmith.org/ecc-inversion-addition-chains-01#p256_scalar_inversion),算是比较顺利。这个方法以及CombinedMult方法在签名和验签中有用,能提高性能。
|
||||
* 持续优化蒙哥马利约简,主要是根据P这个素数的特性,对`T3=T+(T mod 2^64)*P,T = T3 / 2^64`,努力减少乘法。
|
||||
|
||||
这个实现的性能,据我测试,在amd64下,加解密大概是elliptic.CurveParams默认实现性能的**50**倍,大概是那个纯golang 32位实现的性能的**10**倍。签名和验签我没做性能测试,不过应该也有很大提高。这个性能已经和SM2基于NIST P256曲线实现的性能相当接近了,考虑到SM2 256曲线的参数复杂度,这个性能算是不错的了。
|
||||
|
||||
最后,向Golang中NIST P256的实现者致敬!
|
||||
|
||||
**参考**:
|
||||
|
||||
[Elliptic Curve Cryptography: a gentle introduction](https://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/)
|
||||
|
||||
[Elliptic curves and their implementation (04 Dec 2010)](https://www.imperialviolet.org/2010/12/04/ecc.html)
|
||||
|
||||
[Fast prime field elliptic-curve cryptography with 256-bit primes](https://link.springer.com/article/10.1007%2Fs13389-014-0090-x)
|
||||
|
||||
[P-256 (secp256r1) Scalar Inversion](https://briansmith.org/ecc-inversion-addition-chains-01#p256_scalar_inversion)
|
Loading…
x
Reference in New Issue
Block a user