-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdynamic_key.go
138 lines (113 loc) · 3.49 KB
/
dynamic_key.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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package searchparty
import (
"bytes"
"encoding/base64"
"io"
"time"
"github.com/denysvitali/searchparty-keys"
"github.com/denysvitali/searchparty-go/model"
)
const (
primaryRotationMinutes = 15
secondaryRotationHours = 24
)
type DynamicKey struct {
beacon *searchpartykeys.Beacon
}
func (d *DynamicKey) ID() string {
return base64.StdEncoding.EncodeToString(sha256Hash(d.beacon.PublicKey.Key.Data)[:8])
}
func (d *DynamicKey) Type() string {
return "dynamic"
}
func (d *DynamicKey) KeyInfo() model.KeyInfo {
return model.KeyInfo{
Model: d.beacon.Model,
PairingDate: d.beacon.PairingDate,
Identifier: d.beacon.Identifier,
StableIdentifier: d.beacon.StableIdentifier[0],
}
}
var _ model.MainKey = &DynamicKey{}
const (
primaryRotation = 15 * time.Minute
secondaryRotation = 24 * time.Hour
)
func CalculateKeyRotation(from, to, initialTime time.Time, rotationDuration time.Duration) (int, int) {
realFrom := from.Truncate(rotationDuration)
elapsedFrom := realFrom.Sub(initialTime)
// Calculate the elapsed time from the initial time to the "to" time
elapsedTo := to.Sub(initialTime)
// Calculate the number of amountKeys at each time
rotationsFrom := int(elapsedFrom / rotationDuration)
rotationsTo := int(elapsedTo / rotationDuration)
// The number of amountKeys between "from" and "to"
amountKeys := rotationsTo - rotationsFrom
if amountKeys == 0 {
amountKeys = 1
}
// Calculate the offset from the initial time to the "to" time
offset := elapsedFrom / rotationDuration
if offset < 0 {
offset = 0
}
return amountKeys, int(offset)
}
func (d *DynamicKey) GetSubKeys(from time.Time, to time.Time, lostAt time.Time) (subKeys []model.SubKey, err error) {
amountPrimary, offsetPrimary := CalculateKeyRotation(lostAt, to, d.beacon.PairingDate, primaryRotation)
amountSecondary, offsetSecondary := CalculateKeyRotation(lostAt, to, d.beacon.PairingDate, secondaryRotation)
logger.Debugf("Primary: %d, Secondary: %d", amountPrimary, amountSecondary)
logger.Debugf("Primary offset: %d, Secondary offset: %d", offsetPrimary, offsetSecondary)
primaryKeys, err := searchpartykeys.CalculateAdvertisementKeys(
d.beacon.PrivateKey.Key.Data,
d.beacon.SharedSecret.Key.Data,
amountPrimary,
offsetPrimary+2,
)
if err != nil {
return nil, err
}
secondaryKeys, err := searchpartykeys.CalculateAdvertisementKeys(
d.beacon.PrivateKey.Key.Data,
d.beacon.SecondarySharedSecret.Key.Data,
amountSecondary,
offsetSecondary+2,
)
if err != nil {
return nil, err
}
for _, p := range primaryKeys {
logger.Debugf("Adding primary key %s", base64.StdEncoding.EncodeToString(p.HashedAdvKey()))
subKeys = append(subKeys, model.SubKey{
AdvKey: p.AdvKeyBytes(),
HashedAdvKey: p.HashedAdvKey(),
PrivateKey: p.PrivateKey(),
Type: model.Primary,
MainKey: model.MainKey(d),
})
}
for _, s := range secondaryKeys {
logger.Debugf("Adding secondary key %s", base64.StdEncoding.EncodeToString(s.HashedAdvKey()))
subKeys = append(subKeys, model.SubKey{
AdvKey: s.AdvKeyBytes(),
HashedAdvKey: s.HashedAdvKey(),
PrivateKey: s.PrivateKey(),
Type: model.Secondary,
MainKey: model.MainKey(d),
})
}
return
}
func LoadDynamicKey(reader io.ReadSeeker, key []byte) (model.MainKey, error) {
d, err := searchpartykeys.Decrypt(reader, key)
if err != nil {
return nil, err
}
decoded, err := searchpartykeys.Decode(bytes.NewReader(d))
if err != nil {
return nil, err
}
return &DynamicKey{
beacon: decoded,
}, nil
}