Go实现Rsa+Aes混合加密、端到端加密

只是个示例,用户的数据在内存

image

目前服务器给客户端回消息是没加密的、若要加密,就让客户端也生成自己的私钥,公钥。

然后把自己的公钥传到服务器,服务器回复用客户端的公钥进行加密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)
}

image
image

posted @ 2025-12-30 16:07  朝阳1  阅读(5)  评论(0)    收藏  举报