ZBLOG

golang 编写 http AES 加密代理

下面是一个简单的 golang 编写的 http AES 加密代理示例代码:

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "encoding/base64"
    "fmt"
    "io"
    "log"
    "net/http"
    "net/url"
)

const key = "1234567890123456" // 16字节的AES加密密钥

func encrypt(text string) string {
    block, err := aes.NewCipher([]byte(key))
    if err != nil {
        panic(err)
    }
    plaintext := []byte(text)
    ciphertext := make([]byte, aes.BlockSize+len(plaintext))
    iv := ciphertext[:aes.BlockSize]
    if _, err := io.ReadFull(rand.Reader, iv); err != nil {
        panic(err)
    }
    stream := cipher.NewCTR(block, iv)
    stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
    return base64.URLEncoding.EncodeToString(ciphertext)
}

func decrypt(text string) (string, error) {
    ciphertext, err := base64.URLEncoding.DecodeString(text)
    if err != nil {
        return "", err
    }
    block, err := aes.NewCipher([]byte(key))
    if err != nil {
        return "", err
    }
    if len(ciphertext) < aes.BlockSize {
        return "", fmt.Errorf("ciphertext too short")
    }
    iv := ciphertext[:aes.BlockSize]
    ciphertext = ciphertext[aes.BlockSize:]
    stream := cipher.NewCTR(block, iv)
    stream.XORKeyStream(ciphertext, ciphertext)
    return string(ciphertext), nil
}

func handleProxy(w http.ResponseWriter, r *http.Request) {
    targetUrl := r.URL.Query().Get("url")
    u, err := url.Parse(targetUrl)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    req, err := http.NewRequest(r.Method, u.String(), r.Body)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    defer resp.Body.Close()
    w.Header().Set("Content-Type", "application/json")
    io.Copy(w, resp.Body)
}

func handleEncryptProxy(w http.ResponseWriter, r *http.Request) {
    targetUrl := r.URL.Query().Get("url")
    u, err := url.Parse(targetUrl)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    req, err := http.NewRequest(r.Method, u.String(), r.Body)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    defer resp.Body.Close()
    w.Header().Set("Content-Type", "application/json")
    var encryptedBody string
    io.Copy(&encryptedBody, resp.Body)
    fmt.Fprintf(w, `{"data": "%s"}`, encrypt(encryptedBody))
}

func main() {
    http.HandleFunc("/proxy/", handleProxy)
    http.HandleFunc("/encrypt-proxy/", handleEncryptProxy)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

这段代码实现了两个路由:

  1. /proxy/ :直接代理访问目标地址,并返回原始响应内容。
  2. /encrypt-proxy/ :代理访问目标地址,加密响应内容后返回。

其中,AES 加密使用的是 CTR 模式。在 encrypt 函数中,先生成一个随机的 16 字节的初始向量(IV),再用 AES 加密算法对原始数据进行加密,并将 IV 和密文拼接成一个字节数组,并使用 base64 编码转换成字符串返回。在 decrypt 函数中,先将密文字符串解码为字节数组,然后从中提取出 IV 和密文部分,再用 AES 解密算法对密文进行解密,最后返回解密出来的明文字符串。

需要注意的是,由于原始的响应内容可能包含二进制数据,在将响应内容加密后,需要将加密后的字节数组转换成字符串类型返回给客户端。在 handleEncryptProxy 中,我使用了 fmt.Fprintf 来格式化输出 JSON 响应结果,但实际情况下,这种方式可能不太适合复杂的 JSON 结构,需要根据实际情况选择更适合的方式。

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=1069

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?