package auth import ( "crypto/rand" "crypto/sha256" "encoding/base64" "encoding/hex" "errors" "strings" ) const tokenPrefix = "tk_" var ErrInvalidTokenFormat = errors.New("invalid token format") type Generator struct{} func NewGenerator() *Generator { return &Generator{} } func (Generator) Generate() (raw, hash string, err error) { buf := make([]byte, 32) if _, err := rand.Read(buf); err != nil { return "", "", err } raw = tokenPrefix + base64.RawURLEncoding.EncodeToString(buf) hash = HashToken(raw) return raw, hash, nil } func HashToken(raw string) string { sum := sha256.Sum256([]byte(raw)) return hex.EncodeToString(sum[:]) } func ValidateFormat(raw string) error { if !strings.HasPrefix(raw, tokenPrefix) { return ErrInvalidTokenFormat } if len(raw) < len(tokenPrefix)+20 { return ErrInvalidTokenFormat } return nil }