Go 語言的 RSA 加密與解密:方法與最佳實踐
一般對接過支付業務的都知道,RSA 算法。
RSA 是一種廣泛應用於安全通信領域的非對稱加密算法。
它使用一對密鑰(公鑰和私鑰)來加密和解密數據,在互聯網通信、數字簽名等場景中具有重要作用。
咱們一起看一下,在 Go 語言中,如何使用 RSA 算法。
一、RSA 加密與解密的基礎知識
1. 非對稱加密
RSA 屬於非對稱加密算法,主要特點是密鑰成對使用:一個用於加密(公鑰),另一個用於解密(私鑰)。
使用公鑰加密的數據只能用對應的私鑰解密,反之亦然。
這一特性使 RSA 非常適合用於安全通信和數字簽名。
2. 密鑰生成
RSA 密鑰由公鑰和私鑰構成。公鑰可以公開分發,而私鑰必須嚴格保密。
Go 提供了 crypto/rsa 和 crypto/rand 包,允許我們生成和使用 RSA 密鑰對。
二、RSA 加密與解密的實現
在 Go 中,實現 RSA 加密與解密涉及以下幾個步驟:
-
生成 RSA 密鑰對。
-
使用公鑰加密數據。
-
使用私鑰解密數據。
下面,我們將依次實現這些操作。
三、RSA 加密與解密方法
1. 生成 RSA 密鑰對
首先,我們需要生成一對 RSA 密鑰。
可以使用 crypto/rsa 和 crypto/rand 包來完成這一步。
通常,密鑰長度建議使用 2048 位及以上,以保證安全性。
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"os"
)
// 生成 RSA 密鑰對並保存到文件中
func generateRSAKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey) {
// 生成私鑰
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
fmt.Println("Failed to generate private key:", err)
return nil, nil
}
// 通過私鑰獲取公鑰
publicKey := &privateKey.PublicKey
// 保存私鑰到文件
savePEMKey("private.pem", privateKey)
// 保存公鑰到文件
savePublicPEMKey("public.pem", publicKey)
return privateKey, publicKey
}
// 將私鑰保存到 PEM 文件
func savePEMKey(fileName string, key *rsa.PrivateKey) {
file, err := os.Create(fileName)
if err != nil {
fmt.Println("Failed to create key file:", err)
return
}
defer file.Close()
// 將私鑰編碼爲 PEM 格式
privateKeyPEM := pem.EncodeToMemory(
&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(key),
},
)
file.Write(privateKeyPEM)
}
// 將公鑰保存到 PEM 文件
func savePublicPEMKey(fileName string, pubkey *rsa.PublicKey) {
file, err := os.Create(fileName)
if err != nil {
fmt.Println("Failed to create key file:", err)
return
}
defer file.Close()
// 將公鑰編碼爲 PKIX 格式的 PEM
pubKeyBytes, err := x509.MarshalPKIXPublicKey(pubkey)
if err != nil {
fmt.Println("Failed to marshal public key:", err)
return
}
publicKeyPEM := pem.EncodeToMemory(
&pem.Block{
Type: "PUBLIC KEY",
Bytes: pubKeyBytes,
},
)
file.Write(publicKeyPEM)
}
上述代碼生成一對 RSA 密鑰,並將私鑰和公鑰分別保存到 private.pem 和 public.pem 文件中。
密鑰長度建議爲 2048 或 4096 位,以確保安全性。
2. 使用公鑰加密數據
使用公鑰加密數據時,通常需要使用 crypto/rsa 包的 EncryptOAEP 函數,該函數基於 Optimal Asymmetric Encryption Padding (OAEP):https://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding,提供了更高的安全性。
// 使用公鑰加密
func encryptWithPublicKey(msg string, pub *rsa.PublicKey) []byte {
// 使用公鑰加密數據,採用 OAEP padding
ciphertext, err := rsa.EncryptOAEP(
sha256.New(),
rand.Reader,
pub,
[]byte(msg),
nil,
)
if err != nil {
fmt.Println("Encryption failed:", err)
return nil
}
return ciphertext
}
在此示例中,使用 rsa.EncryptOAEP 進行加密,推薦使用 SHA-256 作爲哈希函數,確保數據安全。
3. 使用私鑰解密數據
要解密用公鑰加密的數據,需要使用私鑰。我們將使用 crypto/rsa 包中的 DecryptOAEP 函數來完成這一操作。
import (
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"io/ioutil"
)
// 從 PEM 文件中加載私鑰
func loadPrivateKey(fileName string) *rsa.PrivateKey {
data, err := ioutil.ReadFile(fileName)
if err != nil {
fmt.Println("Failed to read private key file:", err)
return nil
}
block, _ := pem.Decode(data)
if block == nil || block.Type != "RSA PRIVATE KEY" {
fmt.Println("Failed to decode PEM block containing private key")
return nil
}
// 解析私鑰
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
fmt.Println("Failed to parse private key:", err)
return nil
}
return privateKey
}
// 使用私鑰解密
func decryptWithPrivateKey(ciphertext []byte, priv *rsa.PrivateKey) string {
// 使用私鑰解密數據,採用 OAEP padding
plaintext, err := rsa.DecryptOAEP(
sha256.New(),
rand.Reader,
priv,
ciphertext,
nil,
)
if err != nil {
fmt.Println("Decryption failed:", err)
return ""
}
return string(plaintext)
}
在這個示例中,我們使用 rsa.DecryptOAEP 函數和私鑰解密數據,並將加密文本轉換回明文。
4. 完整示例:加密和解密
func main() {
// 生成密鑰對
privateKey, publicKey := generateRSAKeyPair(2048)
// 原始消息
message := "Hello, RSA!"
// 使用公鑰加密
ciphertext := encryptWithPublicKey(message, publicKey)
fmt.Printf("Encrypted message: %x\n", ciphertext)
// 使用私鑰解密
plaintext := decryptWithPrivateKey(ciphertext, privateKey)
fmt.Printf("Decrypted message: %s\n", plaintext)
}
四、最佳實踐
-
密鑰安全:私鑰必須妥善保存,絕不能以明文形式存儲在代碼倉庫中。可以使用加密密鑰庫(如 AWS KMS、HashiCorp Vault 等)來保護密鑰。
-
OAEP Padding:在 RSA 加密中,始終使用
OAEP(Optimal Asymmetric Encryption Padding)以抵禦多種攻擊。 -
密鑰長度:使用至少 2048 位的密鑰長度,建議使用 4096 位以增強安全性。
-
錯誤處理:在加密和解密過程中,注意檢查並處理可能出現的錯誤,避免信息泄露。
-
避免直接加密大數據:RSA 不適合直接加密大量數據。通常應將數據先用對稱加密算法(如 AES)加密,再用 RSA 加密對稱密鑰。
五、最後
從密鑰生成開始,介紹瞭如何進行公鑰加密和私鑰解密,並給出了最佳實踐,以確保數據的安全性。
在實際應用中,請根據具體的安全要求合理使用 RSA。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/O4taKtCMyiwb0ksUOqE2OQ