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) == {
strSignR = "" + strSignR
}
if len(strSignS) == {
strSignS = "" + 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) /
lenSignS := len(strS) /
// 2、计算DER序列的总长度
len := lenSignR + lenSignS +
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 := "" + strLen
derString += "" + strLenSignR + strR
derString += "" + strLenSignS + strS
derString += ""
return derString
} // ECDSAVerify ECDSA验证签名 (比特币系统中公钥具有0x04前缀)
func ECDSAVerify(publicKeyBytes, hashed []byte, derSignString string) bool {
// 公钥长度
keyLen := len(publicKeyBytes)
if keyLen != {
return false
}
// 1、生成椭圆曲线对象
curve := elliptic.P256()
// 2、根据公钥字节数字,获取公钥中的x和y
// 公钥字节中的前一半为x轴坐标,再将字节数组转成big.Int类型
publicKeyBytes = publicKeyBytes[:]
// x := big.NewInt(0).SetBytes(publicKeyBytes[:32])
x := new(big.Int).SetBytes(publicKeyBytes[:])
y := new(big.Int).SetBytes(publicKeyBytes[:])
// 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[:]
sBytes = derBytes[len(derBytes)- : len(derBytes)-]
return
}

go语言 内置的椭圆数字签名及其验证算法的更多相关文章

  1. 11 The Go Memory Model go语言内置模型

    The Go Memory Model go语言内置模型 Version of May 31, 2014 Introduction 介绍 Advice 建议 Happens Before 在发生之前 ...

  2. GLSL语言内置的变量详解

    GLSL语言内置的变量,包括内置的顶点属性(attribute).一致变量(uniform).易变变量(varying)以及常量(const),一方面加深印象,另一方面今天的文章可以为以后的编程做查询 ...

  3. Go语言内置包之strconv

    文章引用自 Go语言内置包之strconv Go语言中strconv包实现了基本数据类型和其字符串表示的相互转换. strconv包 strconv包实现了基本数据类型与其字符串表示的转换,主要有以下 ...

  4. go语言内置基础类型

    1.数值型(Number) 三种:整数型.浮点型和虚数型(有符号整数表示整数范围 -2n-1~2n-1-1:无符号整数表示整数范围 0~2n-1) go内置整型有:uint8, uint16, uin ...

  5. JavaScript语言内置对象

    String(字符串对象)RegExp(正则表达式对象)Number(数字对象)Math(数学对象)Function(函数对象)Error(异常对象)Date(日期/时间对象)Boolean(布尔对象 ...

  6. Golang(Go语言)内置函数之copy用法

    该函数主要是切片(slice)的拷贝,不支持数组 将第二个slice里的元素拷贝到第一个slice里,拷贝的长度为两个slice中长度较小的长度值 示例: s := []int{1,2,3} fmt. ...

  7. SQL Server 2016将内置R语言?

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:随着大数据成为一个BuzzWord,和大数据相关的技术也变得越来越火热,其中就包括R语 ...

  8. SQL Server 2016将内置R语言

    题记:随着大数据成为一个BuzzWord,和大数据相关的技术也变得越来越火热,其中就包括R语言.而据说SQL Server 2016将会内置R语言支持? R语言作为一个存在很久的语言,在大数据热炒之后 ...

  9. js中内置有对象

    statpot:使用mongo+bootstrap+highcharts做统计报表 最近做了一个统计项目,这个统计项目大致的需求是统计接口的访问速度.客户端会调用一个接口来记录接口的访问情况,我的需求 ...

随机推荐

  1. openc —— Canny 边缘检测

    边缘检测的一般步骤 [第一步]滤波 边缘检测的算法主要是基于图像强度的一阶和二阶导数,但导数通常对噪声很敏感,因此必须采用滤波器来改善与噪声有关的边缘检测器的性能.常见的滤波方法主要有高斯滤波,即采用 ...

  2. 使用scrapy框架爬取图片网全站图片(二十多万张),并打包成exe可执行文件

    目标网站:https://www.mn52.com/ 本文代码已上传至git和百度网盘,链接分享在文末 网站概览 目标,使用scrapy框架抓取全部图片并分类保存到本地. 1.创建scrapy项目 s ...

  3. P1345 [USACO5.4]奶牛的电信Telecowmunication【最小割】【最大流】

    题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流.这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成的序列a1,a2,...,a(c),且a1与a2相 ...

  4. NFS部署

    yum install nfs-utils -y systemctl restart/enable nfs systemctl status rpcbind vim /etc/exports /dat ...

  5. 论文阅读笔记(二十二)【CVPR2017】:See the Forest for the Trees: Joint Spatial and Temporal Recurrent Neural Networks for Video-based Person Re-identification

    Introduction 在视频序列中,有些帧由于被严重遮挡,需要被尽可能的“忽略”掉,因此本文提出了时间注意力模型(temporal attention model,TAM),注重于更有相关性的帧. ...

  6. [TJOI2015] 概率论 - Catalan数

    一棵随机生成的 \(n\) 个结点的有根二叉树(所有互相不同构的形态等概率出现)的叶子节点数的期望.\(n \leq 10^9\) Solution \(n\) 个点的二叉树个数即 Catalan 数 ...

  7. Elasticsearch操作Document文档

    1.利用客户端操作Document文档数据        1.1 创建一个文档(创建数据的过程,向表中去添加数据)            请求方式:Post    请求地址:es所在IP:9200/索 ...

  8. ES6基础与解构赋值(高颜值弹框小案例!)

    let只作用在当前块级作用域内使用let或者const声明的变量,不能再被重新声明let不存在`变量提升` console.log(dad); var dad = '我是爸爸!';//预定义undef ...

  9. nunjucks如何使用?

    基本的使用 const nunjucks = require('nunjucks') // nunjucks.configure({ autoescape: true }); // const res ...

  10. 剑指offer-面试题18-删除链表中重复的节点-链表

    /* 题目: 删除链表中重复的节点 */ /* 思路: 1.声明一个头节点head,即使首元节点被删除,也可返回head->next 2.声明两个指针, 一个指针qNode指向确定不会删除的链表 ...