when the public and private keys of sm2 are converted into hexadecimal strings, the length is not 64
jan-bar opened this issue · comments
janbar commented
This is the answer to the public and private key length given by GPT
This is a website that generates sm2 public and private keys online:https://const.net.cn/tool/sm2/genkey/
An online sm2 encryption and decryption website:https://webencrypt.org/sm2samplecryptjs/
This is my test program
package main
import (
"crypto/rand"
"fmt"
"github.com/emmansun/gmsm/sm2"
)
func main() {
for {
sm2Pri, err := sm2.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
privateKey := sm2Pri.D.Bytes()
if len(privateKey) != 32 {
fmt.Printf("privateKey len:[%d]\n", len(privateKey))
break
}
publicKey := append(sm2Pri.X.Bytes(), sm2Pri.Y.Bytes()...)
if len(publicKey) != 64 {
fmt.Printf("publicKey len:[%d]\n", len(publicKey))
break
}
}
}
As a result, the length of the public and private keys always does not meet the requirements, causing the generated public and private keys to be unusable in other programming languages.
Sun Yimin commented
- 这是两个不同的概念,这里的私钥中的D,公钥中的X,Y是*big.Int类型,其Bytes()方法返回其实际使用字节数,因为创建big.Int时,已经对其规范化,其高字节0已经去除,不计字节数。
- 和其它语言、系统互操作也有一个把公私钥规范化输出的过程,譬如公钥的PKIX, ASN.1 DER form,私钥的PKCS8、SEC1格式等等。
- 没有哪个规范指明生成的私钥,其最高字节不能为0,如果有(譬如SM2私钥生成规范)请告知。现在的方法和Go语言的方法(NIST P系列曲线的ECDSA/ECDH)是一致的。如果用于签名、加密,使用sm2包下的GenerateKey方法;如果用于ECDH,则建议使用ECDH包下的GenerateKey方法。
janbar commented
@emmansun 我现在需要对外提供十六进制的字符串公私钥,因为网上找到的一些文档和Python和js的库都用十六进制字符串表示公私钥,我试试在长度不足时高位补零看看行不行。不行就只能写个循环,生成的不合法则继续生成,直到成功 😭
Sun Yimin commented
- 不建议使用这种方式传输私钥。
- big.Int可以使用FillBytes方法输出值到固定长度字节。
func toBytes(curve elliptic.Curve, value *big.Int) []byte {
byteLen := (curve.Params().BitSize + 7) >> 3
result := make([]byte, byteLen)
value.FillBytes(result)
return result
}