Go实现Rsa+Aes混合加密、端到端加密
只是个示例,用户的数据在内存

目前服务器给客户端回消息是没加密的、若要加密,就让客户端也生成自己的私钥,公钥。
然后把自己的公钥传到服务器,服务器回复用客户端的公钥进行加密aes的key、原理是一样的
server
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"log"
"net/http"
"sync"
)
// 用户密钥结构
type UserKey struct {
UserID string
PublicKey string
PrivateKey *rsa.PrivateKey
User string
}
// 服务端密钥管理
type KeyManager struct {
users map[string]*UserKey
mutex sync.RWMutex
}
func NewKeyManager() *KeyManager {
return &KeyManager{
users: make(map[string]*UserKey),
}
}
// 生成新的RSA密钥对
func (km *KeyManager) generateNewKeyPair() (*rsa.PrivateKey, error) {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, fmt.Errorf("生成RSA密钥失败: %v", err)
}
return privateKey, nil
}
// 保存或更新用户密钥
func (km *KeyManager) saveOrUpdateUserKey(userID, user string, privateKey *rsa.PrivateKey) error {
// 序列化公钥
publicKeyBytes, err := x509.MarshalPKIXPublicKey(&privateKey.PublicKey)
if err != nil {
return fmt.Errorf("序列化公钥失败: %v", err)
}
pemPublicKey := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: publicKeyBytes,
})
// 保存用户密钥信息
km.mutex.Lock()
defer km.mutex.Unlock()
km.users[userID] = &UserKey{
UserID: userID,
PublicKey: string(pemPublicKey),
PrivateKey: privateKey,
User: user,
}
return nil
}
// 根据用户ID获取私钥
func (km *KeyManager) getPrivateKeyByUserID(userID string) (*rsa.PrivateKey, error) {
km.mutex.RLock()
defer km.mutex.RUnlock()
userKey, exists := km.users[userID]
if !exists {
return nil, fmt.Errorf("用户不存在: %s", userID)
}
return userKey.PrivateKey, nil
}
// 根据用户ID获取公钥
func (km *KeyManager) getPublicKeyPEMByUserID(userID string) (string, error) {
km.mutex.RLock()
defer km.mutex.RUnlock()
userKey, exists := km.users[userID]
if !exists {
return "", fmt.Errorf("用户不存在: %s", userID)
}
return userKey.PublicKey, nil
}
// AES解密函数
func aesDecrypt(data, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonceSize := gcm.NonceSize()
if len(data) < nonceSize {
return nil, fmt.Errorf("密文太短")
}
nonce, ciphertext := data[:nonceSize], data[nonceSize:]
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
return nil, err
}
return plaintext, nil
}
// RSA解密AES密钥
func (km *KeyManager) decryptAESKey(encryptedKeyStr string, userID string) ([]byte, error) {
encryptedKey, err := base64.StdEncoding.DecodeString(encryptedKeyStr)
if err != nil {
return nil, fmt.Errorf("解码加密密钥失败: %v", err)
}
// 获取用户的私钥
privateKey, err := km.getPrivateKeyByUserID(userID)
if err != nil {
return nil, fmt.Errorf("获取用户私钥失败: %v", err)
}
aesKey, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, encryptedKey, nil)
if err != nil {
return nil, fmt.Errorf("RSA解密密钥失败: %v", err)
}
return aesKey, nil
}
// 服务端处理加密数据
func (km *KeyManager) decryptData(encryptedDataStr, encryptedKeyStr, userID string) (string, error) {
// 解密AES密钥
aesKey, err := km.decryptAESKey(encryptedKeyStr, userID)
if err != nil {
return "", err
}
// 解密数据
encryptedData, err := base64.StdEncoding.DecodeString(encryptedDataStr)
if err != nil {
return "", fmt.Errorf("解码加密数据失败: %v", err)
}
decryptedData, err := aesDecrypt(encryptedData, aesKey)
if err != nil {
return "", fmt.Errorf("AES解密失败: %v", err)
}
return string(decryptedData), nil
}
func main() {
keyManager := NewKeyManager()
// 启动HTTP服务器
http.HandleFunc("/public-key", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost { // 使用POST方法接收登录信息
http.Error(w, "只支持POST方法", http.StatusMethodNotAllowed)
return
}
// 获取登录信息
userID := r.FormValue("user_id")
user := r.FormValue("user")
password := r.FormValue("password")
if userID == "" || user == "" || password == "" {
http.Error(w, "缺少用户ID、用户名或密码", http.StatusBadRequest)
return
}
// 简单密码验证
if password != "123456" {
http.Error(w, "密码错误", http.StatusUnauthorized)
return
}
// 生成新的密钥对
privateKey, err := keyManager.generateNewKeyPair()
if err != nil {
log.Printf("生成密钥对失败: %v", err)
http.Error(w, fmt.Sprintf("生成密钥对失败: %v", err), http.StatusInternalServerError)
return
}
// 保存或更新用户密钥
err = keyManager.saveOrUpdateUserKey(userID, user, privateKey)
if err != nil {
log.Printf("保存用户密钥失败: %v", err)
http.Error(w, fmt.Sprintf("保存用户密钥失败: %v", err), http.StatusInternalServerError)
return
}
// 返回用户的公钥
publicKeyPEM, err := keyManager.getPublicKeyPEMByUserID(userID)
if err != nil {
log.Printf("获取用户公钥失败: %v", err)
http.Error(w, fmt.Sprintf("获取用户公钥失败: %v", err), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/plain")
fmt.Println("生成公钥", publicKeyPEM)
fmt.Fprint(w, publicKeyPEM)
})
http.HandleFunc("/decrypt", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "只支持POST方法", http.StatusMethodNotAllowed)
return
}
// 从请求中获取加密数据、加密密钥和用户ID
encryptedData := r.FormValue("data")
encryptedKey := r.FormValue("key")
userID := r.FormValue("user_id")
fmt.Println("收到的请求数据", encryptedData, encryptedKey, userID)
if encryptedData == "" || encryptedKey == "" || userID == "" {
http.Error(w, "缺少加密数据、加密密钥或用户ID", http.StatusBadRequest)
return
}
// 解密数据
decryptedData, err := keyManager.decryptData(encryptedData, encryptedKey, userID)
if err != nil {
log.Printf("解密失败: %v", err)
http.Error(w, fmt.Sprintf("解密失败: %v", err), http.StatusBadRequest)
return
}
w.Header().Set("Content-Type", "text/plain")
fmt.Println("解密数据", decryptedData)
fmt.Fprint(w, decryptedData)
})
// 获取指定用户的公钥--端到端加密
http.HandleFunc("/user-public-key", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "只支持POST方法", http.StatusMethodNotAllowed)
return
}
// 验证请求者身份--todo
requesterID := r.FormValue("requester_id")
requesterPassword := r.FormValue("requester_password")
targetUserID := r.FormValue("target_user_id")
if requesterID == "" || requesterPassword == "" || targetUserID == "" {
http.Error(w, "缺少必要参数", http.StatusBadRequest)
return
}
// 验证请求者身份(密码验证)
if requesterPassword != "123456" { // 实际应用中应该使用更安全的验证方式
http.Error(w, "身份验证失败", http.StatusUnauthorized)
return
}
// 获取目标用户的公钥
publicKeyPEM, err := keyManager.getPublicKeyPEMByUserID(targetUserID)
if err != nil {
log.Printf("获取用户公钥失败: %v", err)
http.Error(w, fmt.Sprintf("获取用户公钥失败: %v", err), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/plain")
fmt.Fprint(w, publicKeyPEM)
})
// 接收客户端公钥
http.HandleFunc("/client-public-key", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "只支持POST方法", http.StatusMethodNotAllowed)
return
}
userID := r.FormValue("user_id")
password := r.FormValue("password")
clientPublicKey := r.FormValue("public_key")
if userID == "" || password == "" || clientPublicKey == "" {
http.Error(w, "缺少必要参数", http.StatusBadRequest)
return
}
// 验证用户身份
if password != "123456" {
http.Error(w, "身份验证失败", http.StatusUnauthorized)
return
}
// 保存客户端公钥
keyManager.mutex.Lock()
if userKey, exists := keyManager.users[userID]; exists {
userKey.PublicKey = clientPublicKey // 更新客户端公钥
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, "客户端公钥保存成功")
} else {
// 如果用户不存在,创建新用户(需要先注册)
keyManager.mutex.Unlock()
http.Error(w, "用户不存在,请先注册", http.StatusNotFound)
return
}
keyManager.mutex.Unlock()
})
fmt.Println("服务端启动在 :8080 端口")
fmt.Printf("公钥获取地址: http://localhost:8080/public-key\n")
fmt.Printf("解密接口地址: POST http://localhost:8080/decrypt\n")
fmt.Printf("获取用户公钥接口地址: POST http://localhost:8080/user-public-key\n")
fmt.Printf("上传用户公钥接口地址: POST http://localhost:8080/client-public-key\n")
log.Fatal(http.ListenAndServe(":8080", nil))
}
client
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"io"
"net/http"
"net/url"
"strings"
)
// AES加密函数
func aesEncrypt(data, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonce := make([]byte, gcm.NonceSize())
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
return nil, err
}
ciphertext := gcm.Seal(nonce, nonce, data, nil)
return ciphertext, nil
}
// 从PEM格式加载公钥
func loadPublicKey(publicKeyPEM string) (*rsa.PublicKey, error) {
block, _ := pem.Decode([]byte(publicKeyPEM))
if block == nil {
return nil, fmt.Errorf("无法解码PEM格式的公钥")
}
publicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("解析公钥失败: %v", err)
}
rsaPublicKey, ok := publicKey.(*rsa.PublicKey)
if !ok {
return nil, fmt.Errorf("解析的公钥不是RSA公钥")
}
return rsaPublicKey, nil
}
// 使用服务端公钥进行混合加密
func hybridEncryptWithServerKey(plaintext string, serverPublicKeyPEM string) (string, string, error) {
// 加载服务端公钥
publicKey, err := loadPublicKey(serverPublicKeyPEM)
if err != nil {
return "", "", fmt.Errorf("加载公钥失败: %v", err)
}
// 生成AES密钥
aesKey := make([]byte, 32) // 256位密钥
if _, err := io.ReadFull(rand.Reader, aesKey); err != nil {
return "", "", fmt.Errorf("生成AES密钥失败: %v", err)
}
// 使用AES加密数据
encryptedData, err := aesEncrypt([]byte(plaintext), aesKey)
if err != nil {
return "", "", fmt.Errorf("AES加密失败: %v", err)
}
// 使用RSA公钥加密AES密钥
encryptedKey, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, aesKey, nil)
if err != nil {
return "", "", fmt.Errorf("RSA加密密钥失败: %v", err)
}
// 编码结果
encodedData := base64.StdEncoding.EncodeToString(encryptedData)
encodedKeyStr := base64.StdEncoding.EncodeToString(encryptedKey)
return encodedData, encodedKeyStr, nil
}
// 登录并从服务端获取公钥
func getServerPublicKey(serverURL, userID, user string) (string, error) {
// 构建登录请求
client := &http.Client{}
formData := fmt.Sprintf("user_id=%s&user=%s&password=123456", url.QueryEscape(userID), url.QueryEscape(user))
req, err := http.NewRequest("POST", serverURL+"/public-key", strings.NewReader(formData))
if err != nil {
return "", fmt.Errorf("创建登录请求失败: %v", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("发送登录请求失败: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("登录失败,状态码: %d", resp.StatusCode)
}
publicKeyPEM := make([]byte, 2048) // 预分配更多空间
n, err := resp.Body.Read(publicKeyPEM)
if err != nil && err.Error() != "EOF" {
return "", fmt.Errorf("读取公钥失败: %v", err)
}
return string(publicKeyPEM[:n]), nil
}
// 向服务端发送加密数据并获取解密结果
func sendEncryptedData(serverURL, encryptedData, encryptedKey, userID string) (string, error) {
// URL编码加密数据和密钥
encodedData := url.QueryEscape(encryptedData)
encodedKey := url.QueryEscape(encryptedKey)
encodedUserID := url.QueryEscape(userID)
client := &http.Client{}
// 构建POST请求
reqBody := fmt.Sprintf("data=%s&key=%s&user_id=%s", encodedData, encodedKey, encodedUserID)
req, err := http.NewRequest("POST", serverURL+"/decrypt", strings.NewReader(reqBody))
if err != nil {
return "", fmt.Errorf("创建请求失败: %v", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("发送请求失败: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("解密失败,状态码: %d", resp.StatusCode)
}
result := make([]byte, 1024) // 预分配空间
n, err := resp.Body.Read(result)
if err != nil && err.Error() != "EOF" {
return "", fmt.Errorf("读取解密结果失败: %v", err)
}
return string(result[:n]), nil
}
// 获取其他用户的公钥--端到端加密
func getTargetUserPublicKey(serverURL, requesterID, requesterPassword, targetUserID string) (string, error) {
client := &http.Client{}
formData := fmt.Sprintf("requester_id=%s&requester_password=%s&target_user_id=%s",
url.QueryEscape(requesterID),
url.QueryEscape(requesterPassword),
url.QueryEscape(targetUserID))
req, err := http.NewRequest("POST", serverURL+"/user-public-key", strings.NewReader(formData))
if err != nil {
return "", fmt.Errorf("创建请求失败: %v", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("发送请求失败: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("获取公钥失败,状态码: %d", resp.StatusCode)
}
publicKeyPEM := make([]byte, 2048)
n, err := resp.Body.Read(publicKeyPEM)
if err != nil && err.Error() != "EOF" {
return "", fmt.Errorf("读取公钥失败: %v", err)
}
return string(publicKeyPEM[:n]), nil
}
// 客户端生成自己的RSA密钥对
func generateClientKeyPair() (*rsa.PrivateKey, string, error) {
// 生成RSA密钥对
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, "", fmt.Errorf("生成RSA密钥失败: %v", err)
}
// 序列化公钥为PEM格式
publicKeyBytes, err := x509.MarshalPKIXPublicKey(&privateKey.PublicKey)
if err != nil {
return nil, "", fmt.Errorf("序列化公钥失败: %v", err)
}
publicKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: publicKeyBytes,
})
return privateKey, string(publicKeyPEM), nil
}
// 将客户端公钥发送给服务器
func sendClientPublicKey(serverURL, userID, password, publicKey string) error {
client := &http.Client{}
formData := fmt.Sprintf("user_id=%s&password=%s&public_key=%s",
url.QueryEscape(userID),
url.QueryEscape(password),
url.QueryEscape(publicKey))
req, err := http.NewRequest("POST", serverURL+"/client-public-key", strings.NewReader(formData))
if err != nil {
return fmt.Errorf("创建请求失败: %v", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("发送请求失败: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("发送公钥失败,状态码: %d", resp.StatusCode)
}
return nil
}
func main() {
serverURL := "http://localhost:8080"
// 要加密的原始数据
plaintext := "Hello, this is a secret message from client!"
fmt.Printf("原始数据: %s\n", plaintext)
// 从服务端获取公钥(模拟用户登录)
userID := "user123" // 模拟用户ID
user := "john" // 模拟用户名
fmt.Println("正在从服务端获取公钥...")
publicKeyPEM, err := getServerPublicKey(serverURL, userID, user)
if err != nil {
fmt.Printf("获取公钥失败: %v\n", err)
return
}
fmt.Printf("获取公钥成功\n")
// 使用服务端公钥加密数据
fmt.Println("正在使用服务端公钥加密数据...")
encryptedData, encryptedKey, err := hybridEncryptWithServerKey(plaintext, publicKeyPEM)
if err != nil {
fmt.Printf("加密失败: %v\n", err)
return
}
fmt.Printf("加密成功!\n")
fmt.Printf("加密数据: %s\n", encryptedData)
fmt.Printf("加密密钥: %s\n", encryptedKey)
// 将加密数据发送到服务端进行解密
fmt.Println("正在向服务端发送加密数据...")
decryptedData, err := sendEncryptedData(serverURL, encryptedData, encryptedKey, userID)
if err != nil {
fmt.Printf("发送或解密失败: %v\n", err)
return
}
fmt.Printf("服务端解密结果: %s\n", decryptedData)
fmt.Println("混合加密通信演示完成!")
// 生成客户端自己的密钥对
_, clientPublicKey, err := generateClientKeyPair() // 忽略私钥,因为暂时只在演示中使用
if err != nil {
fmt.Printf("生成客户端密钥对失败: %v\n", err)
return
}
fmt.Printf("客户端密钥对生成成功\n")
// 先注册新用户,获取服务器生成的密钥对
userIDNew := "user1234" // 第二个用户ID
fmt.Println("正在注册新用户...")
_, err = getServerPublicKey(serverURL, userIDNew, "john2") // 忽略返回的公钥,因为我们有自己的公钥
if err != nil {
fmt.Printf("注册用户失败: %v\n", err)
return
}
fmt.Printf("用户注册成功\n")
// 将客户端公钥发送给服务器
fmt.Println("正在将客户端公钥发送给服务器...")
err = sendClientPublicKey(serverURL, userIDNew, "123456", clientPublicKey)
if err != nil {
fmt.Printf("发送客户端公钥失败: %v\n", err)
return
}
fmt.Printf("客户端公钥发送成功\n")
// 从服务端获取另一个用户的公钥(模拟用户登录)
fmt.Println("正在从服务端获取目标用户公钥...")
targetPublicKey, err := getTargetUserPublicKey(serverURL, userIDNew, "123456", "user123")
if err != nil {
fmt.Printf("获取目标用户公钥失败: %v\n", err)
return
}
fmt.Printf("获取目标用户公钥成功: %s\n", targetPublicKey)
// 使用目标用户公钥加密数据
fmt.Println("正在使用目标用户公钥加密数据...")
encryptedData2, encryptedKey2, err := hybridEncryptWithServerKey("Hello, this is a message from user2 to user1!", targetPublicKey)
if err != nil {
fmt.Printf("加密失败: %v\n", err)
return
}
fmt.Printf("加密成功!\n")
// 发送加密数据给目标用户
fmt.Println("正在向目标用户发送加密数据...")
result, err := sendEncryptedData(serverURL, encryptedData2, encryptedKey2, "user123")
if err != nil {
fmt.Printf("发送或解密失败: %v\n", err)
return
}
fmt.Printf("目标用户解密结果: %s\n", result)
}



浙公网安备 33010602011771号