代码地址:https://github.com/Freezingsmile/fabric-gmsm
主要是根据原bccsp的sw文件夹,通过参考里面的rsa、ecdsa、aes等算法的使用,新增sm2、sm3、sm4等算法的调用。
bccsp的代码实现结构
bccsp.go: 主要接口声明的文件,比如 BCCSP、Key、各种 Opts 等, 其中
BCCSP 接口为主要接口。
sw: bccsp 的纯软件实现,内部实现通过调用 go 原生支持的密码算法,并且
提供了一个 keystore 来保存密钥。
pkcs11: bccsp 的 pkcs11 实现,通过调用 pkcs11 接口来实现相关的密码操
作,仅支持 ecdsa、rsa 以及 aes 算法。密钥保存在 pkcs11 通过 pin 口令保
护的数据库或者硬件设备中。
utils:工具包,密钥编码转换等
signer: 实现了 go 的 crypto.signer 接口
factory:factory 是 bccsp 的一个工厂,可以通过这个工厂返回一个具体的
bccsp 实例,比如上面说的 sw 或者 pkcs11,如果添加了自己的 bccsp 实现,
也要讲该 bccsp 添加到 factory 中。
fileks.go:与密钥存储和读取相关
impl.go:sw 的主文件,通过调用 6 中的函数来实现 bccsp 的各个接口。
以算法名字开头的:密码算法实现相关。
以算法名字+key 开头的: 定义该算法密钥的具体数据结构,并实现 Key 接口
以 bccsp 接口函数名开头的:包含了 bccsp 接口各个函数的具体实现代码。
BCCSP 实例是通过工厂来提供的,sw 包对应的工厂在 swFactory.go 中实现,
pkcs11 包对应的工厂在 pkcs11Factory.go 中实现,它们都共同实现了的
BCCSPFactory 接口。
以下主要讲述具有国密算法改动的部分。
sm2.go
sm2.go文件里面调用了SM2类型的签名者和校验者的接口实现。主要包含了签名和验签功能。
func signGMSM2(k *sm2.PrivateKey, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) {
signature, err = k.Sign(rand.Reader, digest, opts)
return
}
func verifyGMSM2(k *sm2.PublicKey, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) {
valid = k.Verify(digest, signature)
return
}
type gmsm2Signer struct{
}
func (s *gmsm2Signer) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) {
return signGMSM2(k.(*gmsm2PrivateKey).privKey, digest, opts)
}
type ecdsaPrivateKeySigner struct{
}
func (s *ecdsaPrivateKeySigner) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) {
puk := k.(*ecdsaPrivateKey).privKey.PublicKey
sm2pk := sm2.PublicKey{
Curve: puk.Curve,
X: puk.X,
Y: puk.Y,
}
privKey := k.(*ecdsaPrivateKey).privKey
sm2privKey := sm2.PrivateKey{
D: privKey.D,
PublicKey: sm2pk,
}
return signGMSM2(&sm2privKey, digest, opts)
}
type gmsm2PrivateKeyVerifier struct{
}
func (v *gmsm2PrivateKeyVerifier) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) {
return verifyGMSM2(&(k.(*gmsm2PrivateKey).privKey.PublicKey), signature, digest, opts)
}
type gmsm2PublicKeyKeyVerifier struct{
}
func (v *gmsm2PublicKeyKeyVerifier) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) {
return verifyGMSM2(k.(*gmsm2PublicKey).pubKey, signature, digest, opts)
}
type ecdsaPrivateKeyVerifier struct{
}
func (v *ecdsaPrivateKeyVerifier) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) {
puk := k.(*ecdsaPrivateKey).privKey.PublicKey
sm2pk := sm2.PublicKey{
Curve: puk.Curve,
X: puk.X,
Y: puk.Y,
}
return verifyGMSM2(&sm2pk, signature, digest, opts)
}
type ecdsaPublicKeyKeyVerifier struct{
}
func (v *ecdsaPublicKeyKeyVerifier) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) {
puk := k.(*ecdsaPublicKey).pubKey
sm2pk := sm2.PublicKey{
Curve: puk.Curve,
X: puk.X,
Y: puk.Y,
}
return verifyGMSM2(&sm2pk, signature, digest, opts)
}
Sign和Verify主要是调用sm2的函数算法,其中由于ecdsa与sm2同属椭圆曲线加密算法,其在函数调用上有一定的共通性,所以也可以用ecdsa算法产生的密钥当作参数。
sm2key.go
SM2类型的Key接口实现,包括sm2PrivateKey和sm2PublicKey。
type gmsm2PrivateKey struct {
privKey *sm2.PrivateKey
}
func (k *gmsm2PrivateKey) PublicKey() (bccsp.Key, error) {