61 lines
1.4 KiB
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
|
|
}
|