usb-server/internal/token/token.go

61 lines
1.4 KiB
Go

package token
import (
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"fmt"
"strings"
)
const TokenLength = 32 // 32 bytes = 256 bits per token
// Tokens holds the 3 authentication tokens
type Tokens struct {
Token1 string `json:"token1"`
Token2 string `json:"token2"`
Token3 string `json:"token3"`
}
// Generate creates 3 cryptographically random tokens
func Generate() (*Tokens, error) {
t := &Tokens{}
var err error
t.Token1, err = randomToken()
if err != nil {
return nil, fmt.Errorf("generating token 1: %w", err)
}
t.Token2, err = randomToken()
if err != nil {
return nil, fmt.Errorf("generating token 2: %w", err)
}
t.Token3, err = randomToken()
if err != nil {
return nil, fmt.Errorf("generating token 3: %w", err)
}
return t, nil
}
// Hash computes the SHA256 hash of the 3 tokens combined
func (t *Tokens) Hash() string {
combined := strings.Join([]string{t.Token1, t.Token2, t.Token3}, ":")
sum := sha256.Sum256([]byte(combined))
return fmt.Sprintf("%x", sum)
}
// HashFromString computes the hash from a pre-combined token string
func HashFromTokens(token1, token2, token3 string) string {
t := &Tokens{Token1: token1, Token2: token2, Token3: token3}
return t.Hash()
}
func randomToken() (string, error) {
b := make([]byte, TokenLength)
if _, err := rand.Read(b); err != nil {
return "", err
}
return base64.URLEncoding.EncodeToString(b), nil
}