/
ratchetring.go
87 lines (78 loc) · 2.34 KB
/
ratchetring.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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package ratchet
// Ratchet ring:
// Three ratchets, one past, one current, one future.
//
// CounterPast := ((timeNow - StartDate)/duration)
// CounterCurrent := ((timeNow - StartDate)/duration)+1
// CounterFuture := ((timeNow - StartDate)/duration)+2
// Ring contains three ratchets, one current, one past, one future.
type Ring struct {
past, current, future *State
}
// NewRatchetRing returns a new, possibly filled, RatchetRing. pastStep is the expected
// counter value for the past value. Operates on a copy of ratchet.
func NewRatchetRing(ratchet *State, currentStep uint64) *Ring {
rr := new(Ring)
rr.set(ratchet, currentStep)
return rr
}
// set ring to given currentStep, using a copy of ratchet.
func (rr *Ring) set(ratchet *State, currentStep uint64) {
r := ratchet.Copy()
c := r.Counter()
if c > currentStep {
// Bad, this means we have a wrong time setting.
panic("github.com/JonathanLogan/cypherlock/ratchet: Time has reversed or overflown.")
}
if c < currentStep {
for i := c; i < currentStep; i = r.Counter() {
r.Step()
}
rr.past = r.Copy()
r.Step()
}
rr.current = r.Copy()
// Advance one more for future.
rr.future = rr.current.Copy().Step()
}
// StepTo steps to currentStep.
func (rr *Ring) StepTo(currentStep uint64) {
c := rr.current.Counter()
if c == currentStep {
return
}
if c == currentStep-1 {
rr.Step()
return
}
rr.set(rr.current, currentStep)
}
// Step executes one step for the ratchets.
func (rr *Ring) Step() {
rr.past = rr.current.Copy() // current is ALWAYS set.
rr.current = rr.future.Copy() // future is ALWAYS set.
rr.future.Step() // continue on future.
}
// Current returns a copy of the current ratchet state for marshalling.
// The past state will be lost in marshalling.
func (rr *Ring) Current() *State {
return rr.current.Copy()
}
// CurrentStep returns the counter of the current ratchet.
func (rr *Ring) CurrentStep() uint64 {
return rr.current.Counter()
}
// Find the ratchet state that matches the expected public key and return a copy, or nil
// if not found.
func (rr *Ring) Find(expect *[32]byte) *State {
if rr.current != nil && rr.current.PublicKey == *expect {
return rr.current.Copy()
}
if rr.past != nil && rr.past.PublicKey == *expect {
return rr.past.Copy()
}
if rr.future != nil && rr.future.PublicKey == *expect {
return rr.future.Copy()
}
return nil
}