You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

95 lines
2.6 KiB

package idgen
import (
cryptorand "crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"math/big"
"sync"
)
// Generator handles the generation of various IDs
type Generator struct {
charsetMu sync.RWMutex
charset string
}
// NewGenerator creates a new ID generator with default settings
func NewGenerator() *Generator {
return &Generator{
charset: "0123456789ABCDEFGHJKLMNPQRSTVWXYZ",
}
}
// SetCharset allows customizing the character set used for ID generation
func (g *Generator) SetCharset(charset string) {
g.charsetMu.Lock()
defer g.charsetMu.Unlock()
g.charset = charset
}
// GenerateMachineID generates a new machine ID with the format auth0|user_XX[unique_id]
func (g *Generator) GenerateMachineID() (string, error) {
prefix := "auth0|user_"
// Generate random sequence number between 0-99
seqNum, err := cryptorand.Int(cryptorand.Reader, big.NewInt(100))
if err != nil {
return "", fmt.Errorf("failed to generate sequence number: %w", err)
}
sequence := fmt.Sprintf("%02d", seqNum.Int64())
uniqueID, err := g.generateUniqueID(23)
if err != nil {
return "", fmt.Errorf("failed to generate unique ID: %w", err)
}
fullID := prefix + sequence + uniqueID
return hex.EncodeToString([]byte(fullID)), nil
}
// GenerateMacMachineID generates a new MAC machine ID using SHA-256
func (g *Generator) GenerateMacMachineID() (string, error) {
data := make([]byte, 32)
if _, err := cryptorand.Read(data); err != nil {
return "", fmt.Errorf("failed to generate random data: %w", err)
}
hash := sha256.Sum256(data)
return hex.EncodeToString(hash[:]), nil
}
// GenerateDeviceID generates a new device ID in UUID v4 format
func (g *Generator) GenerateDeviceID() (string, error) {
uuid := make([]byte, 16)
if _, err := cryptorand.Read(uuid); err != nil {
return "", fmt.Errorf("failed to generate UUID: %w", err)
}
// Set version (4) and variant (2) bits according to RFC 4122
uuid[6] = (uuid[6] & 0x0f) | 0x40
uuid[8] = (uuid[8] & 0x3f) | 0x80
return fmt.Sprintf("%x-%x-%x-%x-%x",
uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:16]), nil
}
// generateUniqueID generates a random string of specified length using the configured charset
func (g *Generator) generateUniqueID(length int) (string, error) {
g.charsetMu.RLock()
defer g.charsetMu.RUnlock()
result := make([]byte, length)
max := big.NewInt(int64(len(g.charset)))
for i := range result {
randNum, err := cryptorand.Int(cryptorand.Reader, max)
if err != nil {
return "", fmt.Errorf("failed to generate random number: %w", err)
}
result[i] = g.charset[randNum.Int64()]
}
return string(result), nil
}