网站首页 > 技术文章 正文
本文介绍 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
// ...
publicKey 和 privateKey 变量分别用于加密和解密。
加密
我们用 EncryptOEAP[5] 函数来加密一串随机的信息。我们需要为这个函数提供一些输入:
- 一个哈希函数,用了它之后要能保证即使输入做了微小的改变,输出哈希也会变化很大。SHA256 适合于此。
- 一个用来生成随机位的 random reader,这样相同的内容重复输入时就不会有相同的输出
- 之前生成的公钥
- 我们想加密的信息
- 可选的标签参数(本文中我们忽略)
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/
- 上一篇: 实践干货:Axure插入图标的4种办法
- 下一篇: 浅谈RSA加密 rsa加密用法
猜你喜欢
- 2025-07-01 Java 如何加载带密码的 PCKS8 PEM 私钥
- 2025-07-01 犯罪啊 2.8万台路由器居然共用一把RSA密钥
- 2025-07-01 HTTPS全站加密时代 网宿推证书优选方案
- 2025-07-01 如何在 Windows 11 或 10 上使用 Winget 安装 OpenSSH
- 2025-07-01 网络篇:朋友面试之https认证加密过程
- 2025-07-01 如何安全管理SSH密钥以防止服务器被入侵
- 2025-07-01 在 Windows 10 上实现免密码 SSH 登录
- 2025-07-01 HTTPS的加密过程是怎样的?(https加密和解密的过程)
- 2025-07-01 Linux系统实现SSH安全免密登录的设置与管理
- 2025-07-01 Burpsuit插件开发之RSA加解密(burpsuite安装插件)
你 发表评论:
欢迎- 584℃几个Oracle空值处理函数 oracle处理null值的函数
- 578℃Oracle分析函数之Lag和Lead()使用
- 565℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 563℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 559℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 551℃【数据统计分析】详解Oracle分组函数之CUBE
- 538℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 532℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- 前端懒加载 (49)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle的函数 (57)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)