golang在gin在中间键 中实现Aes+ecc加密
介绍
在Go语言中,使用Gin框架实现AES加密和ECC(Elliptic Curve Cryptography)加密可以为Web应用提供强大的数据安全保护。AES (Advanced Encryption Standard) 是一种广泛使用的对称加密算法,它用相同的密钥进行数据的加密和解密。而ECC是一种使用椭圆曲线数学来构建密钥的非对称加密技术,通常用于创建加密密钥和数字签名,它提供了与RSA相同级别的安全性,但使用较短的密钥长度,从而提高了效率。
代码解析中间价解析流程
return func(c *gin.Context) {
// 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localStorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
name := c.Request.Header.Get("i-name")
token := c.Request.Header.Get("i-token")
encrypt := c.Request.Header.Get("p-encrypt")
if token == "" {
response.FailWithDetailed(gin.H{"reload": true}, "未登录或非法访问", c)
c.Abort()
return
}
config, err := utils.FindUrlConfigByName(name)
...
data, ok := config.UnlockAES(token)
...
//开始解密 encrypt
signatureHex, err := hex.DecodeString(encrypt)
...
if !config.UnlockECC(data, string(signatureHex)) {
...
}
//encrypt sign
ok, err = ParseJSONAndCheckTimestamp(data)
...
c.Set("params", data)
c.Next()
}
分成 UnlockAES DecodeString UnlockECC ParseJSONAndCheckTimestamp 四步
UnlockAES
判断加密啊数据是否可会被串改(AEAD) 这个概念
func (urlConfig *UrlConfig) UnlockAES(data string) ([]byte, bool) {
cipherText, err := base64.StdEncoding.DecodeString(data)
if err != nil {
return nil, false
}
....
for _, key := range keys {
//使用当前密钥创建一个新的AES加密块block。如果创建失败(例如,如果密钥长度不符合AES要求),则跳过当前密钥,继续尝试下一个密钥
block, err := aes.NewCipher([]byte(key))
if err != nil {
continue
}
//这个会寻找这个硬件是否支持ACe
gcm, err := cipher.NewGCM(block)
if err != nil {
continue
}
//去判断文本数量,也就是说加密之前是否一致.
nonceSize := gcm.NonceSize()
if len(cipherText) < nonceSize {
continue
}
nonce, cipherText := cipherText[:nonceSize], cipherText[nonceSize:]
result, err := gcm.Open(nil, nonce, cipherText, nil)
if err != nil {
continue
}
return result, true
}
return nil, false
}
DecodeString
从十六进制转成常用的string
UnlockECC
func (urlConfig *UrlConfig) UnlockECC(data []byte, sign string) bool {
var keys = []string{urlConfig.PublicKeyRawA, urlConfig.PublicKeyRawB}
for _, key := range keys {
publicKey, err := checkPublicKey(key)
--》
pubBytes, err := base64.StdEncoding.DecodeString(encodedPubKey)
if err != nil {
return nil, err
}
publicKey, err := x509.ParsePKIXPublicKey(pubBytes)
if err != nil {
return nil, err
}
ecPublicKey, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
return nil, fmt.Errorf("不是有效的 ECDSA 公钥")
}
return ecPublicKey, nil
--》
if err != nil {
// TODO error
//log.Fatal("公钥检查失败: ", err)
continue
}
//验证数据是否正确
if VerifySignature(publicKey, data, []byte(sign)) {
return true
}
-->
func VerifySignature(publicKey *ecdsa.PublicKey, data, signature []byte) bool {
hash := sha256.Sum256(data)
return ecdsa.VerifyASN1(publicKey, hash[:], signature)
}
-->
}
return false
}
ParseJSONAndCheckTimestamp 事件处理
// ParseJSONAndCheckTimestamp 解析 JSON 字符串到 map,并检查时间戳
func ParseJSONAndCheckTimestamp(jsonStr []byte) (bool, error) {
var dataMap map[string]interface{}
err := json.Unmarshal(jsonStr, &dataMap)
if err != nil {
return false, err
}
timestampStr, ok := dataMap["timestamp"]
if !ok {
return false, nil // 或者返回一个错误,表示没有找到 timestamp
}
timestampString, ok := timestampStr.(float64)
if !ok {
return false, err
}
timestamp := time.Unix(int64(timestampString), 0)
now := time.Now()
// 检查 timestamp 是否在当前时间前后 5 分钟内
diff := now.Sub(timestamp)
if diff < -5*time.Minute || diff > 5*time.Minute {
return false, nil
}
return true, nil
}
总结
这样子就可以知道数据有没有被中间人给串改
转载自:https://juejin.cn/post/7337519776794869769