-
Notifications
You must be signed in to change notification settings - Fork 18
/
saltpool.go
46 lines (40 loc) · 1.07 KB
/
saltpool.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package ss2022
import "time"
// SaltPool stores salts for [retention, 2*retention) to protect against replay attacks
// during the replay window.
//
// SaltPool is not safe for concurrent use.
type SaltPool[T comparable] struct {
pool map[T]time.Time
retention time.Duration
lastClean time.Time
}
// clean removes expired salts from the pool.
func (p *SaltPool[T]) clean() {
if now := time.Now(); now.Sub(p.lastClean) > p.retention {
for salt, added := range p.pool {
if now.Sub(added) > p.retention {
delete(p.pool, salt)
}
}
p.lastClean = now
}
}
// Check returns whether the given salt is valid (not in the pool).
func (p *SaltPool[T]) Check(salt T) bool {
p.clean()
_, ok := p.pool[salt]
return !ok
}
// Add adds the given salt to the pool.
func (p *SaltPool[T]) Add(salt T) {
p.pool[salt] = time.Now()
}
// NewSaltPool returns a new SaltPool with the given retention.
func NewSaltPool[T comparable](retention time.Duration) *SaltPool[T] {
return &SaltPool[T]{
pool: make(map[T]time.Time),
retention: retention,
lastClean: time.Now(),
}
}