go实现laravel的encrypt()和decrypt()方法

gedongdong · · 488 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

最近项目准备从laravel迁移到go,但是为了最小范围的影响,只能一部分一部分的慢慢迁移,所以就会涉及到兼容laravel加密解密的问题。现将代码记录到这里,以备后续查看。 ### 加密方式 AES-256-CBC ### 密钥格式 支持常规32位字符串密钥,也支持base64格式的密钥 ### 代码 ```golang package main import ( "crypto/hmac" "crypto/rand" "crypto/sha256" "encoding/base64" "encoding/hex" "encoding/json" "errors" "fmt" "os" "strings" "github.com/forgoer/openssl" "github.com/techoner/gophp/serialize" ) //支持两种key格式 //const EncrypterKey = "9bcv6ioh0s51pjlaw2d7u8rt3fyqnxge" //const EncrypterKey = "base64:UXn0F1XSd2peV2M6mPtEWfeKPVlf5p+j5NqCd3+4/AA=" //加密 func Encrypt(value string) (string, error) { iv := make([]byte, 16) _, err := rand.Read(iv) if err != nil { return "", err } //反序列化 message, err := serialize.Marshal(value) if err != nil { return "", err } key := getKey() //加密value res, err := openssl.AesCBCEncrypt(message, []byte(key), iv, openssl.PKCS7_PADDING) if err != nil { return "", err } //base64加密 resVal := base64.StdEncoding.EncodeToString(res) resIv := base64.StdEncoding.EncodeToString(iv) //生成mac值 data := resIv + resVal mac := computeHmacSha256(data, key) //构造ticket结构 ticket := make(map[string]interface{}) ticket["iv"] = resIv ticket["mac"] = mac ticket["value"] = resVal //json序列化 resTicket, err := json.Marshal(ticket) if err != nil { return "", err } //base64加密ticket ticketR := base64.StdEncoding.EncodeToString(resTicket) return ticketR, nil } //解密 func Decrypt(value string) (string, error) { //base64解密 token, err := base64.StdEncoding.DecodeString(value) fmt.Println("token---", string(token)) if err != nil { return "", err } //json反序列化 tokenJson := make(map[string]string) err = json.Unmarshal(token, &tokenJson) fmt.Println("tokenJson---", tokenJson) if err != nil { return "", err } tokenJsonIv, okIv := tokenJson["iv"] tokenJsonValue, okValue := tokenJson["value"] tokenJsonMac, okMac := tokenJson["mac"] if !okIv || !okValue || !okMac { return "", errors.New("value is not full") } key := getKey() //mac检查,防止数据篡改 data := tokenJsonIv + tokenJsonValue check := checkMAC(data, tokenJsonMac, key) if !check { return "", errors.New("mac valid failed") } //base64解密iv和value tokenIv, err := base64.StdEncoding.DecodeString(tokenJsonIv) if err != nil { return "", err } tokenValue, err := base64.StdEncoding.DecodeString(tokenJsonValue) if err != nil { return "", err } //aes解密value dst, err := openssl.AesCBCDecrypt(tokenValue, []byte(key), tokenIv, openssl.PKCS7_PADDING) fmt.Println("dst", string(dst)) if err != nil { return "", err } //反序列化 res, err := serialize.UnMarshal(dst) if err != nil { return "", err } return res.(string), nil } //比较预期的hash和实际的hash func checkMAC(message, msgMac, secret string) bool { expectedMAC := computeHmacSha256(message, secret) fmt.Println(expectedMAC, msgMac) return hmac.Equal([]byte(expectedMAC), []byte(msgMac)) } //计算mac值 func computeHmacSha256(message string, secret string) string { key := []byte(secret) h := hmac.New(sha256.New, key) h.Write([]byte(message)) sha := hex.EncodeToString(h.Sum(nil)) return sha } //处理密钥 func getKey() string { appKey := os.Getenv("APP_KEY") if strings.HasPrefix(appKey, "base64:") { split := appKey[7:] if key, err := base64.StdEncoding.DecodeString(split); err == nil { return string(key) } return split } return appKey } ```

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

488 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传