2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2019 Sergey Matveev <stargrave@stargrave.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, version 3 of the License.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 "golang.org/x/crypto/blake2b"
36 type PeerID [IDSize]byte
38 func (id PeerID) String() string {
39 return base64.RawStdEncoding.EncodeToString(id[:])
42 func (id PeerID) MarshalJSON() ([]byte, error) {
43 return []byte(`"` + id.String() + `"`), nil
46 type MACAndTimeSync struct {
52 type MACCache struct {
53 cache map[PeerID]*MACAndTimeSync
57 func NewMACCache() *MACCache {
58 return &MACCache{cache: make(map[PeerID]*MACAndTimeSync)}
61 // Remove disappeared keys, add missing ones with initialized MACs.
62 func (mc *MACCache) Update(peers *map[PeerID]*PeerConf) {
64 for pid := range mc.cache {
65 if _, exists := (*peers)[pid]; !exists {
66 log.Println("Cleaning key:", pid)
70 for pid, pc := range *peers {
71 if _, exists := mc.cache[pid]; exists {
72 mc.cache[pid].ts = pc.TimeSync
74 log.Println("Adding key", pid)
75 mac, err := blake2b.New256(pid[:])
79 mc.cache[pid] = &MACAndTimeSync{
88 // If timeSync > 0, then XOR timestamp with the data.
89 func AddTimeSync(ts int, data []byte) {
93 buf := make([]byte, 8)
94 binary.BigEndian.PutUint64(buf, uint64(time.Now().Unix()/int64(ts)*int64(ts)))
95 for i := 0; i < 8; i++ {
100 // Try to find peer's identity (that equals to MAC)
101 // by taking first blocksize sized bytes from data at the beginning
102 // as plaintext and last bytes as cyphertext.
103 func (mc *MACCache) Find(data []byte) *PeerID {
107 buf := make([]byte, 8)
108 sum := make([]byte, 32)
110 for pid, mt := range mc.cache {
112 AddTimeSync(mt.ts, buf)
118 if subtle.ConstantTimeCompare(sum[len(sum)-8:], data[len(data)-8:]) == 1 {