首页 / 算法 / go语言 椭圆数字签名及其验证算法
go语言 椭圆数字签名及其验证算法
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了go语言 椭圆数字签名及其验证算法,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3750字,纯文字阅读大概需要6分钟。
内容图文
![go语言 椭圆数字签名及其验证算法](/upload/InfoBanner/zyjiaocheng/645/5a3991d84a4a4a83b0c14132aea2910e.jpg)
package main import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/sha256" "encoding/hex" "fmt" "log" "math/big" ) func main() { // 1、对需要签名的文件进行hash运算 data := "from xiaoxiao to maomao 100 btc" hashInstance := sha256.New() hashInstance.Write([]byte(data)) hashed := hashInstance.Sum(nil) // 2、生成私钥和公钥字节 privateKey, publicKeyBytes := NewKeyPair() // 3、生成签名的der编码格式 derSignString := ECDSASign(hashed, privateKey) fmt.Printf("签名信息为:%s\n", derSignString) // 4、验证签名 flag := ECDSAVerify(publicKeyBytes, hashed, derSignString) fmt.Println("签名验证结果:", flag) } // NewKeyPair 生成私钥和公钥,生成的私钥为结构体ecdsa.PrivateKey的指针 func NewKeyPair() (ecdsa.PrivateKey, []byte) { // 1、生成椭圆曲线对象 curve := elliptic.P256() // 2、生成秘钥对,返回私钥对象(ecdsa.PrivateKey指针) privateKey, err := ecdsa.GenerateKey(curve, rand.Reader) if err != nil { log.Panic(err) } // 3、编码生成公钥字节数组,参数是椭圆曲线对象、x坐标、y坐标 publicKeyBytes := elliptic.Marshal(curve, privateKey.PublicKey.X, privateKey.Y) fmt.Printf("私钥:%x\n", *privateKey) fmt.Printf("公钥:%x\n", publicKeyBytes) return *privateKey, publicKeyBytes } // ECDSASign ECDSA数字签名 func ECDSASign(hashed []byte, privateKey ecdsa.PrivateKey) string { // 1、数字签名生成r、s的big.Int对象,参数是随机数、私钥、签名文件的哈希串 r, s, err := ecdsa.Sign(rand.Reader, &privateKey, hashed) if err != nil { return "" } fmt.Println("r结果:", r) fmt.Println("s结果:", s) // 2、将r、s转成r/s字符串 strSignR := fmt.Sprintf("%x", r) strSignS := fmt.Sprintf("%x", s) if len(strSignR) == 63 { strSignR = "0" + strSignR } if len(strSignS) == 63 { strSignS = "0" + strSignS } fmt.Printf("r的16进制为:%s,长度为:%d\n", strSignR, len(strSignR)) fmt.Printf("s的16进制为:%s,长度为:%d\n", strSignS, len(strSignS)) // 3、r和s字符串拼接,形成数字签名的der格式 derString := MakeDERSignString(strSignR, strSignS) return derString } // MakeDERSignString 生成数字签名的DER编码格式 func MakeDERSignString(strR, strS string) string { // 1、获取R和S的长度 lenSignR := len(strR) / 2 lenSignS := len(strS) / 2 // 2、计算DER序列的总长度 len := lenSignR + lenSignS + 4 fmt.Printf("lenSignR为:%d,lenSignS为:%d,len为:%d\n", lenSignR, lenSignS, len) // 3、将10进制长度转16进制字符串 strLenSignR := fmt.Sprintf("%x", int64(lenSignR)) strLenSignS := fmt.Sprintf("%x", int64(lenSignS)) strLen := fmt.Sprintf("%x", int64(len)) fmt.Printf("strLenSignR为:%s,strLenSignS为:%s,strLen为:%s\n", strLenSignR, strLenSignS, strLen) // 4、拼接DER编码格式 derString := "30" + strLen derString += "02" + strLenSignR + strR derString += "02" + strLenSignS + strS derString += "01" return derString } // ECDSAVerify ECDSA验证签名 (比特币系统中公钥具有0x04前缀) func ECDSAVerify(publicKeyBytes, hashed []byte, derSignString string) bool { // 公钥长度 keyLen := len(publicKeyBytes) if keyLen != 65 { return false } // 1、生成椭圆曲线对象 curve := elliptic.P256() // 2、根据公钥字节数字,获取公钥中的x和y // 公钥字节中的前一半为x轴坐标,再将字节数组转成big.Int类型 publicKeyBytes = publicKeyBytes[1:] // x := big.NewInt(0).SetBytes(publicKeyBytes[:32]) x := new(big.Int).SetBytes(publicKeyBytes[:32]) y := new(big.Int).SetBytes(publicKeyBytes[32:]) // 3、生成公钥对象 publicKey := ecdsa.PublicKey{Curve: curve, X: x, Y: y} // 4、对der格式的签名进行解析,获取r/s字节数组后转成big.Int类型 rBytes, sBytes := ParseDERSignString(derSignString) r := new(big.Int).SetBytes(rBytes) s := new(big.Int).SetBytes(sBytes) return ecdsa.Verify(&publicKey, hashed, r, s) } // ParseDERSignString 对der格式的签名进行解析 func ParseDERSignString(derString string) (rBytes, sBytes []byte) { fmt.Println("derString:", derString) derBytes, _ := hex.DecodeString(derString) fmt.Println("derBytes", derBytes) rBytes = derBytes[4:36] sBytes = derBytes[len(derBytes)-33 : len(derBytes)-1] return }
内容总结
以上是互联网集市为您收集整理的go语言 椭圆数字签名及其验证算法全部内容,希望文章能够帮你解决go语言 椭圆数字签名及其验证算法所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。