

Golang RSA 如何私钥加密公钥解密
source link: https://ttys3.dev/post/go-rsa-private-encrypt-and-public-decrypt/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

March 22, 2021
一般来说,加密主要用于消息的传递,并且传递的消息只有持有私钥的那个人能解密。
因此, 像 RSA 这种非对称密钥加密算法的常用场景是:
对于加密,公钥加密,私钥解密。
为什么不是 私钥加密,公钥解密呢? 因为使用场景是假定 公钥 都可以获取到,因而公钥解密这种操作也就与明文无异了。
有没有私钥加密的常用场景呢?当然是有,比如常见的签名操作。
明文消息 -> 进行 hash -> 对 hash 后的结果进行私钥加密, 这个加密后的结果就是签名了。
对签名进行验证实际上就是用公钥解密,然后把解密后的hash与原始消息的hash进行对比。
客户端:明文消息 -> 进行 hash -> 对签名使用公钥进行解密,并对比 hash 结果。
the story⚓
早期版本的 Go 标准库 并不提供私钥加密 和 公钥解密功能。但是大家应该能猜想到,
其实要实现 私钥加密, 只需要在原来的签名函数上修改一个 hash 参数,使得这个 hash 啥也不做。
当然,由于明文并不能像 hash 一样是固定位数 的,因此,这里自然免不了要 padding.
Go 的 签名是采用的 PKCS #1 v1.5 padding 方式。
这个提交使得标准库直接支持 私钥加密了:
crypto/rsa: support unpadded signatures.
Usually when a message is signed it’s first hashed because RSA has low limits on the size of messages that it can sign. However, some protocols sign short messages directly. This isn’t a great idea because the messages that can be signed suddenly depend on the size of the RSA key, but several people on golang-nuts have requested support for this and it’s very easy to do.
R=golang-codereviews, rsc CC=golang-codereviews golang.org/cl/44400043
the solution⚓
Since go 1.3
, you can easily do this using SignPKCS1v15
rsa.SignPKCS1v15(nil, priv, crypto.Hash(0), plainData)
refer: https://groups.google.com/forum/#!topic/Golang-Nuts/Vocj33WNhJQ
所以,现在的 SignPKCS1v15
方法是这样的:
// SignPKCS1v15 calculates the signature of hashed using
// RSASSA-PKCS1-V1_5-SIGN from RSA PKCS #1 v1.5. Note that hashed must
// be the result of hashing the input message using the given hash
// function. If hash is zero, hashed is signed directly. This isn't
// advisable except for interoperability.
//
// If rand is not nil then RSA blinding will be used to avoid timing
// side-channel attacks.
//
// This function is deterministic. Thus, if the set of possible
// messages is small, an attacker may be able to build a map from
// messages to signatures and identify the signed messages. As ever,
// signatures provide authenticity, not confidentiality.
func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
if err != nil {
return nil, err
}
tLen := len(prefix) + hashLen
k := priv.Size()
if k < tLen+11 {
return nil, ErrMessageTooLong
}
// EM = 0x00 || 0x01 || PS || 0x00 || T
em := make([]byte, k)
em[1] = 1
for i := 2; i < k-tLen-1; i++ {
em[i] = 0xff
}
copy(em[k-tLen:k-hashLen], prefix)
copy(em[k-hashLen:k], hashed)
m := new(big.Int).SetBytes(em)
c, err := decryptAndCheck(rand, priv, m)
if err != nil {
return nil, err
}
return c.FillBytes(em), nil
}
如果给 rand 传 nil 则每次生成的加密结果都是一样的。
如果给 crypto.Hash() 传0, 则表示不进行任何 hash
因此,私钥加密实际上只是一个特殊参数的调用:
encrypted, err := rsa.SignPKCS1v15(nil, priv, crypto.Hash(0), []byte(message))
troubleshoot⚓
Golang 加密后的消息给 node.js 解密时,node.js 报错:
rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01
不要被错误信息迷惑了。这种错误跟 block type (padding) 没有什么关系。
错误的根本原因是,要么是加密的人私钥用错了,要么是解密的人公钥用错了。(没错,我在写某知名软件的注册机时,因为这个错误提示浪费了很多时间 ,直到后面意识到了问题的真正原因。 另外,我还要在这里吐槽一下某公司,你们的注册算法写得太烂了,有标准的签名算法不用,直接用的私钥加密/公钥解密这一套。还害我写这么一篇文章 。另外,都2021年了,你们还在用 RSA 1024)
refs⚓
https://golang.org/src/crypto/rsa/pkcs1v15.go?s=8774:8874#L221
https://gist.github.com/kkHAIKE/be3b8d7ff8886457c6fdac2714d56fe1
https://github.com/buf1024/golib/blob/master/crypt/rsa.go
https://topic.alibabacloud.com/a/golang-private-key-encrypt-public-key-decrypt_1_38_30920103.html
node.js 类似 https://www.geeksforgeeks.org/node-js-crypto-publicdecrypt-method/
Recommend
-
105
最近一段时间,国内各大网站纷纷用上了https连接,在访问这些网站的时候,很多浏览器会给予“特别关照”,给它们的链接旁边加上一个绿色的小锁,那么,什么是https,它与网络安全又有什么关系呢?今天我们就来谈谈https与tls(传输层安全)。
-
77
程序员 - @GuguguguDa - 下面这个博客看的我很疑惑啊先不论私钥加密,公钥解密有没有意义私钥加密的结果,用公钥解密,还能解出来的吗?我试了下,居然还真可以?https://blog.csdn.net/
-
25
以太坊geth 公私钥地址签名转换基础 以太坊中使用的椭圆曲线是S256,私钥和HASH都为32位,公钥为65位其中第一位是压缩字节0x04,压缩公钥为33字节,地址是是公钥的后64位hash后取后20个字节作为地址。签名数据为65位,R,S...
-
21
ssh利用RSA公钥远程登录验证 2013-03-12 11:54:00 1、本地机器生成密钥 $ssh-keygen -t rsa生成基于ssh协议第二版密钥,如果还是用rsa1,该升级了。 2、复制...
-
7
零一间2021.04.20 01:16:38字数 1,347阅读 29理解公钥与私钥 一、公钥算法与私钥算法 1、私钥算法 ...
-
28
web3js里有直接从私钥获取公钥的接口吗 是这个web3.shh.getPublicKey吗,我调用直接报错没有这类方法 ...
-
6
在以太坊中,账户、地址、私钥(Private Key)和公钥(Public Key)是非常重要的概念。账户扮演着以太坊的中心角色,地址是我们与以太坊系统进行交互的标识,它是以太坊账户与外界进行交互的名字,而私钥与公钥是保护我们账户安全的重要屏障。 什么是...
-
4
runliuv runliuv@cnblogs
-
3
使用 java 提取 jks 文件中的公钥和私钥 Full's Blog
-
6
jdk 中的 keytool 的使用,以及提取 jks 文件中的公钥和私钥 Full's Blog
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK