Files
proxy/gateway/core/security.go

75 lines
1.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package core
import (
"context"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/json"
"fmt"
g "proxy-server/gateway/globals"
"time"
)
type SecuredReq struct {
Content string `json:"content"`
Nonce string `json:"nonce"`
Timestamp int64 `json:"timestamp"`
}
func Decrypt[T any](req *SecuredReq, secret string) (resp *T, err error) {
// 解密请求
block, err := aes.NewCipher([]byte(secret))
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
var nonce = []byte(req.Nonce)
content, err := base64.StdEncoding.DecodeString(req.Content)
if err != nil {
return nil, err
}
var aad = []byte(fmt.Sprintf("%s:%d", req.Nonce, req.Timestamp))
bytes, err := gcm.Open(nil, nonce, content, aad)
if err != nil {
return nil, err
}
// 检查时间与 nonce 是否匹配
var duration = time.Now().UnixMilli() - req.Timestamp
if duration > 1000*60*5 { // 5分钟
return nil, fmt.Errorf("请求超时,当前时间:%d接收时间%d", time.Now().UnixMilli(), req.Timestamp)
}
result, err := g.Redis.Exists(context.Background(), req.Nonce).Result()
if err != nil {
return nil, err
}
if result > 0 {
return nil, fmt.Errorf("请求已被使用nonce%s", req.Nonce)
}
// 将 nonce 存入 redis设置过期时间为 5 分钟
err = g.Redis.Set(context.Background(), req.Nonce, 1, time.Minute*5).Err()
if err != nil {
return nil, err
}
// 返回解密后的数据
err = json.Unmarshal(bytes, &resp)
if err != nil {
return nil, err
}
return resp, nil
}