百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

图解 Golang 实现 RSA 加密和签名(有示例)

toyiye 2024-06-21 12:00 8 浏览 0 评论

本文介绍 RSA 干了什么,以及我们怎样用 Go 实现它。

RSA(Rivest–Shamir–Adleman)加密是使用最广的安全数据加密算法之一。

它是一种非对称加密算法,也叫”单向加密“。用这种方式,任何人都可以很容易地对数据进行加密,而只有用正确的”秘钥“才能解密。

如果你想跳过解释直接看源码,点击这里[1]

RSA 加密,一言以蔽之

RSA 是通过生成一个公钥和一个私钥进行加/解密的。公钥和私钥是一起生成的,组成一对秘钥对。

公钥可以用来加密任意的数据,但不能用来解密。

私钥可以用来解密由它对应的公钥加密的数据。

这意味着我们可以把我们的公钥给任何想给的人。之后他们可以把想发送给我们的信息进行加密,唯一能访问这些信息的方式就是用我们的私钥进行解密。

秘钥的生成过程,以及信息的加密解密过程不在本文讨论范围内,但是如果你想研究详细信息,这里有一个关于此主题的强大视频[2]

秘钥的生成

我们要做的第一件事就是生成公钥私钥对。这些秘钥是随机生成的,在后面所有的处理中都会用到。

我们用标准库 crypto/rsa[3] 来生成秘钥,用 crypto/rand[4] 库来生成随机数。

// The GenerateKey method takes in a reader that returns random bits, and
// the number of bits
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
 panic(err)
}

// The public key is a part of the *rsa.PrivateKey struct
publicKey := privateKey.PublicKey

// use the public and private keys
// ...

publicKeyprivateKey 变量分别用于加密和解密。

加密

我们用 EncryptOEAP[5] 函数来加密一串随机的信息。我们需要为这个函数提供一些输入:

  1. 一个哈希函数,用了它之后要能保证即使输入做了微小的改变,输出哈希也会变化很大。SHA256 适合于此。
  2. 一个用来生成随机位的 random reader,这样相同的内容重复输入时就不会有相同的输出
  3. 之前生成的公钥
  4. 我们想加密的信息
  5. 可选的标签参数(本文中我们忽略)
encryptedBytes, err := rsa.EncryptOAEP(
 sha256.New(),
 rand.Reader,
 &publicKey,
 []byte("super secret message"),
 nil)
if err != nil {
 panic(err)
}

fmt.Println("encrypted bytes: ", encryptedBytes)

这段代码会打印加密后的字节,看起来有点像无用的信息。

解密

如果想访问加密字节承载的信息,就需要对它们进行解密。

解密它们的唯一方法就是使用与加密时的公钥对应的私钥。

*rsa.PrivateKey 结构体有一个方法 Decrypt[6],我们使用这个方法从加密数据中解出原始的信息。

解密时我们需要输入的参数有:1. 被加密的数据(称为密文)2. 加密数据用的哈希

// The first argument is an optional random data generator (the rand.Reader we used before)
// we can set this value as nil
// The OEAPOptions in the end signify that we encrypted the data using OEAP, and that we used
// SHA256 to hash the input.
decryptedBytes, err := privateKey.Decrypt(nil, encryptedBytes, &rsa.OAEPOptions{Hash: crypto.SHA256})
if err != nil {
 panic(err)
}

// We get back the original information in the form of bytes, which we
// the cast to a string and print
fmt.Println("decrypted message: ", string(decryptedBytes))

签名和校验

RSA 秘钥也用于签名和校验。签名不同于加密,签名可以让你宣示真实性,而不是机密性。

也就是说,由原始信息生成一段数据,称为“签名”,而不是伪装原始信息的内容(像加密[7]中做的那样)。

有签名、信息和公钥的任何人,可以用 RSA 校验来确保信息就是来自拥有公钥的人。如果数据和签名不匹配,校验不通过。

请注意,只有拥有私钥的人才能对信息进行签名,但是有公钥的人可以验证它。

msg := []byte("verifiable message")

// Before signing, we need to hash our message
// The hash is what we actually sign
msgHash := sha256.New()
_, err = msgHash.Write(msg)
if err != nil {
 panic(err)
}
msgHashSum := msgHash.Sum(nil)

// In order to generate the signature, we provide a random number generator,
// our private key, the hashing algorithm that we used, and the hash sum
// of our message
signature, err := rsa.SignPSS(rand.Reader, privateKey, crypto.SHA256, msgHashSum, nil)
if err != nil {
 panic(err)
}

// To verify the signature, we provide the public key, the hashing algorithm
// the hash sum of our message and the signature we generated previously
// there is an optional "options" parameter which can omit for now
err = rsa.VerifyPSS(&publicKey, crypto.SHA256, msgHashSum, signature, nil)
if err != nil {
 fmt.Println("could not verify signature: ", err)
 return
}
// If we don't get any error from the `VerifyPSS` method, that means our
// signature is valid
fmt.Println("signature verified")

总结

本文中我们看到了如何生成 RSA 公钥和私钥,以及怎样使用它们进行加密、解密、签名和验证任意数据。

在将它们用于你的数据之前,你需要了解一些使用限制。首先,你要加密的数据必须比你的秘钥短。例如,EncryptOAEP 文档[8] 中说“(要加密的)信息不能比公布的模数减去哈希长度的两倍后再减去 2 长”。

使用的哈希算法要适合你的需求。SHA256(在本例中用的就是 SHA256)可以用于大部分案例,但是如果是对数据要求更高的应用,你可能需要用 SHA512。

你可以在这里[9]找到所有示例的源码。


via: https://www.sohamkamani.com/golang/rsa-encryption/

作者:Soham Kamani[10]译者:lxbwolf[11]校对:polaris1119[12]

本文由 GCTT[13] 原创编译,Go 中文网[14] 荣誉推出

参考资料

[1]

这里: https://gist.github.com/sohamkamani/08377222d5e3e6bc130827f83b0c073e

[2]

强大视频: https://www.youtube.com/watch?v=wXB-V_Keiu8

[3]

crypto/rsa: https://pkg.go.dev/crypto/rsa?tab=doc

[4]

crypto/rand: https://pkg.go.dev/crypto/rand?tab=doc

[5]

EncryptOEAP: https://pkg.go.dev/crypto/rsa?tab=doc#EncryptOAEP

[6]

Decrypt: https://pkg.go.dev/crypto/rsa?tab=doc#PrivateKey.Decrypt

[7]

加密: https://www.sohamkamani.com/golang/rsa-encryption/#encryption

[8]

EncryptOAEP 文档: https://pkg.go.dev/crypto/rsa?tab=doc#EncryptOAEP

[9]

这里: https://gist.github.com/sohamkamani/08377222d5e3e6bc130827f83b0c073e

[10]

Soham Kamani: https://twitter.com/sohamkamani

[11]

lxbwolf: https://github.com/lxbwolf

[12]

polaris1119: https://github.com/polaris1119

[13]

GCTT: https://github.com/studygolang/GCTT

[14]

Go 中文网: https://studygolang.com/


相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码