63 lines
1.5 KiB
Go
63 lines
1.5 KiB
Go
|
|
package pow
|
||
|
|
|
||
|
|
import (
|
||
|
|
"crypto/rand"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Generator handles creation of PoW challenges with HMAC signing
|
||
|
|
type Generator struct {
|
||
|
|
config *Config
|
||
|
|
}
|
||
|
|
|
||
|
|
// GenerateOption represents a functional option for challenge generation
|
||
|
|
type generateOption func(*Challenge)
|
||
|
|
|
||
|
|
// WithDifficulty sets custom difficulty for the challenge
|
||
|
|
func WithDifficulty(difficulty int) generateOption {
|
||
|
|
return func(c *Challenge) {
|
||
|
|
c.Difficulty = difficulty
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewGenerator creates a new challenge generator
|
||
|
|
func NewGenerator(config *Config) *Generator {
|
||
|
|
return &Generator{
|
||
|
|
config: config,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// GenerateChallenge creates a new HMAC-signed PoW challenge
|
||
|
|
func (g *Generator) GenerateChallenge(opts ...generateOption) (*Challenge, error) {
|
||
|
|
// Create challenge with defaults (no random data yet)
|
||
|
|
challenge := &Challenge{
|
||
|
|
Timestamp: time.Now().Unix(),
|
||
|
|
Difficulty: g.config.DefaultDifficulty,
|
||
|
|
Resource: g.config.Resource,
|
||
|
|
}
|
||
|
|
|
||
|
|
// Apply options
|
||
|
|
for _, opt := range opts {
|
||
|
|
opt(challenge)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate difficulty bounds
|
||
|
|
if challenge.Difficulty < g.config.MinDifficulty || challenge.Difficulty > g.config.MaxDifficulty {
|
||
|
|
return nil, ErrInvalidDifficulty
|
||
|
|
}
|
||
|
|
|
||
|
|
// Generate cryptographic random data
|
||
|
|
challenge.Random = g.generateRandom(g.config.RandomBytes)
|
||
|
|
|
||
|
|
// Sign the challenge with HMAC
|
||
|
|
challenge.Sign(g.config.HMACSecret)
|
||
|
|
return challenge, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// generateRandom creates cryptographic random bytes
|
||
|
|
func (g *Generator) generateRandom(length int) []byte {
|
||
|
|
bytes := make([]byte, length)
|
||
|
|
rand.Read(bytes)
|
||
|
|
return bytes
|
||
|
|
}
|