Go-数字签名详解与Rsa数字签名代码

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: Go-数字签名详解与Rsa数字签名代码

数字签名概述

手写签名是一种传统的确认方式,如写信、签订协议、支付确认等。在数字系统中同样有签名应用的需求,如假定A发送一个认证的信息给B,如果没有签名确认的措施,B可能伪造一个不同的消息,但声称是从A收到的;或者为了某种目的,A也可能否认发送过该消息。很显然,数字系统的特点决定了不可能沿用原先的手写签名方法来实现防伪造或抵赖,这就是提出了如何实现数字签名的问题。


数字签名(Digital Signature)是电子信息技术发展的产物,是针对电子信息 的一种签名确认方法,它是利用数学方法和密码算法对该电子信息进行关键信息提取并进行加密而形成的,所要达到的目的是:对数字对象的合法化、真实性进行标记,并提供签名者的承诺。


数字化信息的认证性、完整性和不可否认性是实现信息化的基本要求,也决定信息化的普及和推广。数字签名是满足上述要求的主要手段之一也是现代密码学的主要研究内容之一。


数字签名基于两条基本的假设:


一是私钥是安全的,只有其拥有者才能获得;


二是产生数字签名的惟一途径是使用私钥。

数字签名和手写签名的不同

签名:手写签名是被签文件的物理组成部分;数字签名是连接到被签消息上的数字串。

传输方式:数字签名和所签名的消息能够在通信网络中传输;手写签名使用传统的安全方式传输。

验证:手写签名是通过将它与真实的签名进行比较来验证;而数字签名是利用已经公开的验证算法来验证。

数字签名的复制是有效的;而手写签名的复制品是无效的!!!

手书签名是模拟的,且因人而异;数字签名是0和1的数字串,因消息而异。

数字签名与消息加密/认证

与消息加密不同:消息加密和解密可能是一次性的,它要求在解密之前是安全的;而一个签字的消息可能作为一个法律上的文件,如合同等,很可能在对消息签署多年之后才验证其签字,且可能需要多次验证此签字。

与消息认证不同:数字签名也是一种消息认证技术,它属于非对称密码体制,消息认证码属于对称密码体制,所以消息认证码的处理速度比数字签名快得多。但是,消息认证码无法实现不可否认性。

数字签名的步骤

  1. 系统初始化生成数字签名方案用到的所有参数(公私钥对)。
  2. 签名生成算法用户利用给定的算法对消息产生签名。
  3. 签名验证算法验证者利用公开的验证方法对给定消息的签名进行验证,得出签名的有效性。

数字签名的算法有RSA、ECC等。本文介绍RSA数字签名的实现,第一步的公私钥对生成见RSA加密解密详解与代码

Go中使用Rsa进行数字签名

crypto/rsa包

func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err error)

SignPKCS1v15使用RSA PKCS#1 v1.5规定的RSASSA-PKCS1-V1_5-SIGN签名方案计算签名。注意hashed必须是使用提供给本函数的hash参数对(要签名的)原始数据进行hash的结果。

func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (err error)

crypto/sha512包

func Sum512(data []byte) [Size]byte

返回数据的SHA512校验和。

代码

签名

  1. 获取私钥
  2. 使用x509.ParsePKCS1PrivateKey解析
  3. 使用sha512.Sum512获取明文校验和
  4. 使用rsa.SignPKCS1v15进行签名

func RsaSign(plainText []byte, priFilePath string) ([]byte,error) {
  // get pem.Block
  block,err := util.GetKey(priFilePath)
  if err != nil{
    _, file, line, _ := runtime.Caller(0)
    return nil,util.Error(file,line+1,err.Error())
  }
  priKey,err := x509.ParsePKCS1PrivateKey(block.Bytes)
  if err != nil{
    _, file, line, _ := runtime.Caller(0)
    return nil,util.Error(file,line+1,err.Error())
  }
  // calculate hash value
  hashText := sha512.Sum512(plainText)
  // Sign with hashText
  signText, err := rsa.SignPKCS1v15(rand.Reader, priKey, crypto.SHA512, hashText[:])
  if err != nil{
    _, file, line, _ := runtime.Caller(0)
    return nil,util.Error(file,line+1,err.Error())
  }
  return signText,nil
}

验证

  1. 获取公钥
  2. 使用x509.ParsePKIXPublicKey解析
  3. 使用sha512.Sum512获取明文校验和
  4. 使用rsa.VerifyPKCS1v15进行验证
func RsaVerify(plainText []byte, pubFilePath string,signText []byte) error {
  // get pem.Block
  block,err := util.GetKey(pubFilePath)
  if err != nil{
    _, file, line, _ := runtime.Caller(0)
    return util.Error(file,line+1,err.Error())
  }
  // x509
  pubInter,err := x509.ParsePKIXPublicKey(block.Bytes)
  if err != nil{
    _, file, line, _ := runtime.Caller(0)
    return util.Error(file,line+1,err.Error())
  }
  pubKey := pubInter.(*rsa.PublicKey)
  // hashText to verify
  hashText := sha512.Sum512(plainText)
  err = rsa.VerifyPKCS1v15(pubKey,crypto.SHA512,hashText[:],signText)
  if err != nil{
    _, file, line, _ := runtime.Caller(0)
    return util.Error(file,line+1,err.Error())
  }
  return nil
}

测试代码

func TestSignVerify(t *testing.T) {
  plainText := []byte("张华考上了北京大学;李萍进了中等技术学校;我在百货公司当售货员:我们都有美好的未来")
  signText,err := RsaSign(plainText,"./private.pem")
  if err != nil{
    fmt.Println(err)
    os.Exit(0)
  }
  fmt.Printf("%s\n",signText)
  err = RsaVerify(plainText,"./public.pem",signText)
  if err != nil{
    fmt.Println(err)
    os.Exit(0)
  }
  fmt.Println("验证成功")
  plainText = []byte("张华考上了北京大学;李萍进了中等技术学校;我在百货公司当售货员:我们都有美好的未来!")
  err = RsaVerify(plainText,"./public.pem",signText)
  if err != nil{
    fmt.Println(err)
    os.Exit(0)
  }
}

全部代码放到了码云上:https://gitee.com/frankyu365/gocrypto

截图

2020062310470442.png

参考

《现代密码学教程 谷利泽 杨义先等》


Go标准库-crypto/rsa


Go标准库-crypto/sha512


更多内容查看:网络安全-自学笔记


更多Go相关内容:Go-Golang学习总结笔记


有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。




相关文章
|
10月前
|
Go 索引
掌握Go语言:Go语言范围,优雅遍历数据结构,简化代码操作实战解析(24)
掌握Go语言:Go语言范围,优雅遍历数据结构,简化代码操作实战解析(24)
|
7月前
|
Cloud Native Go 开发工具
不改一行代码轻松玩转 Go 应用微服务治理
为了更好的进行 Go 应用微服务治理,提高研发效率和系统稳定性,本文将介绍 MSE 微服务治理方案,无需修改业务代码,实现治理能力。
19909 22
|
3月前
|
算法 安全 Go
Go 语言中实现 RSA 加解密、签名验证算法
随着互联网的发展,安全需求日益增长。非对称加密算法RSA成为密码学中的重要代表。本文介绍如何使用Go语言和[forgoer/openssl](https://github.com/forgoer/openssl)库简化RSA加解密操作,包括秘钥生成、加解密及签名验证。该库还支持AES、DES等常用算法,安装简便,代码示例清晰易懂。
76 12
|
9月前
|
算法 程序员 编译器
美丽的代码:规范go应用代码注释
【6月更文挑战第30天】本文介绍注释应与代码同步,避免误导,且关键点解释。使用LLVM构建编译器示例展示Go语言规范。注释虽有局限,但在解释复杂逻辑、业务规则时仍有其价值。程序员需平衡注释与代码的关系,创造更优的代码。
1137 0
美丽的代码:规范go应用代码注释
|
4月前
|
安全 Go 开发者
代码之美:Go语言并发编程的优雅实现与案例分析
【10月更文挑战第28天】Go语言自2009年发布以来,凭借简洁的语法、高效的性能和原生的并发支持,赢得了众多开发者的青睐。本文通过两个案例,分别展示了如何使用goroutine和channel实现并发下载网页和构建并发Web服务器,深入探讨了Go语言并发编程的优雅实现。
68 2
|
4月前
|
SQL 监控 算法
为Go应用无侵入地添加任意代码
这篇文章旨在提供技术深度和实践指南,帮助开发者理解并应用这项创新技术来提高Golang应用的监控与服务治理能力。在接下来的部分,我们将通过一些实际案例,进一步展示如何在不同场景中应用这项技术,提供更多实践启示。
|
5月前
|
JSON 搜索推荐 Go
ZincSearch搜索引擎中文文档及在Go语言中代码实现
ZincSearch官网及开发文档均为英文,对非英语用户不够友好。GoFly全栈开发社区将官方文档翻译成中文,并增加实战经验和代码,便于新手使用。本文档涵盖ZincSearch在Go语言中的实现,包括封装工具库、操作接口、统一组件调用及业务代码示例。官方文档https://zincsearch-docs.zinc.dev;中文文档https://doc.goflys.cn/docview?id=41。
239 0
|
7月前
|
缓存 NoSQL 数据库
go-zero微服务实战系列(五、缓存代码怎么写)
go-zero微服务实战系列(五、缓存代码怎么写)
|
7月前
|
程序员 测试技术 Go
用 Go 编写简洁代码的最佳实践
用 Go 编写简洁代码的最佳实践
|
7月前
|
缓存 测试技术 Go
使用Singleflight优化Go代码
使用Singleflight优化Go代码