package crypto import ( "crypto/hmac" "crypto/sha256" "encoding/base64" "fmt" "strconv" "strings" "time" ) // token = base64(user) "." expiryUnix "." base64(hmac) func SignSession(secret []byte, user string, expiry time.Time) string { payload := base64.RawURLEncoding.EncodeToString([]byte(user)) + "." + strconv.FormatInt(expiry.Unix(), 10) return payload + "." + sign(secret, payload) } func VerifySession(secret []byte, token string, now time.Time) (string, bool) { parts := strings.Split(token, ".") if len(parts) != 3 { return "", false } payload := parts[0] + "." + parts[1] if !hmac.Equal([]byte(parts[2]), []byte(sign(secret, payload))) { return "", false } exp, err := strconv.ParseInt(parts[1], 10, 64) if err != nil || now.Unix() > exp { return "", false } user, err := base64.RawURLEncoding.DecodeString(parts[0]) if err != nil { return "", false } return string(user), true } func sign(secret []byte, payload string) string { m := hmac.New(sha256.New, secret) fmt.Fprint(m, payload) return base64.RawURLEncoding.EncodeToString(m.Sum(nil)) }