likes
comments
collection
share

golang在gin在中间键 中实现Aes+ecc加密

作者站长头像
站长
· 阅读数 35

介绍

在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
评论
请登录