Hunter0x7c7
2022-08-11 a82f9cb69f63aaeba40c024960deda7d75b9fece
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
47
48
49
50
51
52
53
54
55
56
57
58
package antireplay
 
import (
    "sync"
    "time"
 
    cuckoo "github.com/seiflotfy/cuckoofilter"
)
 
const replayFilterCapacity = 100000
 
// ReplayFilter checks for replay attacks.
type ReplayFilter struct {
    lock     sync.Mutex
    poolA    *cuckoo.Filter
    poolB    *cuckoo.Filter
    poolSwap bool
    lastSwap int64
    interval int64
}
 
// NewReplayFilter creates a new filter with specifying the expiration time interval in seconds.
func NewReplayFilter(interval int64) *ReplayFilter {
    filter := &ReplayFilter{}
    filter.interval = interval
    return filter
}
 
// Interval in second for expiration time for duplicate records.
func (filter *ReplayFilter) Interval() int64 {
    return filter.interval
}
 
// Check determines if there are duplicate records.
func (filter *ReplayFilter) Check(sum []byte) bool {
    filter.lock.Lock()
    defer filter.lock.Unlock()
 
    now := time.Now().Unix()
    if filter.lastSwap == 0 {
        filter.lastSwap = now
        filter.poolA = cuckoo.NewFilter(replayFilterCapacity)
        filter.poolB = cuckoo.NewFilter(replayFilterCapacity)
    }
 
    elapsed := now - filter.lastSwap
    if elapsed >= filter.Interval() {
        if filter.poolSwap {
            filter.poolA.Reset()
        } else {
            filter.poolB.Reset()
        }
        filter.poolSwap = !filter.poolSwap
        filter.lastSwap = now
    }
 
    return filter.poolA.InsertUnique(sum) && filter.poolB.InsertUnique(sum)
}