1. RSA 简介
RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,使用一对公私钥进行加解密。
公钥用于加密数据,私钥用于解密数据或签名。RSA 的安全性基于大整数因子分解的难度。
Go 语言提供了crypto/rsa包实现 RSA 加解密功能。该包包含了生成密钥对、加密、解密等功能。
公钥加密、私钥解密示例:
package main import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" "fmt") func main() { // 生成RSA密钥对 privateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { panic(err) } // 使用公钥加密 message := []byte("Hello, RSA!") ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, &privateKey.PublicKey, message) if err != nil { panic(err) } // 使用私钥解密 plaintext, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, ciphertext) if err != nil { panic(err) } fmt.Printf("Original: %s\nDecrypted: %s\n", message, plaintext)}
2. AES 简介
AES(Advanced Encryption Standard)是对称加密算法,使用相同的密钥进行加解密。它支持 128、192 和 256 位密钥长度。
Go 语言的crypto/aes包提供了 AES 加解密功能。密钥长度可以是 16、24 或 32 字节。
加减密示例:
package main import ( "crypto/aes" "crypto/cipher" "crypto/rand" "fmt" "io") func main() { // 生成随机AES密钥 key := make([]byte, 32) if _, err := rand.Read(key); err != nil { panic(err) } // 加密 plaintext := []byte("Hello, AES!") ciphertext := encryptAES(plaintext, key) // 解密 decryptedText := decryptAES(ciphertext, key) fmt.Printf("Original: %s\nDecrypted: %s\n", plaintext, decryptedText)} // 加密函数func encryptAES(plaintext, key []byte) []byte { block, err := aes.NewCipher(key) if err != nil { panic(err) } ciphertext := make([]byte, aes.BlockSize+len(plaintext)) iv := ciphertext[:aes.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { panic(err) } mode := cipher.NewCBCEncrypter(block, iv) mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext) return ciphertext} // 解密函数func decryptAES(ciphertext, key []byte) []byte { block, err := aes.NewCipher(key) if err != nil { panic(err) } if len(ciphertext) < aes.BlockSize { panic("Ciphertext too short") } iv := ciphertext[:aes.BlockSize] ciphertext = ciphertext[aes.BlockSize:] mode := cipher.NewCBCDecrypter(block, iv) mode.CryptBlocks(ciphertext, ciphertext) return ciphertext}
3. RSA 数字签名
RSA 数字签名用于验证数据的完整性和来源。私钥用于签名,公钥用于验证签名。
实现签名和验证示例:
package main import ( "crypto" "crypto/rand" "crypto/rsa" "fmt") func main() { // 生成RSA密钥对 privateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { panic(err) } // 签名 message := []byte("Hello, RSA Signature!") signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, message) if err != nil { panic(err) } // 验证签名 err = rsa.VerifyPKCS1v15(&privateKey.PublicKey, crypto.SHA256, message, signature) if err != nil { fmt.Println("Signature verification failed") } else { fmt.Println("Signature verified successfully") }}
4. RSA 与 AES 结合使用
流程:
客户端生成 AES 密钥,并使用服务器公钥加密该密钥。
客户端使用生成的 AES 密钥加密数据。
服务端使用私钥解密收到的 AES 密钥。
服务端使用解密后的 AES 密钥解密数据。
实现加密通信示例:
// 客户端package main import ( "crypto/rand" "crypto/rsa" "fmt") func main() { // 生成RSA密钥对 clientPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { panic(err) } // 模拟发送公钥给服务器 clientPublicKey := &clientPrivateKey.PublicKey // 生成AES密钥 aesKey := make([]byte, 32) if _, err := rand.Read(aesKey); err != nil { panic(err) } // 使用服务器公钥加密AES密钥 encryptedAESKey, err := rsa.EncryptPKCS1v15(rand.Reader, clientPublicKey, aesKey) if err != nil { panic(err) } fmt.Printf("Encrypted AES Key: %x\n", encryptedAESKey)} // 服务端package main import ( "crypto/rand" "crypto/rsa" "fmt") func main() { // 生成RSA密钥对 serverPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { panic(err) } // 模拟接收客户端发送的加密的AES密钥 // 在实际应用中,此处应从网络或其他安全通道接收密钥 // encryptedAESKey := ... // 使用私钥解密AES密钥 decryptedAESKey, err := rsa.DecryptPKCS1v15(rand.Reader, serverPrivateKey, encryptedAESKey) if err != nil { panic(err) } fmt.Printf("Decrypted AES Key: %x\n", decryptedAESKey)}
客户端:数据 AES 加密+AES 密钥 RSA 加密
// 客户端package main import ( "crypto/aes" "crypto/cipher" "crypto/rand" "crypto/rsa" "fmt" "io") func main() { // 生成RSA密钥对 clientPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { panic(err) } // 模拟发送公钥给服务器 clientPublicKey := &clientPrivateKey.PublicKey // 生成AES密钥 aesKey := make([]byte, 32) if _, err := rand.Read(aesKey); err != nil { panic(err) } // 使用服务器公钥加密AES密钥 encryptedAESKey, err := rsa.EncryptPKCS1v15(rand.Reader, clientPublicKey, aesKey) if err != nil { panic(err) } // 加密数据 message := []byte("Hello, Secure Communication!") ciphertext := encryptAES(message, aesKey) fmt.Printf("Encrypted AES Key: %x\n", encryptedAESKey) fmt.Printf("Encrypted Data: %x\n", ciphertext)} // 加密函数func encryptAES(plaintext, key []byte) []byte { block, err := aes.NewCipher(key) if err != nil { panic(err) } ciphertext := make([]byte, aes.BlockSize+len(plaintext)) iv := ciphertext[:aes.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { panic(err) } mode := cipher.NewCBCEncrypter(block, iv) mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext) return ciphertext}
服务端:AES 密钥 RSA 解密+数据 AES 解密
// 服务端package main import ( "crypto/aes" "crypto/cipher" "crypto/rand" "crypto/rsa" "fmt" "io") func main() { // 生成RSA密钥对 serverPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { panic(err) } // 模拟接收客户端发送的加密的AES密钥和数据 // 在实际应用中,此处应从网络或其他安全通道接收数据 // encryptedAESKey := ... // encryptedData := ... // 使用私钥解密AES密钥 decryptedAESKey, err := rsa.DecryptPKCS1v15(rand.Reader, serverPrivateKey, encryptedAESKey) if err != nil { panic(err) } // 解密数据 decryptedData := decryptAES(encryptedData, decryptedAESKey) fmt.Printf("Decrypted AES Key: %x\n", decryptedAESKey) fmt.Printf("Decrypted Data: %s\n", decryptedData)} // 解密函数func decryptAES(ciphertext, key []byte) []byte { block, err := aes.NewCipher(key) if err != nil { panic(err) } if len(ciphertext) < aes.BlockSize { panic("Ciphertext too short") } iv := ciphertext[:aes.BlockSize] ciphertext = ciphertext[aes.BlockSize:] mode := cipher.NewCBCDecrypter(block, iv) mode.CryptBlocks(ciphertext, ciphertext) return ciphertext}
5. 实用功能
5.1 PEM 编码解析
PEM 编码用于将二进制数据转换为可打印的 ASCII 字符。在加解密中,PEM 编码通常用于存储密钥。
package main import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" "fmt") func main() { // 生成RSA密钥对 privateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { panic(err) } // 将私钥编码为PEM格式 privateKeyPEM := pem.EncodeToMemory(&pem.Block{ Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey), }) // 将PEM格式的私钥解析回RSA密钥 block, _ := pem.Decode(privateKeyPEM) parsedPrivateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { panic(err) } fmt.Println("Private keys are equal:", *parsedPrivateKey == *privateKey)}
5.2 CBC 模式
CBC(Cipher Block Chaining)是一种分组密码的工作模式,每个明文块与前一个密文块进行异或操作。在crypto/aes 中,使用 cipher.NewCBCDecrypter 和 cipher.NewCBCEncrypter 创建 CBC 模式加解密器。
5.3 PKCS#7 数据填充
PKCS#7 是一种填充方案,用于将数据填充到块大小的整数倍。在 crypto/aes 中,可以使用 crypto/rand 包的 Read 函数进行填充。
5.4 16 位 IV 生成
IV(Initialization Vector)是在加密过程中使用的初始值。在 AES 中,IV 通常是一个固定长度的随机数,可以使用 crypto/rand 包生成。
5.5 Base64 编码
Base64 编码是一种将二进制数据转换为可打印 ASCII 字符的方法。在加解密中,Base64 编码通常用于传输密文。
5.6 加密密文存储
在实际应用中,密文通常需要存储在数据库或文件中。安全存储密文以及密钥的管理尤为重要。
6. 性能优化
选择 RSA 密钥长度时,需权衡安全性和性能。较长的密钥更安全,但可能导致性能下降。
一些平台提供硬件加速 AES 指令集,可显著提高性能。在选择平台时,考虑硬件支持。
Go 语言中可使用 goroutines 实现并发加密,提高系统的吞吐量。
7. 总结
Go 语言的 crypto 包提供了强大的加密功能,涵盖了对称加密(如 AES)和非对称加密(如 RSA)等多种算法,满足不同场景的需求。
Go 语言的 crypto 包设计简洁且易用,提供了清晰的 API 和示例,使开发者能够轻松实现各种加密需求。
结合 RSA 和 AES 的加密方案在网络通信中广泛应用,通过 RSA 实现密钥的安全交换,再利用 AES 进行快速的数据加解密,既保障了通信的机密性,又确保了密钥的安全性。
总体而言,Go 语言提供了完善的加密功能和工具,使开发者能够轻松实现安全可靠的加密通信系统。
在应用中,务必根据实际需求选择适当的加密算法、密钥长度,并采取适当的措施保障密钥的安全存储和传输,以确保系统的整体安全性。