【Go实战】:使用AES和RSA加密算法保护关键信息
前言
作为一名开发者,我们在构建安全可靠的应用时,确保接口请求中的关键信息不被泄露是非常重要的。加密与解密技术是实现这一目标的关键手段。本文将详细介绍如何在Golang中使用AES(高级加密标准)和RSA加密算法来实现数据的加密与解密,帮助你在接口请求中隐藏关键信息,提升系统的安全性。通过本文,你将了解这两种算法的基本原理、适用场景及注意事项,并通过具体的代码示例掌握其实现方法。无论你是初学者还是有一定经验的开发者,本文都能为你提供有价值的参考。
1. AES加密算法
AES是一种对称加密算法,意味着加密和解密过程使用相同的密钥。它支持128、192和256位三种密钥长度,其中256位密钥提供了最高的安全性。AES以其高效性和强大的安全性,成为保护敏感数据的首选。
1.1 代码示例(Go语言):
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
"log"
)
// PKCS7Padding 填充
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
// PKCS7UnPadding 去除填充
func PKCS7UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
// AESEncrypt AES 加密
func AESEncrypt(plaintext, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// 填充
plaintext = PKCS7Padding(plaintext, block.BlockSize())
// 创建 CBC 模式的加密器
ciphertext := make([]byte, len(plaintext))
mode := cipher.NewCBCEncrypter(block, key[:block.BlockSize()])
mode.CryptBlocks(ciphertext, plaintext)
return ciphertext, nil
}
// AESDecrypt AES 解密
func AESDecrypt(ciphertext, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// 创建 CBC 模式的解密器
plaintext := make([]byte, len(ciphertext))
mode := cipher.NewCBCDecrypter(block, key[:block.BlockSize()])
mode.CryptBlocks(plaintext, ciphertext)
// 去除填充
plaintext = PKCS7UnPadding(plaintext)
return plaintext, nil
}
func main() {
key := []byte("abcdefghijklmnop") // 密钥长度必须是 16, 24, 或 32 字节
plaintext := []byte("Hello, AES!")
// 加密
encrypted, err := AESEncrypt(plaintext, key)
if err != nil {
log.Fatalf("加密失败: %v", err)
}
fmt.Printf("加密后: %s\n", base64.StdEncoding.EncodeToString(encrypted))
// 解密
decrypted, err := AESDecrypt(encrypted, key)
if err != nil {
log.Fatalf("解密失败: %v", err)
}
fmt.Printf("解密后: %s\n", decrypted)
}
1.2 运行结果:
加密后: KRw1wPLUXqEjxoSsywa8IA==
解密后: Hello, AES!
2. RSA加密算法
RSA是一种非对称加密算法,使用公钥和私钥对进行加密和解密。公钥用于加密数据,私钥用于解密数据。RSA以其强大的安全性、密钥交换能力和数字签名功能,成为信息安全领域的重要组成部分。
2.1 代码示例(Go语言):
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"fmt"
"log"
)
// 生成 RSA 密钥对
func generateRSAKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey, error) {
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return nil, nil, err
}
publicKey := &privateKey.PublicKey
return privateKey, publicKey, nil
}
// 使用公钥加密数据
func encryptWithPublicKey(data []byte, publicKey *rsa.PublicKey) ([]byte, error) {
return rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, data, nil)
}
// 使用私钥解密数据
func decryptWithPrivateKey(ciphertext []byte, privateKey *rsa.PrivateKey) ([]byte, error) {
return rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, ciphertext, nil)
}
// 将私钥转换为 PEM 格式
func privateKEYToPEM(privateKey *rsa.PrivateKey) ([]byte, error) {
privateDER := x509.MarshalPKCS1PrivateKey(privateKey)
privateBlock := &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privateDER,
}
return pem.EncodeToMemory(privateBlock), nil
}
// 将公钥转换为 PEM 格式
func publicKEYToPEM(publicKey *rsa.PublicKey) ([]byte, error) {
publicDER, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return nil, err
}
publicBlock := &pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: publicDER,
}
return pem.EncodeToMemory(publicBlock), nil
}
func main() {
// 生成 RSA 密钥对
privateKey, publicKey, err := generateRSAKeyPair(2048)
if err != nil {
log.Fatalf("生成 RSA 密钥对失败: %v", err)
}
// 将私钥和公钥转换为 PEM 格式
privateKeyPEM, err := privateKEYToPEM(privateKey)
if err != nil {
log.Fatalf("将私钥转换为 PEM 格式失败: %v", err)
}
publicKeyPEM, err := publicKEYToPEM(publicKey)
if err != nil {
log.Fatalf("将公钥转换为 PEM 格式失败: %v", err)
}
fmt.Println("私钥 (PEM):")
fmt.Println(string(privateKeyPEM))
fmt.Println("公钥 (PEM):")
fmt.Println(string(publicKeyPEM))
// 要加密的数据
data := []byte("Hello, RSA!")
// 使用公钥加密数据
encryptedData, err := encryptWithPublicKey(data, publicKey)
if err != nil {
log.Fatalf("加密数据失败: %v", err)
}
fmt.Println("\n加密后的数据:")
fmt.Printf("%x\n", encryptedData)
// 使用私钥解密数据
decryptedData, err := decryptWithPrivateKey(encryptedData, privateKey)
if err != nil {
log.Fatalf("解密数据失败: %v", err)
}
fmt.Println("\n解密后的数据:")
fmt.Println(string(decryptedData))
}
2.2 运行结果:
私钥 (PEM):
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAtU6Bgi8Rskjt36socqPDPdohqWYmnXGXZfApY8R6U93C4475
MetH1JGI1MsCCcBNO/3fUOe6PGfMmZziMNxWcxYErM3XOPtfBA4QWukUO+t/JSB9
d4Z7YS8hQVGF9zs9ztR4h38dmb2CEtl6XV6+YWO/WJSfesqA0V1BuPTKuYGFC8ps
7QAGd+UnJ+zfkgSQl06u7fTLiRZP84jQTSRUIPscRq1wbbOFDcwNoPXWCW8ybdz0
5+qoh1clD1Yp/+Lz/PI1WT4y846ZJ3YGAsfWC7LfPEIZrRBAnf58Hmzm7bT4ube2
4teWPWlQtJrVY977sPvFNxT+v1IPX3LqYc+11wIDAQABAoIBAFc14A3i3jxH4EQK
bHZYV33VAwQc4s4w6YZbM02OINlefnQ/PZbJec/CAXN6Awz1tzD4OQcNsAOGWmA5
moOuONc67BzDFpeOMnIc4bkZDGaWLJ6LNk7cHVTt+q0Urb/yexSWFzP17SMaiQrQ
GY/4FtN5y3ysYNoLtlL+7LIu7aS03JKr0kFecdGE2fd459coBCZOpKTAN+UIlFjo
n/s+Z84GaOu35ApeQIeO+/qsBRfJmSw6OgdjgNkU7dveV712w1dgt0cUxeF+OBct
QNfhmmQY7OERt6nLrXg8wRoPjjt8Pe9h6H9RmeENo7EbueYXKiaZq5vgbGae0Fj6
Ay/xCgECgYEAx7EEohUzIQObsFLWs+Gx9jGPmfP5YCoB/kiQDuFHhRUt5MWzAxnF
T4f0abTV3fKPvqkwjA77mTJ61eLmihnBHXk0EJKMncLzkFXi+0C5L6CLGqCnshdJ
ToEcdcXPg9exDaFgMgOgFZRki49Y+YIpEEhJWa4I2/fTme89fYg0HcECgYEA6G5b
VmGOTswqL+LvAGNfBG+p4QIg3gbiN/56Y4N1W4hKrOnLfaYHhb3Y6TIPqhlJiNXD
ttOPyOc3JA/ZZJ5jk88rEhmXIjali8/f1QWJlJqea9Co2owJm3LIass1y7jdrJFo
cZl1V0FNwPcix9MmRuZX52nlUPIV9/1tKj5eaZcCgYA0XaVbY7fOtoWDTZXkAhGL
ACAqPSJuJ1XyetDcNhNtQMqSLY3uCDoHyx07AyL6Wvt7Ah8q+1rbJ7OylxfhqzNL
KVeP6P5a+J6qgPtO7AAkDzOrPen798NPhOgTslXiuxNBAcqaEv1N62YaevLYK1vd
Wzdw/wRvuqOQwH4dhzQzgQKBgBBilzXDstCDPAYcLVUNrEkXxhYCnGaKfbAM1Hvn
bIKDXSBLavj0l1sqQvxNdyU6myB2UVG2IFC9W/nC1ERvlf15gUPJYgobaBgvE0xl
E4nSTJC1KPIfJR48PTyqDqTJ53ae2YoIk2kPRXfw9Ba6H9ynqFK7+Fp4dmwBBY0Q
0H8JAoGBALU3itfD5YsCBtQupQ94uNmCIymMjkvlSeoC7V+z3lvXGiQRISdq7A77
YVZVHM1b36bnK+7R9A/Ev1gBc3AvB4q9pXAHmCxlwtmOUjZvXuTK6Rem/gurJmkm
MIMzsl0ElCCySsMxXslyGAyZTEgpYHueakrw+aTYayxoDtYm7Yz3
-----END RSA PRIVATE KEY-----
公钥 (PEM):
-----BEGIN RSA PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtU6Bgi8Rskjt36socqPD
PdohqWYmnXGXZfApY8R6U93C4475MetH1JGI1MsCCcBNO/3fUOe6PGfMmZziMNxW
cxYErM3XOPtfBA4QWukUO+t/JSB9d4Z7YS8hQVGF9zs9ztR4h38dmb2CEtl6XV6+
YWO/WJSfesqA0V1BuPTKuYGFC8ps7QAGd+UnJ+zfkgSQl06u7fTLiRZP84jQTSRU
IPscRq1wbbOFDcwNoPXWCW8ybdz05+qoh1clD1Yp/+Lz/PI1WT4y846ZJ3YGAsfW
C7LfPEIZrRBAnf58Hmzm7bT4ube24teWPWlQtJrVY977sPvFNxT+v1IPX3LqYc+1
1wIDAQAB
-----END RSA PUBLIC KEY-----
加密后的数据:
472886c86bf863a2dedf90dbed919c18fb0c43d8df05a696bcd9a6503372cda6adaac80dc0e1d9538f38b1b59ead2e15a0ffb08df840cda6b50c95d48d73d144a0283f20c649651f5a216ad91cfa4df63c294b9fedcd1b60ab020862ef420a83004c436400bffeece8320b678009236dea02bf8e45e700dbc903239e60242fffddee1b55f628a0b0bcdb0e87939d4117cd1eb4691bb0ba9e6b2e0deba31f4d6db023b8e75925c078de021ce13397e5888e887c54ebb839a4606a125869c6da6b04232c83ee625c8aa545005c1cd617c75fa9706694b0b058593bf5f565bb8cb4996691886d7941316b761935876700323aa8d8aa3d123fe0f9a4cc0296d3870b
解密后的数据:
Hello, RSA!
3. AES与RSA对比
为了更直观地比较AES和RSA两种加密算法,以下是一个详细的对比表格,涵盖了基本属性、密钥管理、加密效率、安全性、适用场景、密钥长度和加密模式等方面。
特性/算法 | AES | RSA |
基本属性 | 对称加密算法 | 非对称加密算法 |
密钥管理 | 加密和解密使用相同密钥 | 公钥加密,私钥解密 |
加密效率 | 高,适合处理大量数据 | 较低,适合加密小量数据或对称密钥 |
安全性 | 支持多种密钥长度,安全性高 | 基于大数分解难题,安全性高 |
适用场景 | 文件加密、数据库加密、网络通信 | 密钥交换、数字签名、电子邮件加密 |
密钥长度 | 128、192、256位 | 至少2048位 |
加密模式 | ECB、CBC、CFB、OFB、GCM等 | 通常使用PKCS#1标准,支持OAEP等填充模式 |
注意事项
密钥的安全管理:无论是AES还是RSA,密钥的安全管理都是至关重要的。确保密钥的存储和传输过程是安全的,避免硬编码在源代码中。
填充方式:在使用对称加密算法时,选择合适的填充方式(如PKCS7)可以增强安全性。
哈希函数:在使用非对称加密算法时,选择合适的哈希函数(如SHA-256)可以增强安全性。
密钥长度:对于RSA,建议使用至少2048位的密钥长度,以确保足够的安全性。
总结
作为一名开发者,确保接口请求中的关键信息不被泄露是构建安全可靠应用的重要一环。通过使用AES和RSA加密算法,你可以在接口请求中有效地隐藏关键信息,提升系统的安全性。AES以其高效性和安全性,特别适合处理大量数据,如文件加密、数据库加密和网络通信。而RSA则以其非对称加密的特点,在密钥交换、数字签名和安全通信等场景中展现出独特的优势。通过本文提供的代码示例和详细的对比表格,希望你能更好地掌握这两种加密算法,从而在实际项目中应用得更加得心应手。