github.com/cloudreve/Cloudreve/v3@v3.0.0-20240224133659-3edb00a6484c/pkg/auth/hmac.go (about) 1 package auth 2 3 import ( 4 "crypto/hmac" 5 "crypto/sha256" 6 "encoding/base64" 7 "io" 8 "strconv" 9 "strings" 10 "time" 11 ) 12 13 // HMACAuth HMAC算法鉴权 14 type HMACAuth struct { 15 SecretKey []byte 16 } 17 18 // Sign 对给定Body生成expires后失效的签名,expires为过期时间戳, 19 // 填写为0表示不限制有效期 20 func (auth HMACAuth) Sign(body string, expires int64) string { 21 h := hmac.New(sha256.New, auth.SecretKey) 22 expireTimeStamp := strconv.FormatInt(expires, 10) 23 _, err := io.WriteString(h, body+":"+expireTimeStamp) 24 if err != nil { 25 return "" 26 } 27 28 return base64.URLEncoding.EncodeToString(h.Sum(nil)) + ":" + expireTimeStamp 29 } 30 31 // Check 对给定Body和Sign进行鉴权,包括对expires的检查 32 func (auth HMACAuth) Check(body string, sign string) error { 33 signSlice := strings.Split(sign, ":") 34 // 如果未携带expires字段 35 if signSlice[len(signSlice)-1] == "" { 36 return ErrExpiresMissing 37 } 38 39 // 验证是否过期 40 expires, err := strconv.ParseInt(signSlice[len(signSlice)-1], 10, 64) 41 if err != nil { 42 return ErrAuthFailed.WithError(err) 43 } 44 // 如果签名过期 45 if expires < time.Now().Unix() && expires != 0 { 46 return ErrExpired 47 } 48 49 // 验证签名 50 if auth.Sign(body, expires) != sign { 51 return ErrAuthFailed 52 } 53 return nil 54 }