Golang实现RSA加密和签名(附示例)
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 适合于此。
- 随机读取器用于生成随机位,因此重复输入相同内容不会有相同的输出
- 之前生成的公钥
- 我们要加密的信息
- 可选标签参数(本文忽略)
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))
S// 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))
签名和验证使用密钥 A也用于签名和验证。签名与加密不同,签名允许您声明真实性,而不是机密性。
// 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))
这意味着从原始消息生成一条称为“签名”的数据,而不是屏蔽原始消息的内容(如加密中所做的那样[7])。
请注意,只有拥有私钥的人才能对消息进行签名,但拥有公钥的人可以验证它。
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]。
来自:https://www.sohamkamani.com/golang/rsa-encryption/
作者:Soham Kamani[10]译者:lxb
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。