aboutsummaryrefslogtreecommitdiff
path: root/src/gnunet/service/dht/path
diff options
context:
space:
mode:
authorBernd Fix <brf@hoi-polloi.org>2022-08-21 16:40:12 +0200
committerBernd Fix <brf@hoi-polloi.org>2022-08-21 16:40:12 +0200
commit21d7292dbd062ff11194fdc235a3d54830d7ba57 (patch)
tree75b5b1c620f4ac9cb722330c6bd9cbcdb24c7700 /src/gnunet/service/dht/path
parent5b03f7567ad8242cc87924c3920dfc04420365ef (diff)
downloadgnunet-go-21d7292dbd062ff11194fdc235a3d54830d7ba57.tar.gz
gnunet-go-21d7292dbd062ff11194fdc235a3d54830d7ba57.zip
Integration test: bug fixes 1st round.
Diffstat (limited to 'src/gnunet/service/dht/path')
-rw-r--r--src/gnunet/service/dht/path/elements.go38
-rw-r--r--src/gnunet/service/dht/path/elements_test.go71
-rw-r--r--src/gnunet/service/dht/path/handling.go146
3 files changed, 164 insertions, 91 deletions
diff --git a/src/gnunet/service/dht/path/elements.go b/src/gnunet/service/dht/path/elements.go
index 1384469..4fb03c1 100644
--- a/src/gnunet/service/dht/path/elements.go
+++ b/src/gnunet/service/dht/path/elements.go
@@ -36,6 +36,7 @@ var (
36) 36)
37 37
38//---------------------------------------------------------------------- 38//----------------------------------------------------------------------
39
39// Entry is an element of the path list 40// Entry is an element of the path list
40type Entry struct { 41type Entry struct {
41 Signature *util.PeerSignature // path element signature 42 Signature *util.PeerSignature // path element signature
@@ -57,9 +58,9 @@ func (e *Entry) String() string {
57 return fmt.Sprintf("(%s,%s)", e.Signer.String(), s) 58 return fmt.Sprintf("(%s,%s)", e.Signer.String(), s)
58} 59}
59 60
60//---------------------------------------------------------------------- 61// ----------------------------------------------------------------------
61// shared path element data across types 62// shared path element data across types
62type elementData struct { 63type _ElementData struct {
63 Expire util.AbsoluteTime // expiration date 64 Expire util.AbsoluteTime // expiration date
64 BlockHash *crypto.HashCode // block hash 65 BlockHash *crypto.HashCode // block hash
65 PeerPredecessor *util.PeerID // predecessor peer 66 PeerPredecessor *util.PeerID // predecessor peer
@@ -67,41 +68,48 @@ type elementData struct {
67} 68}
68 69
69// helper type for signature creation/verification 70// helper type for signature creation/verification
70type elementSignedData struct { 71type _SignedData struct {
71 Size uint16 `order:"big"` // size of signed data 72 Purpose *crypto.SignaturePurpose // signature purpose
72 Purpose uint16 `order:"big"` // signature purpose (SIG_DHT_HOP) 73 Elem *_ElementData // path element data
73 Elem *elementData `` // path element data
74} 74}
75 75
76//---------------------------------------------------------------------- 76// ----------------------------------------------------------------------
77// Element is the full-fledged data assembly for a path element in 77// Element is the full-fledged data assembly for a path element in
78// PUT/GET pathes. It is assembled programatically (on generation[1] and 78// PUT/GET pathes. It is assembled programatically (on generation[1] and
79// verification[2]) and not transferred in messages directly. 79// verification[2]) and not transferred in messages directly.
80// 80//
81// [1] spe = &Element{...} 81// [1] spe = &Element{...}
82// core.Sign(spe) 82//
83// msg.putpath[i] = spe.Wire() 83// core.Sign(spe)
84// msg.putpath[i] = spe.Wire()
84// 85//
85// [2] pe = &Element{...,Signature: wire.sig} 86// [2] pe = &Element{...,Signature: wire.sig}
86// if !pe.Verify(peerId) { ... }
87// 87//
88// if !pe.Verify(peerId) { ... }
88type Element struct { 89type Element struct {
89 elementData 90 _ElementData
90 Entry 91 Entry
91} 92}
92 93
93// SignedData gets the data to be signed by peer ('Signable' interface) 94// SignedData gets the data to be signed by peer ('Signable' interface)
94func (pe *Element) SignedData() []byte { 95func (pe *Element) SignedData() []byte {
95 sd := &elementSignedData{ 96 sd := &_SignedData{
96 Size: 80, 97 Purpose: &crypto.SignaturePurpose{
97 Purpose: uint16(enums.SIG_DHT_HOP), 98 Size: 144,
98 Elem: &(pe.elementData), 99 Purpose: enums.SIG_DHT_HOP,
100 },
101 Elem: &(pe._ElementData),
99 } 102 }
100 buf, err := data.Marshal(sd) 103 buf, err := data.Marshal(sd)
101 if err != nil { 104 if err != nil {
102 logger.Println(logger.ERROR, "can't serialize path element for signature") 105 logger.Println(logger.ERROR, "can't serialize path element for signature")
103 return nil 106 return nil
104 } 107 }
108 if len(buf) != int(sd.Purpose.Size) {
109 logger.Printf(logger.ERROR, "size mismatch for serialized path element -- %d -> %d", sd.Purpose.Size, len(buf))
110 sd.Purpose.Size = uint32(len(buf))
111 return nil
112 }
105 return buf 113 return buf
106} 114}
107 115
diff --git a/src/gnunet/service/dht/path/elements_test.go b/src/gnunet/service/dht/path/elements_test.go
new file mode 100644
index 0000000..68c2384
--- /dev/null
+++ b/src/gnunet/service/dht/path/elements_test.go
@@ -0,0 +1,71 @@
1// This file is part of gnunet-go, a GNUnet-implementation in Golang.
2// Copyright (C) 2019-2022 Bernd Fix >Y<
3//
4// gnunet-go is free software: you can redistribute it and/or modify it
5// under the terms of the GNU Affero General Public License as published
6// by the Free Software Foundation, either version 3 of the License,
7// or (at your option) any later version.
8//
9// gnunet-go is distributed in the hope that it will be useful, but
10// WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Affero General Public License for more details.
13//
14// You should have received a copy of the GNU Affero General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16//
17// SPDX-License-Identifier: AGPL3.0-or-later
18
19package path
20
21import (
22 "encoding/hex"
23 "gnunet/util"
24 "testing"
25)
26
27func TestElementDebug(t *testing.T) {
28 var (
29 signedData = "" +
30 "00000090" +
31 "00000006" +
32 "0005e6983d33f911" +
33 "f3236acc2be7812a988617c647fc27fcfbd0dacc3d960aa29a5f9bf0b9b9131f" +
34 "cdd31cfa45de2cbd9510665e7f2b1ccafefd445511c62729c0798dd1b0675f19" +
35 "0000000000000000000000000000000000000000000000000000000000000000" +
36 "23b096021b25d822c217a756b877cf72c7fdabd4eff79c4dbb7418dd2b232386"
37
38 signature = "" +
39 "ef94ddfd90b56f30b265a88384551907fadef176b4ba6b023df429506b34cde0" +
40 "39f38661d451e6e5bd1c4d5d078d27f0e8954bd964ea55f03afa42aa9964cc0c"
41 signer = "" +
42 "28f06fe5178742c3b8f080431e48cf5bf3898ba8b8fd57a975772d14003a8c75"
43 predecessor = "" +
44 "0000000000000000000000000000000000000000000000000000000000000000"
45 successor = "" +
46 "23b096021b25d822c217a756b877cf72c7fdabd4eff79c4dbb7418dd2b232386"
47 )
48 convert := func(s string) []byte {
49 buf, err := hex.DecodeString(s)
50 if err != nil {
51 t.Fatal(err)
52 }
53 return buf
54 }
55 sd := convert(signedData)
56 sig := util.NewPeerSignature(convert(signature))
57 pred := util.NewPeerID(convert(predecessor))
58 curr := util.NewPeerID(convert(signer))
59 succ := util.NewPeerID(convert(successor))
60
61 ok, err := curr.Verify(sd, sig)
62 if err != nil {
63 t.Fatal(err)
64 }
65 if !ok {
66 t.Logf("Pred: %s", pred.Short())
67 t.Logf("Sign: %s", curr.Short())
68 t.Logf("Succ: %s", succ.Short())
69 t.Error("Verify NOT OK:")
70 }
71}
diff --git a/src/gnunet/service/dht/path/handling.go b/src/gnunet/service/dht/path/handling.go
index 4040511..7ad91df 100644
--- a/src/gnunet/service/dht/path/handling.go
+++ b/src/gnunet/service/dht/path/handling.go
@@ -19,11 +19,10 @@
19package path 19package path
20 20
21import ( 21import (
22 "bytes"
23 "encoding/hex"
24 "fmt"
25 "gnunet/crypto" 22 "gnunet/crypto"
23 "gnunet/enums"
26 "gnunet/util" 24 "gnunet/util"
25 "strings"
27 26
28 "github.com/bfix/gospel/data" 27 "github.com/bfix/gospel/data"
29 "github.com/bfix/gospel/logger" 28 "github.com/bfix/gospel/logger"
@@ -33,17 +32,11 @@ import (
33// Path handling 32// Path handling
34//---------------------------------------------------------------------- 33//----------------------------------------------------------------------
35 34
36// path flags
37const (
38 PathTruncated = 1
39 PathLastHop = 2
40)
41
42// Path is the complete list of verified hops a message travelled. 35// Path is the complete list of verified hops a message travelled.
43// It also keeps the associated block hash and expiration time of 36// It also keeps the associated block hash and expiration time of
44// the request for signature verification purposes. 37// the request for signature verification purposes.
45type Path struct { 38type Path struct {
46 Flags uint32 `order:"big"` // flags 39 Flags uint16 `order:"big"` // flags
47 BlkHash *crypto.HashCode `` // block hash value 40 BlkHash *crypto.HashCode `` // block hash value
48 Expire util.AbsoluteTime `` // expiration time 41 Expire util.AbsoluteTime `` // expiration time
49 TruncOrigin *util.PeerID `opt:"(IsUsed)"` // truncated origin (optional) 42 TruncOrigin *util.PeerID `opt:"(IsUsed)"` // truncated origin (optional)
@@ -58,9 +51,9 @@ type Path struct {
58func (p *Path) IsUsed(field string) bool { 51func (p *Path) IsUsed(field string) bool {
59 switch field { 52 switch field {
60 case "TruncOrigin": 53 case "TruncOrigin":
61 return p.Flags&PathTruncated != 0 54 return p.Flags&enums.DHT_RO_TRUNCATED != 0
62 case "LastSig", "LastHop": 55 case "LastSig", "LastHop":
63 return p.Flags&PathLastHop != 0 56 return p.Flags&enums.DHT_RO_RECORD_ROUTE != 0
64 } 57 }
65 return false 58 return false
66} 59}
@@ -128,7 +121,7 @@ func (p *Path) Clone() *Path {
128// NewElement creates a new path element from data 121// NewElement creates a new path element from data
129func (p *Path) NewElement(pred, signer, succ *util.PeerID) *Element { 122func (p *Path) NewElement(pred, signer, succ *util.PeerID) *Element {
130 return &Element{ 123 return &Element{
131 elementData: elementData{ 124 _ElementData: _ElementData{
132 Expire: p.Expire, 125 Expire: p.Expire,
133 BlockHash: p.BlkHash, 126 BlockHash: p.BlkHash,
134 PeerPredecessor: pred, 127 PeerPredecessor: pred,
@@ -155,7 +148,7 @@ func (p *Path) Add(elem *Element) {
155 // update last hop signature 148 // update last hop signature
156 p.LastSig = elem.Signature 149 p.LastSig = elem.Signature
157 p.LastHop = elem.Signer 150 p.LastHop = elem.Signer
158 p.Flags |= PathLastHop 151 p.Flags |= enums.DHT_RO_RECORD_ROUTE
159} 152}
160 153
161// Verify path: process list entries from right to left (decreasing index). 154// Verify path: process list entries from right to left (decreasing index).
@@ -181,6 +174,7 @@ func (p *Path) Verify(local *util.PeerID) {
181 pe := p.NewElement(pred, p.LastHop, local) 174 pe := p.NewElement(pred, p.LastHop, local)
182 ok, err := pe.Verify(p.LastSig) 175 ok, err := pe.Verify(p.LastSig)
183 if err != nil || !ok { 176 if err != nil || !ok {
177 logger.Println(logger.WARN, "[path] Dropping path (invalid last signature)")
184 // remove last hop signature and truncated origin; reset flags 178 // remove last hop signature and truncated origin; reset flags
185 p.LastSig = nil 179 p.LastSig = nil
186 p.LastHop = nil 180 p.LastHop = nil
@@ -188,79 +182,79 @@ func (p *Path) Verify(local *util.PeerID) {
188 p.Flags = 0 182 p.Flags = 0
189 } 183 }
190 return 184 return
191 } else { 185 }
192 // yes: process list of path elements 186 // yes: process list of path elements
193 signer := p.LastHop 187 signer := p.LastHop
194 sig := p.LastSig 188 sig := p.LastSig
195 succ := local 189 succ := local
196 num := len(p.List) 190 num := len(p.List)
197 var pred *util.PeerID 191 var pred *util.PeerID
198 for i := num - 1; i >= 0; i-- { 192 for i := num - 1; i >= 0; i-- {
199 if i == -1 { 193 if i == -1 {
200 if p.TruncOrigin != nil { 194 if p.TruncOrigin != nil {
201 pred = p.TruncOrigin 195 pred = p.TruncOrigin
202 } else {
203 pred = util.NewPeerID(nil)
204 }
205 } else { 196 } else {
206 pred = p.List[i].Signer 197 pred = util.NewPeerID(nil)
207 } 198 }
208 pe := p.NewElement(pred, signer, succ) 199 } else {
209 ok, err := pe.Verify(sig) 200 pred = p.List[i].Signer
210 if err != nil || !ok { 201 }
211 // we need to truncate: 202 pe := p.NewElement(pred, signer, succ)
212 logger.Printf(logger.WARN, "[path] Truncating path (invalid signature at hop %d)", i) 203 ok, err := pe.Verify(sig)
204 if err != nil || !ok {
205 // we need to truncate:
206 logger.Printf(logger.WARN, "[path] Truncating path (invalid signature at hop %d)", i)
213 207
214 // are we at the end of the list? 208 // are we at the end of the list?
215 if i == num-1 { 209 if i == num-1 {
216 // yes: the last hop signature failed -> reset path 210 // yes: the last hop signature failed -> reset path
217 p.LastSig = nil 211 p.LastSig = nil
218 p.LastHop = nil 212 p.LastHop = nil
219 p.TruncOrigin = nil 213 p.TruncOrigin = nil
220 p.Flags = 0 214 p.Flags = 0
221 p.List = make([]*Entry, 0) 215 p.List = make([]*Entry, 0)
222 return
223 }
224 // trim list
225 p.Flags |= PathTruncated
226 p.TruncOrigin = signer
227 size := num - 2 - i
228 list := make([]*Entry, size)
229 if size > 0 {
230 copy(list, p.List[i+2:])
231 }
232 p.List = list
233 return 216 return
234 } 217 }
235 // check next path element 218 // trim list
236 succ = signer 219 p.Flags |= enums.DHT_RO_TRUNCATED
237 signer = pred 220 p.TruncOrigin = signer
238 if i != -1 { 221 size := num - 2 - i
239 sig = p.List[i].Signature 222 list := make([]*Entry, size)
223 if size > 0 {
224 copy(list, p.List[i+2:])
240 } 225 }
226 p.List = list
227 return
228 }
229 // check next path element
230 succ = signer
231 signer = pred
232 if i != -1 {
233 sig = p.List[i].Signature
241 } 234 }
242 } 235 }
243} 236}
244 237
245// String returs a uman-readbale representation 238// String returns a human-readable representation
246func (p *Path) String() string { 239func (p *Path) String() string {
247 buf := new(bytes.Buffer) 240 var hops []string
248 s := "0" 241 if p != nil {
249 if p.TruncOrigin != nil { 242 if p.TruncOrigin != nil {
250 s = p.TruncOrigin.String() 243 hops = append(hops, p.TruncOrigin.Short())
251 } 244 }
252 buf.WriteString(fmt.Sprintf("{to=%s, (%d)[", s, len(p.List))) 245 for _, e := range p.List {
253 for _, e := range p.List { 246 hops = append(hops, e.Signer.Short())
254 buf.WriteString(e.String()) 247 }
255 } 248 if p.LastHop != nil {
256 s = "0" 249 hops = append(hops, p.LastHop.Short())
257 if p.LastSig != nil { 250 }
258 s = hex.EncodeToString(p.LastSig.Bytes())
259 } 251 }
260 num := len(s) 252 // trim to sensible length for display
261 if num > 16 { 253 if num := len(hops); num > 8 {
262 s = s[:8] + ".." + s[num-8:] 254 trim := make([]string, 9)
255 copy(trim[:4], hops[:4])
256 trim[4] = "..."
257 copy(trim[5:], hops[num-5:])
263 } 258 }
264 buf.WriteString(fmt.Sprintf("], ls=%s}", s)) 259 return "[" + strings.Join(hops, "-") + "]"
265 return buf.String()
266} 260}