| package sign | |
| import ( | |
| "crypto/hmac" | |
| "crypto/sha256" | |
| "encoding/base64" | |
| "io" | |
| "strconv" | |
| "strings" | |
| "time" | |
| ) | |
| type HMACSign struct { | |
| SecretKey []byte | |
| } | |
| func (s HMACSign) Sign(data string, expire int64) string { | |
| h := hmac.New(sha256.New, s.SecretKey) | |
| expireTimeStamp := strconv.FormatInt(expire, 10) | |
| _, err := io.WriteString(h, data+":"+expireTimeStamp) | |
| if err != nil { | |
| return "" | |
| } | |
| return base64.URLEncoding.EncodeToString(h.Sum(nil)) + ":" + expireTimeStamp | |
| } | |
| func (s HMACSign) Verify(data, sign string) error { | |
| signSlice := strings.Split(sign, ":") | |
| // check whether contains expire time | |
| if signSlice[len(signSlice)-1] == "" { | |
| return ErrExpireMissing | |
| } | |
| // check whether expire time is expired | |
| expires, err := strconv.ParseInt(signSlice[len(signSlice)-1], 10, 64) | |
| if err != nil { | |
| return ErrExpireInvalid | |
| } | |
| // if expire time is expired, return error | |
| if expires < time.Now().Unix() && expires != 0 { | |
| return ErrSignExpired | |
| } | |
| // verify sign | |
| if s.Sign(data, expires) != sign { | |
| return ErrSignInvalid | |
| } | |
| return nil | |
| } | |
| func NewHMACSign(secret []byte) Sign { | |
| return HMACSign{SecretKey: secret} | |
| } | |