国密算法Go语言实现(详解)(七) ——SM2(椭圆曲线公钥密码算法)
原创代码:https://github.com/ZZMarquis/gm
引用时,请导入原创代码库。本文仅以注释方式详解代码逻辑,供学习研究使用。
对原创代码的修改内容
- 修改了部分常量、变量、结构体属性的名称, 以便与GO语言标准包规范相统一
- 加入中文注释,解释代码逻辑
注释者及联系邮箱
Paul Lee
paul_lee0919@163.com
// PublicKey 代表SM2算法的公钥类:
// (1) X,Y 为P点(有限素数域上基点G的D倍点)坐标
// (2) Curve 为SM2算法的椭圆曲线
type PublicKey struct {
X, Y *big.Int
Curve P256V1Curve
}
// PrivateKey 代表SM2算法的私钥类:
// (1) D代表公钥P点相对于基点G的倍数
// (2) Curve 为SM2算法的椭圆曲线
type PrivateKey struct {
D *big.Int
Curve P256V1Curve
}
以上为SM2算法公钥类和私钥类的定义,其中:
- 不论是公钥类还是私钥类,均将其基础椭圆曲线定义作为基本属性
- 公钥为曲线上的一个点P,因此,其特征值指向P点坐标(X, Y)
- 私钥为公钥点P相对于基点G的倍数,因此,其特征值指向倍数D
// GenerateKey 为国密SM2生成秘钥对的函数:
// (1) 利用GO语言标准包crypto/rand生成随机数rand;
// (2) 将SM2推荐曲线参数和随机数rand输入GO语言标准包crypto/elliptic的公钥对生成方法GenerateKey(),生成密钥对核心参数(priv, x, y);
// (3) 根据PublicKey类和PrivateKey类的定义生成公钥和私钥的实例,并将上述核心参数赋值给实例各相应属性以完成初始化.
func GenerateKey(rand io.Reader) (*PrivateKey, *PublicKey, error) {
priv, x, y, err := elliptic.GenerateKey(sm2P256V1, rand)
if err != nil {
return nil, nil, err
}
privateKey := new(PrivateKey)
privateKey.Curve = sm2P256V1
privateKey.D = new(big.Int).SetBytes(priv)
publicKey := new(PublicKey)
publicKey.Curve = sm2P256V1
publicKey.X = x
publicKey.Y = y
return privateKey, publicKey, nil
}
GenerateKey( )为国密SM2生成秘钥对的函数:
- (1) 利用GO语言标准包crypto/rand生成随机数rand;
- (2) 将SM2推荐曲线参数和随机数rand输入GO语言标准包crypto/elliptic的公钥对生成方法GenerateKey(),生成密钥对核心参数(priv, x, y);
- (3) 根据PublicKey类和PrivateKey类的定义生成公钥和私钥的实例,并将上述核心参数赋值给实例各相应属性以完成初始化.
// RawBytesToPublicKey 将字节数组形式的原始格式数据转化为SM2公钥的方法:
// (1) 校验原始格式数据的字节长度(32的2倍,即64个字节)
// (2) 利用GO语言标准包math/big的SetBytes()方法将原始格式数据