Files

113 lines
3.2 KiB
Go

package util
import (
"crypto/sha256"
"crypto/subtle"
"encoding/base64"
"encoding/hex"
"fmt"
"strings"
)
// SHA256Hex returns the hex-encoded SHA-256 hash of a string.
func SHA256Hex(input string) string {
h := sha256.Sum256([]byte(input))
return hex.EncodeToString(h[:])
}
// IsTokenValid checks a plaintext input against a plaintext secret.
// Per review-resolution #24: SHA-256 both sides, then constant-time compare.
func IsTokenValid(input, secret string) bool {
if secret == "" || input == "" {
return false
}
inputHash := SHA256Hex(input)
secretHash := SHA256Hex(secret)
return subtle.ConstantTimeCompare([]byte(inputHash), []byte(secretHash)) == 1
}
// IsGrantTokenValid checks a plaintext input against a stored SHA-256 hash.
// Per review-resolution #24: hash the input, then constant-time compare with stored hash.
func IsGrantTokenValid(input, storedHash string) bool {
if input == "" || storedHash == "" {
return false
}
inputHash := SHA256Hex(input)
return subtle.ConstantTimeCompare([]byte(inputHash), []byte(storedHash)) == 1
}
// RandomToken generates a 24-byte random base64url token (no padding).
func RandomToken() (string, error) {
var buf [24]byte
if _, err := readRandom(buf[:]); err != nil {
return "", err
}
return base64.RawURLEncoding.EncodeToString(buf[:]), nil
}
// EncodeBase64URL encodes to standard base64 URL encoding with padding.
func EncodeBase64URL(input string) string {
return base64.URLEncoding.EncodeToString([]byte(input))
}
// EncodeBase64RawURL encodes to base64 URL encoding without padding.
func EncodeBase64RawURL(input string) string {
return base64.RawURLEncoding.EncodeToString([]byte(input))
}
// EncodeBase64Std encodes to standard base64 encoding.
func EncodeBase64Std(input string) string {
return base64.StdEncoding.EncodeToString([]byte(input))
}
// DecodeBase64Std decodes standard base64.
func DecodeBase64Std(s string) (string, error) {
b, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return "", err
}
return string(b), nil
}
// DecodeBase64URL decodes URL-safe base64 with padding.
func DecodeBase64URL(s string) (string, error) {
b, err := base64.URLEncoding.DecodeString(s)
if err != nil {
return "", err
}
return string(b), nil
}
// DecodeBase64RawURL decodes URL-safe base64 without padding.
// Per review-resolution #15: used for SSR.
func DecodeBase64RawURL(s string) (string, error) {
b, err := base64.RawURLEncoding.DecodeString(s)
if err != nil {
return "", err
}
return string(b), nil
}
// DecodeBase64Auto tries Std first, then RawURL — per review-resolution #15.
func DecodeBase64Auto(s string) (string, error) {
s = strings.TrimSpace(s)
// Try standard base64 first
if b, err := base64.StdEncoding.DecodeString(s); err == nil {
return string(b), nil
}
// Try raw URL encoding (no padding)
if b, err := base64.RawURLEncoding.DecodeString(s); err == nil {
return string(b), nil
}
// Try URL encoding with padding
if b, err := base64.URLEncoding.DecodeString(s); err == nil {
return string(b), nil
}
return "", fmt.Errorf("invalid base64")
}
// Base64Utf8 encodes a UTF-8 string to standard base64.
func Base64Utf8(input string) string {
return base64.StdEncoding.EncodeToString([]byte(input))
}