aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBernd Fix <brf@hoi-polloi.org>2022-02-02 15:14:12 +0100
committerBernd Fix <brf@hoi-polloi.org>2022-02-02 15:14:12 +0100
commit205cad60026bf0af1cd2712a8faa4bce08eafb1d (patch)
tree9a2f361e5b2227b3e213fc5093d07641c18cedb4 /src
parentd9dc142fe6d634066c8e33b48106cd6e5c588baf (diff)
downloadgnunet-go-205cad60026bf0af1cd2712a8faa4bce08eafb1d.tar.gz
gnunet-go-205cad60026bf0af1cd2712a8faa4bce08eafb1d.zip
Refactored GNS zone crypto implementation.v0.1.23
Diffstat (limited to 'src')
-rw-r--r--src/cmd/gnunet-service-gns-go/main.go31
-rw-r--r--src/cmd/gnunet-service-revocation-go/main.go29
-rw-r--r--src/gnunet/config/config.go24
-rw-r--r--src/gnunet/config/gnunet-config.json3
-rw-r--r--src/gnunet/crypto/gns.go432
-rw-r--r--src/gnunet/crypto/gns_edkey.go245
-rw-r--r--src/gnunet/crypto/gns_pkey.go241
-rw-r--r--src/gnunet/crypto/gns_test.go370
-rw-r--r--src/gnunet/crypto/key_derivation.go50
-rw-r--r--src/gnunet/crypto/key_derivation_test.go228
-rw-r--r--src/gnunet/crypto/key_exchange_test.go7
-rw-r--r--src/gnunet/crypto/symmetric.go108
-rw-r--r--src/gnunet/enums/gns.go1
-rw-r--r--src/gnunet/go.mod18
-rw-r--r--src/gnunet/go.sum119
-rw-r--r--src/gnunet/message/const.go12
-rw-r--r--src/gnunet/message/factory.go7
-rw-r--r--src/gnunet/message/message.go14
-rw-r--r--src/gnunet/message/msg_core.go8
-rw-r--r--src/gnunet/message/msg_dht.go38
-rw-r--r--src/gnunet/message/msg_gns.go193
-rw-r--r--src/gnunet/message/msg_gns_test.go353
-rw-r--r--src/gnunet/message/msg_namecache.go99
-rw-r--r--src/gnunet/message/msg_revocation.go86
-rw-r--r--src/gnunet/message/msg_transport.go76
-rw-r--r--src/gnunet/modules.go23
-rw-r--r--src/gnunet/rpc/server.go66
-rw-r--r--src/gnunet/service/client.go4
-rw-r--r--src/gnunet/service/context.go4
-rw-r--r--src/gnunet/service/dht/module.go10
-rw-r--r--src/gnunet/service/gns/block_handler.go160
-rw-r--r--src/gnunet/service/gns/box.go6
-rw-r--r--src/gnunet/service/gns/dns.go39
-rw-r--r--src/gnunet/service/gns/module.go160
-rw-r--r--src/gnunet/service/gns/service.go139
-rw-r--r--src/gnunet/service/namecache/module.go4
-rw-r--r--src/gnunet/service/revocation/module.go39
-rw-r--r--src/gnunet/service/revocation/pow.go71
-rw-r--r--src/gnunet/service/revocation/pow_test.go235
-rw-r--r--src/gnunet/service/revocation/service.go63
-rw-r--r--src/gnunet/service/service.go39
-rw-r--r--src/gnunet/transport/channel.go14
-rw-r--r--src/gnunet/transport/channel_netw.go20
-rw-r--r--src/gnunet/transport/channel_test.go87
-rw-r--r--src/gnunet/transport/connection.go2
-rw-r--r--src/gnunet/transport/session.go12
-rw-r--r--src/gnunet/util/address.go2
-rw-r--r--src/gnunet/util/array.go8
-rw-r--r--src/gnunet/util/database.go20
-rw-r--r--src/gnunet/util/id.go3
-rw-r--r--src/gnunet/util/key_value_store.go22
-rw-r--r--src/gnunet/util/misc.go6
-rw-r--r--src/gnunet/util/time.go2
-rw-r--r--src/gnunet/util/time_test.go44
54 files changed, 2748 insertions, 1348 deletions
diff --git a/src/cmd/gnunet-service-gns-go/main.go b/src/cmd/gnunet-service-gns-go/main.go
index 2815eaa..57eec7e 100644
--- a/src/cmd/gnunet-service-gns-go/main.go
+++ b/src/cmd/gnunet-service-gns-go/main.go
@@ -19,16 +19,20 @@
19package main 19package main
20 20
21import ( 21import (
22 "context"
22 "flag" 23 "flag"
23 "os" 24 "os"
24 "os/signal" 25 "os/signal"
26 "strings"
25 "syscall" 27 "syscall"
26 "time" 28 "time"
27 29
28 "github.com/bfix/gospel/logger"
29 "gnunet/config" 30 "gnunet/config"
31 "gnunet/rpc"
30 "gnunet/service" 32 "gnunet/service"
31 "gnunet/service/gns" 33 "gnunet/service/gns"
34
35 "github.com/bfix/gospel/logger"
32) 36)
33 37
34func main() { 38func main() {
@@ -44,11 +48,13 @@ func main() {
44 srvEndp string 48 srvEndp string
45 err error 49 err error
46 logLevel int 50 logLevel int
51 rpcEndp string
47 ) 52 )
48 // handle command line arguments 53 // handle command line arguments
49 flag.StringVar(&cfgFile, "c", "gnunet-config.json", "GNUnet configuration file") 54 flag.StringVar(&cfgFile, "c", "gnunet-config.json", "GNUnet configuration file")
50 flag.StringVar(&srvEndp, "s", "", "GNS service end-point") 55 flag.StringVar(&srvEndp, "s", "", "GNS service end-point")
51 flag.IntVar(&logLevel, "L", logger.INFO, "GNS log level (default: INFO)") 56 flag.IntVar(&logLevel, "L", logger.INFO, "GNS log level (default: INFO)")
57 flag.StringVar(&rpcEndp, "R", "", "JSON-RPC endpoint (default: none)")
52 flag.Parse() 58 flag.Parse()
53 59
54 // read configuration file and set missing arguments. 60 // read configuration file and set missing arguments.
@@ -64,13 +70,31 @@ func main() {
64 } 70 }
65 71
66 // start a new GNS service 72 // start a new GNS service
67 gns := gns.NewGNSService() 73 gns := gns.NewService()
68 srv := service.NewServiceImpl("gns", gns) 74 srv := service.NewServiceImpl("gns", gns)
69 if err = srv.Start(srvEndp); err != nil { 75 if err = srv.Start(srvEndp); err != nil {
70 logger.Printf(logger.ERROR, "[gns] Error: '%s'\n", err.Error()) 76 logger.Printf(logger.ERROR, "[gns] Error: '%s'", err.Error())
71 return 77 return
72 } 78 }
73 79
80 // start JSON-RPC server on request
81 var cancel func() = func() {}
82 if len(rpcEndp) > 0 {
83 var ctx context.Context
84 ctx, cancel = context.WithCancel(context.Background())
85 parts := strings.Split(rpcEndp, "+")
86 if parts[0] != "tcp" {
87 logger.Println(logger.ERROR, "[gns] RPC must have a TCP/IP endpoint")
88 return
89 }
90 config.Cfg.RPC.Endpoint = parts[1]
91 if err = rpc.Start(ctx); err != nil {
92 logger.Printf(logger.ERROR, "[gns] RPC failed to start: %s", err.Error())
93 return
94 }
95 rpc.Register(gns)
96 }
97
74 // handle OS signals 98 // handle OS signals
75 sigCh := make(chan os.Signal, 5) 99 sigCh := make(chan os.Signal, 5)
76 signal.Notify(sigCh) 100 signal.Notify(sigCh)
@@ -101,5 +125,6 @@ loop:
101 } 125 }
102 126
103 // terminating service 127 // terminating service
128 cancel()
104 srv.Stop() 129 srv.Stop()
105} 130}
diff --git a/src/cmd/gnunet-service-revocation-go/main.go b/src/cmd/gnunet-service-revocation-go/main.go
index c829aea..ec5ce73 100644
--- a/src/cmd/gnunet-service-revocation-go/main.go
+++ b/src/cmd/gnunet-service-revocation-go/main.go
@@ -19,16 +19,20 @@
19package main 19package main
20 20
21import ( 21import (
22 "context"
22 "flag" 23 "flag"
23 "os" 24 "os"
24 "os/signal" 25 "os/signal"
26 "strings"
25 "syscall" 27 "syscall"
26 "time" 28 "time"
27 29
28 "github.com/bfix/gospel/logger"
29 "gnunet/config" 30 "gnunet/config"
31 "gnunet/rpc"
30 "gnunet/service" 32 "gnunet/service"
31 "gnunet/service/revocation" 33 "gnunet/service/revocation"
34
35 "github.com/bfix/gospel/logger"
32) 36)
33 37
34func main() { 38func main() {
@@ -44,11 +48,13 @@ func main() {
44 srvEndp string 48 srvEndp string
45 err error 49 err error
46 logLevel int 50 logLevel int
51 rpcEndp string
47 ) 52 )
48 // handle command line arguments 53 // handle command line arguments
49 flag.StringVar(&cfgFile, "c", "gnunet-config.json", "GNUnet configuration file") 54 flag.StringVar(&cfgFile, "c", "gnunet-config.json", "GNUnet configuration file")
50 flag.StringVar(&srvEndp, "s", "", "REVOCATION service end-point") 55 flag.StringVar(&srvEndp, "s", "", "REVOCATION service end-point")
51 flag.IntVar(&logLevel, "L", logger.INFO, "REVOCATION log level (default: INFO)") 56 flag.IntVar(&logLevel, "L", logger.INFO, "REVOCATION log level (default: INFO)")
57 flag.StringVar(&rpcEndp, "R", "", "JSON-RPC endpoint (default: none)")
52 flag.Parse() 58 flag.Parse()
53 59
54 // read configuration file and set missing arguments. 60 // read configuration file and set missing arguments.
@@ -64,13 +70,31 @@ func main() {
64 } 70 }
65 71
66 // start a new REVOCATION service 72 // start a new REVOCATION service
67 rvc := revocation.NewRevocationService() 73 rvc := revocation.NewService()
68 srv := service.NewServiceImpl("revocation", rvc) 74 srv := service.NewServiceImpl("revocation", rvc)
69 if err = srv.Start(srvEndp); err != nil { 75 if err = srv.Start(srvEndp); err != nil {
70 logger.Printf(logger.ERROR, "[revocation] Error: '%s'\n", err.Error()) 76 logger.Printf(logger.ERROR, "[revocation] Error: '%s'\n", err.Error())
71 return 77 return
72 } 78 }
73 79
80 // start JSON-RPC server on request
81 var cancel func() = func() {}
82 if len(rpcEndp) > 0 {
83 var ctx context.Context
84 ctx, cancel = context.WithCancel(context.Background())
85 parts := strings.Split(rpcEndp, "+")
86 if parts[0] != "tcp" {
87 logger.Println(logger.ERROR, "[revocation] RPC must have a TCP/IP endpoint")
88 return
89 }
90 config.Cfg.RPC.Endpoint = parts[1]
91 if err = rpc.Start(ctx); err != nil {
92 logger.Printf(logger.ERROR, "[revocation] RPC failed to start: %s", err.Error())
93 return
94 }
95 rpc.Register(rvc)
96 }
97
74 // handle OS signals 98 // handle OS signals
75 sigCh := make(chan os.Signal, 5) 99 sigCh := make(chan os.Signal, 5)
76 signal.Notify(sigCh) 100 signal.Notify(sigCh)
@@ -101,5 +125,6 @@ loop:
101 } 125 }
102 126
103 // terminating service 127 // terminating service
128 cancel()
104 srv.Stop() 129 srv.Stop()
105} 130}
diff --git a/src/gnunet/config/config.go b/src/gnunet/config/config.go
index 690b186..914a017 100644
--- a/src/gnunet/config/config.go
+++ b/src/gnunet/config/config.go
@@ -29,9 +29,17 @@ import (
29) 29)
30 30
31/////////////////////////////////////////////////////////////////////// 31///////////////////////////////////////////////////////////////////////
32// RPC configuration
33
34// RPCConfig contains parameters for the JSON-RPC service
35type RPCConfig struct {
36 Endpoint string `json:"endpoint"` // end-point of JSON-RPC service
37}
38
39///////////////////////////////////////////////////////////////////////
32// GNS configuration 40// GNS configuration
33 41
34// GNSConfig 42// GNSConfig contains parameters for the GNU Name System service
35type GNSConfig struct { 43type GNSConfig struct {
36 Endpoint string `json:"endpoint"` // end-point of GNS service 44 Endpoint string `json:"endpoint"` // end-point of GNS service
37 DHTReplLevel int `json:"dhtReplLevel"` // DHT replication level 45 DHTReplLevel int `json:"dhtReplLevel"` // DHT replication level
@@ -41,7 +49,7 @@ type GNSConfig struct {
41/////////////////////////////////////////////////////////////////////// 49///////////////////////////////////////////////////////////////////////
42// DHT configuration 50// DHT configuration
43 51
44// DHTConfig 52// DHTConfig contains parameters for the distributed hash table (DHT)
45type DHTConfig struct { 53type DHTConfig struct {
46 Endpoint string `json:"endpoint"` // end-point of DHT service 54 Endpoint string `json:"endpoint"` // end-point of DHT service
47} 55}
@@ -49,7 +57,7 @@ type DHTConfig struct {
49/////////////////////////////////////////////////////////////////////// 57///////////////////////////////////////////////////////////////////////
50// Namecache configuration 58// Namecache configuration
51 59
52// NamecacheConfig 60// NamecacheConfig contains parameters for the local name cache
53type NamecacheConfig struct { 61type NamecacheConfig struct {
54 Endpoint string `json:"endpoint"` // end-point of Namecache service 62 Endpoint string `json:"endpoint"` // end-point of Namecache service
55} 63}
@@ -57,7 +65,7 @@ type NamecacheConfig struct {
57/////////////////////////////////////////////////////////////////////// 65///////////////////////////////////////////////////////////////////////
58// Revocation configuration 66// Revocation configuration
59 67
60// RevocationConfig 68// RevocationConfig contains parameters for the key revocation service
61type RevocationConfig struct { 69type RevocationConfig struct {
62 Endpoint string `json:"endpoint"` // end-point of Revocation service 70 Endpoint string `json:"endpoint"` // end-point of Revocation service
63 Storage string `json:"storage"` // persistance mechanism for revocation data 71 Storage string `json:"storage"` // persistance mechanism for revocation data
@@ -66,11 +74,12 @@ type RevocationConfig struct {
66/////////////////////////////////////////////////////////////////////// 74///////////////////////////////////////////////////////////////////////
67 75
68// Environment settings 76// Environment settings
69type Environ map[string]string 77type Environment map[string]string
70 78
71// Config is the aggregated configuration for GNUnet. 79// Config is the aggregated configuration for GNUnet.
72type Config struct { 80type Config struct {
73 Env Environ `json:"environ"` 81 Env Environment `json:"environ"`
82 RPC *RPCConfig `json:"rpc"`
74 DHT *DHTConfig `json:"dht"` 83 DHT *DHTConfig `json:"dht"`
75 GNS *GNSConfig `json:"gns"` 84 GNS *GNSConfig `json:"gns"`
76 Namecache *NamecacheConfig `json:"namecache"` 85 Namecache *NamecacheConfig `json:"namecache"`
@@ -82,7 +91,8 @@ var (
82 Cfg *Config 91 Cfg *Config
83) 92)
84 93
85// Parse a JSON-encoded configuration file map it to the Config data structure. 94// ParseConfig converts a JSON-encoded configuration file and maps it to
95// the Config data structure.
86func ParseConfig(fileName string) (err error) { 96func ParseConfig(fileName string) (err error) {
87 // parse configuration file 97 // parse configuration file
88 file, err := ioutil.ReadFile(fileName) 98 file, err := ioutil.ReadFile(fileName)
diff --git a/src/gnunet/config/gnunet-config.json b/src/gnunet/config/gnunet-config.json
index aefc9ee..daf65f9 100644
--- a/src/gnunet/config/gnunet-config.json
+++ b/src/gnunet/config/gnunet-config.json
@@ -17,5 +17,8 @@
17 "revocation": { 17 "revocation": {
18 "endpoint": "unix+${RT_SYS}/gnunet-service-revocation-go.sock+perm=0770", 18 "endpoint": "unix+${RT_SYS}/gnunet-service-revocation-go.sock+perm=0770",
19 "storage": "redis+localhost:6397++15" 19 "storage": "redis+localhost:6397++15"
20 },
21 "rpc": {
22 "endpoint": "tcp+127.0.0.1:80"
20 } 23 }
21} 24}
diff --git a/src/gnunet/crypto/gns.go b/src/gnunet/crypto/gns.go
index 8b33057..6aa7972 100644
--- a/src/gnunet/crypto/gns.go
+++ b/src/gnunet/crypto/gns.go
@@ -1,5 +1,5 @@
1// This file is part of gnunet-go, a GNUnet-implementation in Golang. 1// This file is part of gnunet-go, a GNUnet-implementation in Golang.
2// Copyright (C) 2019, 2020 Bernd Fix >Y< 2// Copyright (C) 2019-2022 Bernd Fix >Y<
3// 3//
4// gnunet-go is free software: you can redistribute it and/or modify it 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 5// under the terms of the GNU Affero General Public License as published
@@ -19,35 +19,415 @@
19package crypto 19package crypto
20 20
21import ( 21import (
22 "bytes"
22 "crypto/sha256" 23 "crypto/sha256"
23 "crypto/sha512" 24 "crypto/sha512"
25 "encoding/binary"
26 "errors"
27 "gnunet/enums"
28 "gnunet/util"
24 29
25 "github.com/bfix/gospel/crypto/ed25519" 30 "github.com/bfix/gospel/data"
31 "github.com/bfix/gospel/math"
26 "golang.org/x/crypto/hkdf" 32 "golang.org/x/crypto/hkdf"
27) 33)
28 34
29// DeriveBlockKey returns a symmetric key and initialization vector to decipher a GNS block. 35//======================================================================
30func DeriveBlockKey(label string, pub *ed25519.PublicKey) (iv *SymmetricIV, skey *SymmetricKey) { 36// All zone-related cryptography in GNS is encapsulated in three
31 // generate symmetric key 37// distinct types: ZonePrivate, ZoneKey (public) and ZoneSignature.
32 prk := hkdf.Extract(sha512.New, pub.Bytes(), []byte("gns-aes-ctx-key")) 38// To enable crypto-agility, these types are implemented in a generic
33 rdr := hkdf.Expand(sha256.New, prk, []byte(label)) 39// way - mostly as byte arrays holding the specific representation of a
34 skey = NewSymmetricKey() 40// crypto implementation.
35 rdr.Read(skey.AESKey) 41//
36 rdr.Read(skey.TwofishKey) 42// Currently two key systems are implemented:
37 43// * PKEY: Ed25519 keys with private scalar and ECDSA signatures
38 // generate initialization vector 44// * EDKEY: Ed25519 keys for EdDSA signatures (Ed25519 standard)
39 prk = hkdf.Extract(sha512.New, pub.Bytes(), []byte("gns-aes-ctx-iv")) 45//
40 rdr = hkdf.Expand(sha256.New, prk, []byte(label)) 46// It is easy to implement new crypto schemes as long as the following
41 iv = NewSymmetricIV() 47// criteria are met:
42 rdr.Read(iv.AESIv) 48// * It is an asymmetric crypto scheme (with private and public key)
43 rdr.Read(iv.TwofishIv) 49// * It can encrypt data with a public key and decrypt it with the
44 return 50// corresponding private key. How that is done is completely up to
45} 51// the specific implementation.
46 52// * It can sign data with the private key and verify it with the
47// DecryptBlock for a given zone and label. 53// corresponding public key.
48func DecryptBlock(data []byte, zoneKey *ed25519.PublicKey, label string) (out []byte, err error) { 54// * It can do key blinding (public and private) based on a 64 byte
49 // derive key material for decryption 55// byte array. How that is done is up to the specific implementation.
50 iv, skey := DeriveBlockKey(label, zoneKey) 56//
51 // perform decryption 57// The way to add new zone crypto implementation is as follows; as an
52 return SymmetricDecrypt(data, skey, iv) 58// example the RSA crypto scheme is outlined:
59//
60// (1) Register/define a new GNS_TYPE_RSAKEY
61// (2) Add ZONE_RSAKEY to the "Zone types" declarations below.
62// (3) Code the implementation in a file named `gns_rsakey.go`:
63// You have to implement three interfaces (ZonePrivateImpl,
64// ZoneKeyImpl and ZoneSigImpl) in three separate custom types.
65// Additionally an instantiation function (zero value) must be
66// defined for all three custom types (like 'NewRSAPrivate()'
67// taking no arguments and returning an empty new instance.
68// (4) In the 'init()' method of your source file, register the
69// implementation in the "Zone implementations" below with:
70// zoneImpl[ZONE_RSAKEY] = &ZoneImplementation{
71// NewPrivate: NewRSAPrivate,
72// PrivateSize: 256,
73// NewPublic: NewRSAPublic,
74// PublicSize: 270.
75// NewSignature: newRSASignature,
76// SignatureSize: 512,
77// }
78// Review a provided implementation (like `gns_edkey.go`) as an
79// example on how to create a custom GNS zone crypto.
80// (5) Add the zone type to the GNS block handler in file
81// `service/gns/block_handler.go`:
82// ;
83// enums.GNS_TYPE_RSAKEY: NewZoneHandler,
84// ;
85//
86//======================================================================
87
88//----------------------------------------------------------------------
89// Implementation interfaces
90//----------------------------------------------------------------------
91
92// ZoneAbstractImpl is an abstract interface used in derived interfaces
93type ZoneAbstractImpl interface {
94 // Init the instance from given binary representation
95 Init(data []byte) error
96
97 // Bytes returns the binary representation (can be used with 'init()')
98 Bytes() []byte
99}
100
101// ZoneKeyImpl defines the methods for a public zone key.
102type ZoneKeyImpl interface {
103 ZoneAbstractImpl
104
105 // Derive a zone key from this zone key based on a big integer
106 // (key blinding). Returns the derived key and the blinding value.
107 Derive(h *math.Int) (ZoneKeyImpl, *math.Int)
108
109 // BlockKey returns the key for block en-/decryption
110 BlockKey(label string, expires util.AbsoluteTime) (skey []byte)
111
112 // Encrypt binary data (of any size). Output can be larger than input
113 Encrypt(data []byte, label string, expires util.AbsoluteTime) ([]byte, error)
114
115 // Decrypt data (of any size). Output can be smaller than input
116 Decrypt(data []byte, label string, expires util.AbsoluteTime) ([]byte, error)
117
118 // Verify a signature for binary data
119 Verify(data []byte, sig *ZoneSignature) (bool, error)
120}
121
122// ZonePrivateImpl defines the methods for a private zone key.
123type ZonePrivateImpl interface {
124 ZoneAbstractImpl
125
126 // Derive a private key from this zone key based on a big integer
127 // (key blinding). Returns the derived key and the blinding value.
128 Derive(h *math.Int) (ZonePrivateImpl, *math.Int)
129
130 // Sign binary data and return the signature
131 Sign(data []byte) (*ZoneSignature, error)
132
133 // Public returns the associated public key
134 Public() ZoneKeyImpl
135}
136
137// ZoneSigImpl defines the methods for a signature object.
138type ZoneSigImpl interface {
139 ZoneAbstractImpl
140}
141
142//----------------------------------------------------------------------
143// Zone types
144//----------------------------------------------------------------------
145var (
146 ZONE_PKEY = uint32(enums.GNS_TYPE_PKEY)
147 ZONE_EDKEY = uint32(enums.GNS_TYPE_EDKEY)
148)
149
150//----------------------------------------------------------------------
151// Zone implementations
152//----------------------------------------------------------------------
153
154// ZoneImplementation holds factory methods and size values for a
155// specific crypto implementation (based on the associated zone type)
156type ZoneImplementation struct {
157 NewPrivate func() ZonePrivateImpl
158 PrivateSize uint
159 NewPublic func() ZoneKeyImpl
160 PublicSize uint
161 NewSignature func() ZoneSigImpl
162 SignatureSize uint
163}
164
165// keep a mapping of available implementations
166var (
167 zoneImpl = make(map[uint32]*ZoneImplementation)
168)
169
170// Error codes
171var (
172 ErrNoImplementation = errors.New("unknown zone implementation")
173)
174
175// GetImplementation return the factory for a given zone type.
176// If zje zone type is unregistered, nil is returned.
177func GetImplementation(ztype uint32) *ZoneImplementation {
178 if impl, ok := zoneImpl[ztype]; ok {
179 return impl
180 }
181 return nil
182}
183
184//======================================================================
185// Generic implementations:
186//======================================================================
187
188//----------------------------------------------------------------------
189// Zone key (private)
190//----------------------------------------------------------------------
191
192// ZonePrivate represents the possible types of private zone keys (PKEY, EDKEY,...)
193type ZonePrivate struct {
194 ZoneKey
195
196 impl ZonePrivateImpl // reference to implementation
197}
198
199// NewZonePrivate returns a new initialized ZonePrivate instance
200func NewZonePrivate(ztype uint32, d []byte) (*ZonePrivate, error) {
201 // get factory for given zone type
202 impl, ok := zoneImpl[ztype]
203 if !ok {
204 return nil, ErrNoImplementation
205 }
206 // assemble private zone key
207 zp := &ZonePrivate{
208 ZoneKey{
209 ztype,
210 nil,
211 nil,
212 },
213 nil,
214 }
215 zp.impl = impl.NewPrivate()
216 zp.impl.Init(d)
217 zp.ZoneKey.KeyData = zp.impl.Public().Bytes()
218 zp.ZoneKey.impl = impl.NewPublic()
219 zp.ZoneKey.impl.Init(zp.ZoneKey.KeyData)
220 return zp, nil
221}
222
223// KeySize returns the number of bytes of a key representation.
224// This method is used during serialization (Unmarshal).
225func (zp *ZonePrivate) KeySize() uint {
226 if impl, ok := zoneImpl[zp.Type]; ok {
227 return impl.PrivateSize
228 }
229 return 0
230}
231
232// Derive key (key blinding)
233func (zp *ZonePrivate) Derive(label, context string) (*ZonePrivate, *math.Int) {
234 // get factory for given zone type
235 impl := zoneImpl[zp.Type]
236
237 // caclulate derived key
238 h := deriveH(zp.impl.Bytes(), label, context)
239 var derived ZonePrivateImpl
240 derived, h = zp.impl.Derive(h)
241
242 // assemble derived pivate key
243 dzp := &ZonePrivate{
244 ZoneKey{
245 zp.Type,
246 nil,
247 nil,
248 },
249 derived,
250 }
251 zp.ZoneKey.KeyData = derived.Public().Bytes()
252 zp.ZoneKey.impl = impl.NewPublic()
253 zp.ZoneKey.impl.Init(zp.ZoneKey.KeyData)
254 return dzp, h
255}
256
257// ZoneSign data with a private key
258func (zp *ZonePrivate) Sign(data []byte) (sig *ZoneSignature, err error) {
259 return zp.impl.Sign(data)
260}
261
262// Public returns the associated public key
263func (zp *ZonePrivate) Public() *ZoneKey {
264 return &zp.ZoneKey
265}
266
267//----------------------------------------------------------------------
268// Zone key (public)
269//----------------------------------------------------------------------
270
271// ZoneKey represents the possible types of zone keys (PKEY, EDKEY,...)
272type ZoneKey struct {
273 Type uint32 `json:"type" order:"big"`
274 KeyData []byte `json:"key" size:"(KeySize)"`
275
276 impl ZoneKeyImpl // reference to implementation
277}
278
279// NewZoneKey returns a new initialized ZoneKey instance
280func NewZoneKey(d []byte) (*ZoneKey, error) {
281 // read zone key from data
282 zk := new(ZoneKey)
283 if err := data.Unmarshal(zk, d); err != nil {
284 return nil, err
285 }
286 // initialize implementation
287 impl, ok := zoneImpl[zk.Type]
288 if !ok {
289 return nil, errors.New("unknown zone type")
290 }
291 zk.impl = impl.NewPublic()
292 zk.impl.Init(zk.KeyData)
293 return zk, nil
294}
295
296// KeySize returns the number of bytes of a key representation.
297// This method is used during serialization (Unmarshal).
298func (zk *ZoneKey) KeySize() uint {
299 if impl, ok := zoneImpl[zk.Type]; ok {
300 return impl.PublicSize
301 }
302 return 0
303}
304
305// Derive key (key blinding)
306func (zk *ZoneKey) Derive(label, context string) (*ZoneKey, *math.Int) {
307 h := deriveH(zk.KeyData, label, context)
308 var derived ZoneKeyImpl
309 derived, h = zk.impl.Derive(h)
310 return &ZoneKey{
311 Type: zk.Type,
312 KeyData: derived.Bytes(),
313 impl: derived,
314 }, h
315}
316
317// BlockKey returns the key for block en-/decryption
318func (zk *ZoneKey) BlockKey(label string, expires util.AbsoluteTime) (skey []byte) {
319 return zk.impl.BlockKey(label, expires)
320}
321
322// Encrypt data
323func (zk *ZoneKey) Encrypt(data []byte, label string, expire util.AbsoluteTime) ([]byte, error) {
324 return zk.impl.Encrypt(data, label, expire)
325}
326
327// Decrypt data
328func (zk *ZoneKey) Decrypt(data []byte, label string, expire util.AbsoluteTime) ([]byte, error) {
329 return zk.impl.Decrypt(data, label, expire)
330}
331
332// Verify a zone signature
333func (zk *ZoneKey) Verify(data []byte, zs *ZoneSignature) (ok bool, err error) {
334 zk.withImpl()
335 return zk.impl.Verify(data, zs)
336}
337
338// ID returns the human-readable zone identifier.
339func (zk *ZoneKey) ID() string {
340 buf := new(bytes.Buffer)
341 binary.Write(buf, binary.BigEndian, zk.Type)
342 buf.Write(zk.KeyData)
343 return util.EncodeBinaryToString(buf.Bytes())
344}
345
346// Bytes returns all bytes of a zone key
347func (zk *ZoneKey) Bytes() []byte {
348 data, _ := data.Marshal(zk)
349 return data
350}
351
352// Equal checks if two zone keys are equal
353func (zk *ZoneKey) Equal(k *ZoneKey) bool {
354 return bytes.Equal(zk.KeyData, k.KeyData)
355}
356
357// withImpl ensure that an implementation reference is available
358func (zk *ZoneKey) withImpl() {
359 if zk.impl == nil {
360 factory := zoneImpl[zk.Type]
361 zk.impl = factory.NewPublic()
362 zk.impl.Init(zk.KeyData)
363 }
364}
365
366//----------------------------------------------------------------------
367// Zone signature
368//----------------------------------------------------------------------
369
370type ZoneSignature struct {
371 ZoneKey
372 Signature []byte `size:"(SigSize)"` // signature data
373
374 impl ZoneSigImpl // reference to implementation
375}
376
377// NewZoneSignature returns a new initialized ZoneSignature instance
378func NewZoneSignature(d []byte) (*ZoneSignature, error) {
379 // read signature
380 sig := new(ZoneSignature)
381 if err := data.Unmarshal(sig, d); err != nil {
382 return nil, err
383 }
384 // initialize implementations
385 impl, ok := zoneImpl[sig.Type]
386 if !ok {
387 return nil, errors.New("unknown zone type")
388 }
389 // set signature implementation
390 zs := impl.NewSignature()
391 zs.Init(sig.Signature)
392 sig.impl = zs
393 // set public key implementation
394 zk := impl.NewPublic()
395 zk.Init(sig.KeyData)
396 sig.ZoneKey.impl = zk
397
398 return sig, nil
399}
400
401// SigSize returns the number of bytes of a signature that can be
402// verified with a given zone key. This method is used during
403// serialization (Unmarshal).
404func (zs *ZoneSignature) SigSize() uint {
405 if impl, ok := zoneImpl[zs.Type]; ok {
406 return impl.SignatureSize
407 }
408 return 0
409}
410
411// Key returns the associated zone key object
412func (zs *ZoneSignature) Key() *ZoneKey {
413 return &zs.ZoneKey
414}
415
416// Verify a signature
417func (zs *ZoneSignature) Verify(data []byte) (bool, error) {
418 return zs.ZoneKey.Verify(data, zs)
419}
420
421//----------------------------------------------------------------------
422// Helper functions
423//----------------------------------------------------------------------
424
425// deriveH derives an integer 'h' from the arguments.
426func deriveH(key []byte, label, context string) *math.Int {
427 prk := hkdf.Extract(sha512.New, key, []byte("key-derivation"))
428 data := append([]byte(label), []byte(context)...)
429 rdr := hkdf.Expand(sha256.New, prk, data)
430 b := make([]byte, 64)
431 rdr.Read(b)
432 return math.NewIntFromBytes(b)
53} 433}
diff --git a/src/gnunet/crypto/gns_edkey.go b/src/gnunet/crypto/gns_edkey.go
new file mode 100644
index 0000000..3153628
--- /dev/null
+++ b/src/gnunet/crypto/gns_edkey.go
@@ -0,0 +1,245 @@
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 crypto
20
21import (
22 "crypto/sha256"
23 "crypto/sha512"
24 "errors"
25 "gnunet/util"
26
27 "github.com/bfix/gospel/crypto/ed25519"
28 "github.com/bfix/gospel/data"
29 "github.com/bfix/gospel/math"
30 "golang.org/x/crypto/hkdf"
31 "golang.org/x/crypto/nacl/secretbox"
32)
33
34//======================================================================
35// EDKEY implementation for GNS zone crypto:
36// ----------------------------------------
37// Based on the Ed25519 curve. Private keys are defined by a seed
38// and signatures are based on EdDSA.
39//======================================================================
40
41// register our implementation
42func init() {
43 zoneImpl[ZONE_EDKEY] = &ZoneImplementation{
44 NewPrivate: func() ZonePrivateImpl { return &EDKEYPrivateImpl{} },
45 PrivateSize: 32,
46 NewPublic: func() ZoneKeyImpl { return &EDKEYPublicImpl{} },
47 PublicSize: 32,
48 NewSignature: func() ZoneSigImpl { return &EDKEYSigImpl{} },
49 SignatureSize: 64,
50 }
51}
52
53//----------------------------------------------------------------------
54// Private key
55//----------------------------------------------------------------------
56
57// EDKEYPublicImpl implements the public key scheme.
58type EDKEYPublicImpl struct {
59 ztype uint32
60 pub *ed25519.PublicKey
61}
62
63// Init instance from binary data. The data represents a big integer
64// (in big-endian notation) for the private scalar d.
65func (pk *EDKEYPublicImpl) Init(data []byte) error {
66 pk.ztype = ZONE_EDKEY
67 pk.pub = ed25519.NewPublicKeyFromBytes(data)
68 return nil
69}
70
71// Bytes returns a binary representation of the instance suitable for
72// consumption in 'Init()'.
73func (pk *EDKEYPublicImpl) Bytes() []byte {
74 return pk.pub.Bytes()
75}
76
77// Derive a public key from this key based on a big integer
78// (key blinding). Returns the derived key and the blinding value.
79func (pk *EDKEYPublicImpl) Derive(h *math.Int) (ZoneKeyImpl, *math.Int) {
80 // limit to allowed value range
81 h = h.Mod(ed25519.GetCurve().N)
82 derived := pk.pub.Mult(h)
83 dPk := &EDKEYPublicImpl{
84 pk.ztype,
85 derived,
86 }
87 return dPk, h
88}
89
90// Encrypt binary data (of any size). Output can be larger than input
91func (pk *EDKEYPublicImpl) Encrypt(data []byte, label string, expires util.AbsoluteTime) (out []byte, err error) {
92 // derive key material for decryption
93 skey := pk.BlockKey(label, expires)
94
95 // En-/decrypt with XSalsa20-Poly1305 cipher
96 var key [32]byte
97 var nonce [24]byte
98 copy(key[:], skey[:32])
99 copy(nonce[:], skey[32:])
100 out = secretbox.Seal(nil, data, &nonce, &key)
101 return
102}
103
104// Decrypt binary data (of any size). Output can be smaller than input
105func (pk *EDKEYPublicImpl) Decrypt(data []byte, label string, expires util.AbsoluteTime) (out []byte, err error) {
106 // derive key material for decryption
107 skey := pk.BlockKey(label, expires)
108
109 // En-/decrypt with XSalsa20-Poly1305 cipher
110 var (
111 key [32]byte
112 nonce [24]byte
113 ok bool
114 )
115 copy(key[:], skey[:32])
116 copy(nonce[:], skey[32:])
117 if out, ok = secretbox.Open(nil, data, &nonce, &key); !ok {
118 err = errors.New("XSalsa20-Poly1305 open failed")
119 }
120 return
121}
122
123// Verify a signature for binary data
124func (pk *EDKEYPublicImpl) Verify(data []byte, zs *ZoneSignature) (ok bool, err error) {
125 var sig *ed25519.EdSignature
126 if sig, err = ed25519.NewEdSignatureFromBytes(zs.Signature); err != nil {
127 return
128 }
129 return pk.pub.EdVerify(data, sig)
130}
131
132// BlockKey return the symmetric key (and initialization vector) based on
133// label and expiration time.
134func (pk *EDKEYPublicImpl) BlockKey(label string, expires util.AbsoluteTime) (skey []byte) {
135 // generate symmetric key
136 skey = make([]byte, 56)
137 kd := pk.Bytes()
138 prk := hkdf.Extract(sha512.New, kd, []byte("gns-xsalsa-ctx-key"))
139 rdr := hkdf.Expand(sha256.New, prk, []byte(label))
140 rdr.Read(skey[:32])
141
142 // assemble initialization vector
143 iv := &struct {
144 Nonce []byte `size:"16"` // Nonce
145 Expiration util.AbsoluteTime `` // Expiration time of block
146 }{
147 Nonce: make([]byte, 16),
148 Expiration: expires,
149 }
150 prk = hkdf.Extract(sha512.New, kd, []byte("gns-xsalsa-ctx-iv"))
151 rdr = hkdf.Expand(sha256.New, prk, []byte(label))
152 rdr.Read(iv.Nonce)
153 buf, _ := data.Marshal(iv)
154 copy(skey[32:], buf)
155 return
156}
157
158//----------------------------------------------------------------------
159// Private key
160//----------------------------------------------------------------------
161
162// EDKEYPrivateImpl implements the private key scheme.
163type EDKEYPrivateImpl struct {
164 EDKEYPublicImpl
165
166 prv *ed25519.PrivateKey
167}
168
169// Init instance from binary data. The data represents a big integer
170// (in big-endian notation) for the private scalar d.
171func (pk *EDKEYPrivateImpl) Init(data []byte) error {
172 pk.prv = ed25519.NewPrivateKeyFromSeed(data)
173 pk.ztype = ZONE_EDKEY
174 pk.pub = pk.prv.Public()
175 return nil
176}
177
178// Bytes returns a binary representation of the instance suitable for
179// consumption in 'Init()'.
180func (pk *EDKEYPrivateImpl) Bytes() []byte {
181 return pk.prv.Bytes()
182}
183
184// Public returns the associate public key implementation.
185func (pk *EDKEYPrivateImpl) Public() ZoneKeyImpl {
186 return &pk.EDKEYPublicImpl
187}
188
189// Derive a public key from this key based on a big integer
190// (key blinding). Returns the derived key and the blinding value.
191func (pk *EDKEYPrivateImpl) Derive(h *math.Int) (ZonePrivateImpl, *math.Int) {
192 // limit to allowed value range
193 h = h.Mod(ed25519.GetCurve().N)
194 derived := pk.prv.Mult(h)
195 dPk := &EDKEYPrivateImpl{
196 EDKEYPublicImpl{
197 pk.ztype,
198 derived.Public(),
199 },
200 derived,
201 }
202 return dPk, h
203}
204
205// Sign binary data
206func (pk *EDKEYPrivateImpl) Sign(data []byte) (*ZoneSignature, error) {
207 s, err := pk.prv.EdSign(data)
208 if err != nil {
209 return nil, err
210 }
211 sd := s.Bytes()
212 sigImpl := new(EDKEYSigImpl)
213 sigImpl.Init(sd)
214 sig := &ZoneSignature{
215 ZoneKey{
216 Type: pk.ztype,
217 KeyData: pk.pub.Bytes(),
218 },
219 sd,
220 sigImpl,
221 }
222 return sig, nil
223}
224
225//----------------------------------------------------------------------
226// Signature
227//----------------------------------------------------------------------
228
229// ZoneSigImpl defines the methods for a signature object.
230type EDKEYSigImpl struct {
231 sig *ed25519.EcSignature
232}
233
234// Init instance from binary data. The data represents a big integers
235// R and S of the signature.
236func (s *EDKEYSigImpl) Init(data []byte) (err error) {
237 s.sig, err = ed25519.NewEcSignatureFromBytes(data)
238 return
239}
240
241// Bytes returns a binary representation of the instance suitable for
242// consumption in 'Init()'.
243func (s *EDKEYSigImpl) Bytes() []byte {
244 return s.sig.Bytes()
245}
diff --git a/src/gnunet/crypto/gns_pkey.go b/src/gnunet/crypto/gns_pkey.go
new file mode 100644
index 0000000..fa319a4
--- /dev/null
+++ b/src/gnunet/crypto/gns_pkey.go
@@ -0,0 +1,241 @@
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 crypto
20
21import (
22 "crypto/aes"
23 "crypto/cipher"
24 "crypto/sha256"
25 "crypto/sha512"
26 "gnunet/util"
27
28 "github.com/bfix/gospel/crypto/ed25519"
29 "github.com/bfix/gospel/data"
30 "github.com/bfix/gospel/math"
31 "golang.org/x/crypto/hkdf"
32)
33
34//======================================================================
35// PKEY implementation for GNS zone crypto:
36// ----------------------------------------
37// Based on the Ed25519 curve. Private keys are defined by a scalar
38// and signatures are based on a deterministic variant of ECDSA.
39//======================================================================
40
41// register our implementation
42func init() {
43 zoneImpl[ZONE_PKEY] = &ZoneImplementation{
44 NewPrivate: func() ZonePrivateImpl { return &PKEYPrivateImpl{} },
45 PrivateSize: 32,
46 NewPublic: func() ZoneKeyImpl { return &PKEYPublicImpl{} },
47 PublicSize: 32,
48 NewSignature: func() ZoneSigImpl { return &PKEYSigImpl{} },
49 SignatureSize: 64,
50 }
51}
52
53//----------------------------------------------------------------------
54// Private key
55//----------------------------------------------------------------------
56
57// PKEYPublicImpl implements the public key scheme.
58type PKEYPublicImpl struct {
59 ztype uint32
60 pub *ed25519.PublicKey
61}
62
63// Init instance from binary data. The data represents a big integer
64// (in big-endian notation) for the private scalar d.
65func (pk *PKEYPublicImpl) Init(data []byte) error {
66 pk.ztype = ZONE_PKEY
67 pk.pub = ed25519.NewPublicKeyFromBytes(data)
68 return nil
69}
70
71// Bytes returns a binary representation of the instance suitable for
72// consumption in 'Init()'.
73func (pk *PKEYPublicImpl) Bytes() []byte {
74 return pk.pub.Bytes()
75}
76
77// Derive a public key from this key based on a big integer
78// (key blinding). Returns the derived key and the blinding value.
79func (pk *PKEYPublicImpl) Derive(h *math.Int) (ZoneKeyImpl, *math.Int) {
80 // limit to allowed value range
81 h = h.Mod(ed25519.GetCurve().N)
82 derived := pk.pub.Mult(h)
83 dPk := &PKEYPublicImpl{
84 pk.ztype,
85 derived,
86 }
87 return dPk, h
88}
89
90// Encrypt binary data (of any size). Output can be larger than input
91func (pk *PKEYPublicImpl) Encrypt(data []byte, label string, expires util.AbsoluteTime) ([]byte, error) {
92 return pk.cipher(true, data, label, expires)
93}
94
95// Decrypt binary data (of any size). Output can be smaller than input
96func (pk *PKEYPublicImpl) Decrypt(data []byte, label string, expires util.AbsoluteTime) ([]byte, error) {
97 return pk.cipher(false, data, label, expires)
98}
99
100// Verify a signature for binary data
101func (pk *PKEYPublicImpl) Verify(data []byte, zs *ZoneSignature) (ok bool, err error) {
102 var sig *ed25519.EcSignature
103 if sig, err = ed25519.NewEcSignatureFromBytes(zs.Signature); err != nil {
104 return
105 }
106 return pk.pub.EcVerify(data, sig)
107}
108
109// BlockKey return the symmetric key (and initialization vector) based on
110// label and expiration time.
111func (pk *PKEYPublicImpl) BlockKey(label string, expires util.AbsoluteTime) (skey []byte) {
112 // generate symmetric key
113 skey = make([]byte, 48)
114 kd := pk.pub.Bytes()
115 prk := hkdf.Extract(sha512.New, kd, []byte("gns-aes-ctx-key"))
116 rdr := hkdf.Expand(sha256.New, prk, []byte(label))
117 rdr.Read(skey[:32])
118
119 // assemble initialization vector
120 iv := &struct {
121 Nonce []byte `size:"4"` // 32 bit Nonce
122 Expiration util.AbsoluteTime `` // Expiration time of block
123 Counter uint32 `order:"big"` // Block counter
124 }{
125 Nonce: make([]byte, 4),
126 Expiration: expires,
127 Counter: 1,
128 }
129 prk = hkdf.Extract(sha512.New, kd, []byte("gns-aes-ctx-iv"))
130 rdr = hkdf.Expand(sha256.New, prk, []byte(label))
131 rdr.Read(iv.Nonce)
132 buf, _ := data.Marshal(iv)
133 copy(skey[32:], buf)
134 return
135}
136
137// cipher implements symmetric en/-decryption (for block data).
138func (pk *PKEYPublicImpl) cipher(encrypt bool, data []byte, label string, expires util.AbsoluteTime) (out []byte, err error) {
139 // derive key material for decryption
140 skey := pk.BlockKey(label, expires)
141
142 // En-/decrypt with AES CTR stream cipher
143 var blk cipher.Block
144 if blk, err = aes.NewCipher(skey[:32]); err != nil {
145 return
146 }
147 stream := cipher.NewCTR(blk, skey[32:])
148 out = make([]byte, len(data))
149 stream.XORKeyStream(out, data)
150 return
151}
152
153//----------------------------------------------------------------------
154// Private key
155//----------------------------------------------------------------------
156
157// PKEYPrivateImpl implements the private key scheme.
158type PKEYPrivateImpl struct {
159 PKEYPublicImpl
160
161 prv *ed25519.PrivateKey
162}
163
164// Init instance from binary data. The data represents a big integer
165// (in big-endian notation) for the private scalar d.
166func (pk *PKEYPrivateImpl) Init(data []byte) error {
167 d := math.NewIntFromBytes(data)
168 pk.prv = ed25519.NewPrivateKeyFromD(d)
169 pk.ztype = ZONE_PKEY
170 pk.pub = pk.prv.Public()
171 return nil
172}
173
174// Bytes returns a binary representation of the instance suitable for
175// consumption in 'Init()'.
176func (pk *PKEYPrivateImpl) Bytes() []byte {
177 return pk.prv.Bytes()
178}
179
180// Public returns the associate public key implementation.
181func (pk *PKEYPrivateImpl) Public() ZoneKeyImpl {
182 return &pk.PKEYPublicImpl
183}
184
185// Derive a public key from this key based on a big integer
186// (key blinding). Returns the derived key and the blinding value.
187func (pk *PKEYPrivateImpl) Derive(h *math.Int) (ZonePrivateImpl, *math.Int) {
188 // limit to allowed value range
189 h = h.Mod(ed25519.GetCurve().N)
190 derived := pk.prv.Mult(h)
191 dPk := &PKEYPrivateImpl{
192 PKEYPublicImpl{
193 pk.ztype,
194 derived.Public(),
195 },
196 derived,
197 }
198 return dPk, h
199}
200
201// Verify a signature for binary data
202func (pk *PKEYPrivateImpl) Sign(data []byte) (*ZoneSignature, error) {
203 s, err := pk.prv.EcSign(data)
204 if err != nil {
205 return nil, err
206 }
207 sd := s.Bytes()
208 sigImpl := new(PKEYSigImpl)
209 sigImpl.Init(sd)
210 sig := &ZoneSignature{
211 ZoneKey{
212 Type: pk.ztype,
213 KeyData: pk.pub.Bytes(),
214 },
215 sd,
216 sigImpl,
217 }
218 return sig, nil
219}
220
221//----------------------------------------------------------------------
222// Signature
223//----------------------------------------------------------------------
224
225// ZoneSigImpl defines the methods for a signature object.
226type PKEYSigImpl struct {
227 sig *ed25519.EcSignature
228}
229
230// Init instance from binary data. The data represents a big integers
231// R and S of the signature.
232func (s *PKEYSigImpl) Init(data []byte) (err error) {
233 s.sig, err = ed25519.NewEcSignatureFromBytes(data)
234 return
235}
236
237// Bytes returns a binary representation of the instance suitable for
238// consumption in 'Init()'.
239func (s *PKEYSigImpl) Bytes() []byte {
240 return s.sig.Bytes()
241}
diff --git a/src/gnunet/crypto/gns_test.go b/src/gnunet/crypto/gns_test.go
index ae39a2b..62a2dfd 100644
--- a/src/gnunet/crypto/gns_test.go
+++ b/src/gnunet/crypto/gns_test.go
@@ -20,100 +20,124 @@ package crypto
20 20
21import ( 21import (
22 "bytes" 22 "bytes"
23 "crypto/sha256"
24 "crypto/sha512"
23 "encoding/hex" 25 "encoding/hex"
26 "gnunet/util"
24 "testing" 27 "testing"
28 "time"
25 29
26 "github.com/bfix/gospel/crypto/ed25519" 30 "golang.org/x/crypto/hkdf"
27)
28
29var (
30 PUB = []byte{
31 0x23, 0xd8, 0x9a, 0x29, 0xda, 0x0f, 0x68, 0x08,
32 0xc6, 0xb6, 0xd5, 0xe5, 0x9c, 0xdd, 0x6a, 0x6f,
33 0xcf, 0x3e, 0x2b, 0xb0, 0x06, 0xf4, 0x66, 0xd5,
34 0x42, 0x3a, 0x93, 0x5d, 0x6b, 0x4d, 0x7e, 0x10,
35 }
36 LABEL = "home"
37) 31)
38 32
39func TestDeriveBlockKey(t *testing.T) { 33func TestDeriveBlockKey(t *testing.T) {
40 var ( 34 var (
41 SKEY = []byte{ 35 PUB = []byte{
36 0x23, 0xd8, 0x9a, 0x29, 0xda, 0x0f, 0x68, 0x08,
37 0xc6, 0xb6, 0xd5, 0xe5, 0x9c, 0xdd, 0x6a, 0x6f,
38 0xcf, 0x3e, 0x2b, 0xb0, 0x06, 0xf4, 0x66, 0xd5,
39 0x42, 0x3a, 0x93, 0x5d, 0x6b, 0x4d, 0x7e, 0x10,
40 }
41 LABEL = "home"
42 EXPIRE = util.NewAbsoluteTime(time.Unix(1643714700060589, 0))
43 SKEY = []byte{
42 0x0c, 0xf7, 0x4d, 0x44, 0x19, 0xe4, 0xac, 0x52, 44 0x0c, 0xf7, 0x4d, 0x44, 0x19, 0xe4, 0xac, 0x52,
43 0x3d, 0x14, 0xf4, 0x9b, 0x09, 0x6c, 0x52, 0xb6, 45 0x3d, 0x14, 0xf4, 0x9b, 0x09, 0x6c, 0x52, 0xb6,
44 0xb3, 0xf5, 0x06, 0x68, 0x98, 0x26, 0xa5, 0xea, 46 0xb3, 0xf5, 0x06, 0x68, 0x98, 0x26, 0xa5, 0xea,
45 0x06, 0x93, 0xfd, 0x4d, 0x80, 0xab, 0xf0, 0x44, 47 0x06, 0x93, 0xfd, 0x4d, 0x80, 0xab, 0xf0, 0x44,
46
47 0xa7, 0x6c, 0xc7, 0x81, 0x07, 0x3b, 0x94, 0x49,
48 0x91, 0x8e, 0xe0, 0x4c, 0x3a, 0x07, 0x56, 0x22,
49 0xe6, 0x95, 0xc3, 0xc7, 0x31, 0xc0, 0xfe, 0x62,
50 0xc3, 0x07, 0xe5, 0x9f, 0x96, 0xa2, 0xd0, 0x48,
51 } 48 }
52 IV = []byte{ 49 IV = []byte{
53 0x04, 0x41, 0xfc, 0xfc, 0x96, 0x5f, 0x2e, 0xa7, 50 0x04, 0x41, 0xfc, 0xfc,
54 0x35, 0xea, 0x59, 0xd8, 0x16, 0xd2, 0xfb, 0xc8, 51 0x1b, 0x1f, 0xb2, 0xee, 0x6f, 0x27, 0x85, 0x40,
55 52 0x00, 0x00, 0x00, 0x01,
56 0x6e, 0xdc, 0xb3, 0xdf, 0x0c, 0x28, 0xbb, 0x14,
57 0xc4, 0x51, 0x1c, 0x89, 0x9f, 0xb6, 0xdd, 0xfc,
58 } 53 }
59 ) 54 )
60 55
61 iv, skey := DeriveBlockKey(LABEL, ed25519.NewPublicKeyFromBytes(PUB)) 56 // create and initialize new public zone key (PKEY)
57 zkey := new(PKEYPublicImpl)
58 zkey.Init(PUB)
62 59
63 if bytes.Compare(IV[:16], iv.AESIv) != 0 { 60 // derive and check a key for symmetric cipher
64 t.Logf("AES_IV(computed) = %s\n", hex.EncodeToString(iv.AESIv)) 61 skey := zkey.BlockKey(LABEL, EXPIRE)
65 t.Logf("AES_IV(expected) = %s\n", hex.EncodeToString(IV[:16])) 62 if !bytes.Equal(IV, skey[32:]) {
63 t.Logf("AES_IV(computed) = %s\n", hex.EncodeToString(skey[32:]))
64 t.Logf("AES_IV(expected) = %s\n", hex.EncodeToString(IV))
66 t.Fatal("AES IV mismatch") 65 t.Fatal("AES IV mismatch")
67 } 66 }
68 if bytes.Compare(IV[16:], iv.TwofishIv) != 0 { 67 if !bytes.Equal(SKEY, skey[:32]) {
69 t.Logf("Twofish_IV(computed) = %s\n", hex.EncodeToString(iv.TwofishIv)) 68 t.Logf("AES_KEY(computed) = %s\n", hex.EncodeToString(skey[:32]))
70 t.Logf("Twofish_IV(expected) = %s\n", hex.EncodeToString(IV[16:])) 69 t.Logf("AES_KEY(expected) = %s\n", hex.EncodeToString(SKEY))
71 t.Fatal("Twofish IV mismatch")
72 }
73
74 if bytes.Compare(SKEY[:32], skey.AESKey) != 0 {
75 t.Logf("AES_KEY(computed) = %s\n", hex.EncodeToString(skey.AESKey))
76 t.Logf("AES_KEY(expected) = %s\n", hex.EncodeToString(SKEY[:32]))
77 t.Fatal("AES KEY mismatch") 70 t.Fatal("AES KEY mismatch")
78 } 71 }
79 if bytes.Compare(SKEY[32:], skey.TwofishKey) != 0 {
80 t.Logf("Twofish_KEY(computed) = %s\n", hex.EncodeToString(skey.TwofishKey))
81 t.Logf("Twofish_KEY(expected) = %s\n", hex.EncodeToString(SKEY[32:]))
82 t.Fatal("Twofish KEY mismatch")
83 }
84} 72}
85 73
86func TestDecryptBlock(t *testing.T) { 74func TestDecryptBlock(t *testing.T) {
87 var ( 75 var (
88 DATA = []byte{ 76 DATA = []byte{
89 0xf7, 0x61, 0x5f, 0x1f, 0xbc, 0x08, 0xb4, 0x32, 77 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0xe5, 0x3b,
90 0x46, 0xdb, 0x09, 0xb7, 0x57, 0x2d, 0x1c, 0x46, 78 0xe1, 0x93, 0x79, 0x91, 0x00, 0x00, 0x00, 0x04,
91 0xe2, 0xd8, 0xbf, 0x74, 0x17, 0x4e, 0x9a, 0x1e, 79 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
92 0xf0, 0x7a, 0xed, 0x45, 0x58, 0x62, 0x60, 0xc9, 80 0x01, 0x02, 0x03, 0x04, 0x00, 0x5c, 0xe4, 0xa5,
93 0xd7, 0xbd, 0x0d, 0x34, 0x6e, 0x08, 0xd8, 0x65, 81 0x39, 0x4a, 0xd9, 0x91, 0x00, 0x00, 0x00, 0x24,
94 0x69, 0x5c, 0x6d, 0x0b, 0xc6, 0x36, 0x73, 0x4c, 82 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
95 0xac, 0xd1, 0xf2, 0x38, 0x5e, 0x63, 0x86, 0x80, 83 0x00, 0x01, 0x00, 0x00, 0x0e, 0x60, 0x1b, 0xe4,
96 0x54, 0xa2, 0x1e, 0x94, 0x77, 0xd0, 0xa0, 0x50, 84 0x2e, 0xb5, 0x7f, 0xb4, 0x69, 0x76, 0x10, 0xcf,
97 0x96, 0xbb, 0x33, 0x4b, 85 0x3a, 0x3b, 0x18, 0x34, 0x7b, 0x65, 0xa3, 0x3f,
98 } 86 0x02, 0x5b, 0x5b, 0x17, 0x4a, 0xbe, 0xfb, 0x30,
99 OUT = []byte{ 87 0x80, 0x7b, 0xfe, 0xcf, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0xaf, 0x87, 88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x5b, 0x91, 0x40, 0x00, 0x00, 0x00, 0x17, 89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x0a, 0x04, 0x6d, 0x61, 0x69, 0x6c, 0x0a,
104 0x68, 0x6f, 0x69, 0x2d, 0x70, 0x6f, 0x6c, 0x6c,
105 0x6f, 0x69, 0x03, 0x6f, 0x72, 0x67, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 0x00, 0x00, 0x00, 0x00, 93 0x00, 0x00, 0x00, 0x00,
109 } 94 }
95 OUT = []byte{
96 0x00, 0xe4, 0x83, 0x7e, 0xb5, 0xd0, 0x4f, 0x92,
97 0x90, 0x3d, 0xe4, 0xb5, 0x23, 0x4e, 0x8c, 0xca,
98 0xc5, 0x73, 0x6c, 0x97, 0x93, 0x37, 0x9a, 0x59,
99 0xc3, 0x33, 0x75, 0xfc, 0x89, 0x51, 0xac, 0xa2,
100 0xeb, 0x7a, 0xad, 0x06, 0x7b, 0xf9, 0xaf, 0x60,
101 0xbf, 0x26, 0x75, 0x86, 0x46, 0xa1, 0x7f, 0x5e,
102 0x5c, 0x3b, 0x62, 0x15, 0xf9, 0x40, 0x79, 0x54,
103 0x5b, 0x1c, 0x4d, 0x4f, 0x1b, 0x2e, 0xbb, 0x22,
104 0xc2, 0xb4, 0xda, 0xd4, 0x41, 0x26, 0x81, 0x7b,
105 0x6f, 0x00, 0x15, 0x30, 0xd4, 0x76, 0x40, 0x1d,
106 0xd6, 0x7a, 0xc0, 0x14, 0x85, 0x54, 0xe8, 0x06,
107 0x35, 0x3d, 0xa9, 0xe4, 0x29, 0x80, 0x79, 0xf3,
108 0xe1, 0xb1, 0x69, 0x42, 0xc4, 0x8d, 0x90, 0xc4,
109 0x36, 0x0c, 0x61, 0x23, 0x8c, 0x40, 0xd9, 0xd5,
110 0x29, 0x11, 0xae, 0xa5, 0x2c, 0xc0, 0x03, 0x7a,
111 0xc7, 0x16, 0x0b, 0xb3, 0xcf, 0x5b, 0x2f, 0x4a,
112 0x72, 0x2f, 0xd9, 0x6b,
113 }
114 LABEL = "test"
115 EXPIRE = util.AbsoluteTime{
116 Val: uint64(14888744139323793),
117 }
118 PUB = []byte{
119 // zone type
120 0x00, 0x01, 0x00, 0x00,
121
122 // public key
123 0x67, 0x7c, 0x47, 0x7d, 0x2d, 0x93, 0x09, 0x7c,
124 0x85, 0xb1, 0x95, 0xc6, 0xf9, 0x6d, 0x84, 0xff,
125 0x61, 0xf5, 0x98, 0x2c, 0x2c, 0x4f, 0xe0, 0x2d,
126 0x5a, 0x11, 0xfe, 0xdf, 0xb0, 0xc2, 0x90, 0x1f,
127 }
110 ) 128 )
111 129
112 out, err := DecryptBlock(DATA, ed25519.NewPublicKeyFromBytes(PUB), LABEL) 130 // create and initialize new public zone key (PKEY)
131 zkey, err := NewZoneKey(PUB)
113 if err != nil { 132 if err != nil {
114 t.Fatal(err) 133 t.Fatal(err)
115 } 134 }
116 if bytes.Compare(out, OUT) != 0 { 135
136 out, err := zkey.Encrypt(DATA, LABEL, EXPIRE)
137 if err != nil {
138 t.Fatal(err)
139 }
140 if !bytes.Equal(out, OUT) {
117 t.Logf("Decrypt(computed) = %s\n", hex.EncodeToString(out)) 141 t.Logf("Decrypt(computed) = %s\n", hex.EncodeToString(out))
118 t.Logf("Decrypt(expected) = %s\n", hex.EncodeToString(OUT)) 142 t.Logf("Decrypt(expected) = %s\n", hex.EncodeToString(OUT))
119 t.Fatal("Decryptions failed") 143 t.Fatal("Decryptions failed")
@@ -136,33 +160,239 @@ func TestVerifyBlock(t *testing.T) {
136 0xf0, 0x4e, 0x3b, 0x70, 160 0xf0, 0x4e, 0x3b, 0x70,
137 } 161 }
138 SIG = []byte{ 162 SIG = []byte{
163 // zone type
164 0x00, 0x01, 0x00, 0x00,
165
166 // public key
167 0x26, 0x84, 0x1b, 0x24, 0x35, 0xa4, 0x63, 0xe9,
168 0xf0, 0x48, 0xae, 0x3e, 0xf7, 0xe8, 0x1b, 0xca,
169 0x55, 0x9f, 0x4c, 0x1e, 0x16, 0x18, 0xa6, 0xd3,
170 0x5b, 0x91, 0x0d, 0x54, 0x31, 0x6e, 0xbf, 0x97,
171
172 // signature
139 0x09, 0xc9, 0x6a, 0xda, 0x69, 0xce, 0x7c, 0x91, 173 0x09, 0xc9, 0x6a, 0xda, 0x69, 0xce, 0x7c, 0x91,
140 0xbd, 0xa4, 0x59, 0xdc, 0xc9, 0x76, 0xf4, 0x6c, 174 0xbd, 0xa4, 0x59, 0xdc, 0xc9, 0x76, 0xf4, 0x6c,
141 0x62, 0xb7, 0x79, 0x3f, 0x94, 0xb2, 0xf6, 0xf0, 175 0x62, 0xb7, 0x79, 0x3f, 0x94, 0xb2, 0xf6, 0xf0,
142 0x90, 0x17, 0x4e, 0x2f, 0x68, 0x49, 0xf8, 0xcc, 176 0x90, 0x17, 0x4e, 0x2f, 0x68, 0x49, 0xf8, 0xcc,
143
144 0x0b, 0x77, 0x32, 0x32, 0x28, 0x77, 0x2d, 0x2a, 177 0x0b, 0x77, 0x32, 0x32, 0x28, 0x77, 0x2d, 0x2a,
145 0x31, 0x31, 0xc1, 0x2c, 0x44, 0x18, 0xf2, 0x5f, 178 0x31, 0x31, 0xc1, 0x2c, 0x44, 0x18, 0xf2, 0x5f,
146 0x1a, 0xe9, 0x8b, 0x2e, 0x65, 0xca, 0x1d, 0xe8, 179 0x1a, 0xe9, 0x8b, 0x2e, 0x65, 0xca, 0x1d, 0xe8,
147 0x22, 0x82, 0x6a, 0x06, 0xe0, 0x6a, 0x5a, 0xe5, 180 0x22, 0x82, 0x6a, 0x06, 0xe0, 0x6a, 0x5a, 0xe5,
148 } 181 }
149 PUB = []byte{
150 0x26, 0x84, 0x1b, 0x24, 0x35, 0xa4, 0x63, 0xe9,
151 0xf0, 0x48, 0xae, 0x3e, 0xf7, 0xe8, 0x1b, 0xca,
152 0x55, 0x9f, 0x4c, 0x1e, 0x16, 0x18, 0xa6, 0xd3,
153 0x5b, 0x91, 0x0d, 0x54, 0x31, 0x6e, 0xbf, 0x97,
154 }
155 ) 182 )
156 sig, err := ed25519.NewEcSignatureFromBytes(SIG) 183
184 // instantiate and initialize signature
185 sig, err := NewZoneSignature(SIG)
157 if err != nil { 186 if err != nil {
158 t.Fatal(err) 187 t.Fatal(err)
159 } 188 }
160 dkey := ed25519.NewPublicKeyFromBytes(PUB) 189 // verify signature
161 ok, err := dkey.EcVerify(SIGNED, sig) 190 ok, err := sig.Verify(SIGNED)
162 if err != nil { 191 if err != nil {
163 t.Fatal(err) 192 t.Fatal(err)
164 } 193 }
165 if !ok { 194 if !ok {
166 t.Fatal("EcDSA verify failed") 195 t.Fatal("signature verify failed")
196 }
197}
198
199func TestDeriveH(t *testing.T) {
200 var (
201 D = []byte{
202 // private scalar (big-endian)
203 0x74, 0x50, 0xf7, 0x1d, 0xef, 0x64, 0x11, 0xe0,
204 0xab, 0x0e, 0x6a, 0x1d, 0xfd, 0x1d, 0x9c, 0xcd,
205 0x0e, 0xaf, 0x71, 0x95, 0x24, 0x94, 0xcc, 0xf5,
206 0x1b, 0x85, 0xff, 0xac, 0x5d, 0xb0, 0x93, 0xc8,
207 }
208 PUB = []byte{
209 // zone type
210 0x00, 0x01, 0x00, 0x00,
211 // public key data
212 0x23, 0xd8, 0x9a, 0x29, 0xda, 0x0f, 0x68, 0x08,
213 0xc6, 0xb6, 0xd5, 0xe5, 0x9c, 0xdd, 0x6a, 0x6f,
214 0xcf, 0x3e, 0x2b, 0xb0, 0x06, 0xf4, 0x66, 0xd5,
215 0x42, 0x3a, 0x93, 0x5d, 0x6b, 0x4d, 0x7e, 0x10,
216 }
217
218 ID = "000G0013V2D2KPGFD04CDDPNWPEDTTKFSWZ2QC06YHKDAGHTJDEPPKBY20"
219 LABEL = "home"
220 CONTEXT = "gns"
221
222 H = []byte{
223 0x07, 0x1e, 0xfc, 0xa7, 0xdb, 0x28, 0x50, 0xbd,
224 0x6f, 0x35, 0x4e, 0xbf, 0xe3, 0x8c, 0x5b, 0xbf,
225 0xd6, 0xba, 0x2f, 0x80, 0x5c, 0xd8, 0xd3, 0xb5,
226 0x4e, 0xdd, 0x7f, 0x3d, 0xd0, 0x73, 0x0d, 0x1a,
227 }
228 Q = []byte{
229 // zone type
230 0x00, 0x01, 0x00, 0x00,
231 // derived public key data
232 0x9f, 0x27, 0xad, 0x25, 0xb5, 0x95, 0x4a, 0x46,
233 0x7b, 0xc6, 0x5a, 0x67, 0x6b, 0x7a, 0x6d, 0x23,
234 0xb2, 0xef, 0x30, 0x0f, 0x7f, 0xc7, 0x00, 0x58,
235 0x05, 0x9e, 0x7f, 0x29, 0xe5, 0x94, 0xb5, 0xc1,
236 }
237 QUERY = []byte{
238 0xa9, 0x1a, 0x2c, 0x46, 0xf1, 0x98, 0x35, 0x50,
239 0x4f, 0x4e, 0x96, 0x78, 0x2d, 0x77, 0xd1, 0x3b,
240 0x9d, 0x4e, 0x61, 0xf3, 0x50, 0xe2, 0xe6, 0xa5,
241 0xc2, 0xd1, 0x36, 0xc1, 0xf1, 0x37, 0x94, 0x79,
242 0x19, 0xe9, 0xab, 0x2b, 0xae, 0xb5, 0xb9, 0x79,
243 0xe9, 0x1e, 0xf2, 0x6a, 0xaa, 0x54, 0x81, 0x65,
244 0xac, 0xb2, 0xec, 0xca, 0x8e, 0x30, 0x76, 0x1c,
245 0xc2, 0x1b, 0xbe, 0x89, 0x0b, 0x34, 0x6d, 0xa1,
246 }
247 )
248
249 // create private key from scalar
250 prv, err := NewZonePrivate(ZONE_PKEY, D)
251 if err != nil {
252 t.Fatal(err)
253 }
254
255 // derive and checkpublic key
256 pub := prv.Public()
257 if !bytes.Equal(pub.Bytes(), PUB) {
258 t.Fatal("wrong public key")
259 }
260
261 // test ID
262 id := pub.ID()
263 if ID != id {
264 t.Logf("id = %s\n", id)
265 t.Logf("ID = %s\n", ID)
266 t.Fatal("wrong ID")
267 }
268
269 // test key derivation
270 dpub, h := pub.Derive(LABEL, CONTEXT)
271 if !bytes.Equal(h.Bytes(), H) {
272 if testing.Verbose() {
273 t.Logf("H(computed) = %s\n", hex.EncodeToString(h.Bytes()))
274 t.Logf("H(expected) = %s\n", hex.EncodeToString(H))
275 }
276 t.Fatal("H mismatch")
277 }
278 // test derived key
279 q := dpub.Bytes()
280 if !bytes.Equal(q, Q) {
281 if testing.Verbose() {
282 t.Logf("derived (computed) = %s\n", hex.EncodeToString(q))
283 t.Logf("derived (expected) = %s\n", hex.EncodeToString(Q))
284 }
285 t.Fatal("x-coordinate mismatch")
286 }
287
288 // test query
289 out := sha512.Sum512(dpub.Bytes())
290 if !bytes.Equal(out[:], QUERY) {
291 if testing.Verbose() {
292 t.Log("query(computed) = " + hex.EncodeToString(out[:]))
293 t.Log("query(expected) = " + hex.EncodeToString(QUERY))
294 }
295 t.Fatal("Query mismatch")
296 }
297}
298
299func TestHKDF_gnunet(t *testing.T) {
300
301 var (
302 // SALT as defined in GNUnet
303 salt = []byte("key-derivation")
304 // expected PRK (as dumped in GNUnet)
305 PRK = []byte{
306 0xEB, 0xFE, 0x63, 0xBA, 0x68, 0x2D, 0xA5, 0x5C,
307 0xF8, 0x37, 0xCE, 0x8F, 0x94, 0x3B, 0x01, 0x44,
308 0x1B, 0xF9, 0x67, 0x3D, 0xFC, 0x91, 0xED, 0x61,
309 0x79, 0x94, 0xE8, 0x2A, 0x62, 0x0A, 0xE8, 0x6E,
310 0x59, 0xDB, 0x56, 0x63, 0x80, 0x94, 0x63, 0xAC,
311 0x8D, 0x35, 0xE2, 0xEA, 0xBA, 0xE6, 0xF3, 0xE8,
312 0xC1, 0x4B, 0xC9, 0x4F, 0xBD, 0xE3, 0xE6, 0x61,
313 0x01, 0xB3, 0xB2, 0x1C, 0x6F, 0x19, 0x73, 0x8B,
314 }
315 info = []byte("master-homegns")
316 // expected result (as dumped in GNUnet)
317 OKM = []byte{
318 0x30, 0x86, 0x34, 0x7F, 0x2E, 0x12, 0xD7, 0x65,
319 0x35, 0x70, 0x44, 0xE2, 0xF6, 0x9B, 0x84, 0x59,
320 0x6E, 0xE1, 0x7F, 0x62, 0x93, 0xAD, 0xAE, 0x56,
321 0x50, 0x6A, 0xA6, 0xD6, 0x8D, 0x39, 0x39, 0x95,
322 }
323 )
324 prk := hkdf.Extract(sha512.New, pub.Bytes(), salt)
325 if testing.Verbose() {
326 t.Log("PRK(computed) = " + hex.EncodeToString(prk))
327 }
328 if !bytes.Equal(prk, PRK) {
329 t.Log("PRK(expected) = " + hex.EncodeToString(PRK))
330 t.Fatal("PRK mismatch")
331 }
332
333 rdr := hkdf.Expand(sha256.New, prk, info)
334 okm := make([]byte, len(OKM))
335 rdr.Read(okm)
336 if testing.Verbose() {
337 t.Log("OKM(computed) = " + hex.EncodeToString(okm))
338 }
339 if !bytes.Equal(okm, OKM) {
340 t.Log("OKM(expected) = " + hex.EncodeToString(OKM))
341 t.Fatal("OKM mismatch")
342 }
343}
344
345func TestHDKF(t *testing.T) {
346 var (
347 ikm = []byte{
348 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
349 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
350 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
351 }
352 salt = []byte{
353 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
354 0x08, 0x09, 0x0a, 0x0b, 0x0c,
355 }
356 PRK = []byte{
357 0x66, 0x57, 0x99, 0x82, 0x37, 0x37, 0xde, 0xd0,
358 0x4a, 0x88, 0xe4, 0x7e, 0x54, 0xa5, 0x89, 0x0b,
359 0xb2, 0xc3, 0xd2, 0x47, 0xc7, 0xa4, 0x25, 0x4a,
360 0x8e, 0x61, 0x35, 0x07, 0x23, 0x59, 0x0a, 0x26,
361 0xc3, 0x62, 0x38, 0x12, 0x7d, 0x86, 0x61, 0xb8,
362 0x8c, 0xf8, 0x0e, 0xf8, 0x02, 0xd5, 0x7e, 0x2f,
363 0x7c, 0xeb, 0xcf, 0x1e, 0x00, 0xe0, 0x83, 0x84,
364 0x8b, 0xe1, 0x99, 0x29, 0xc6, 0x1b, 0x42, 0x37,
365 }
366 info = []byte{
367 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
368 }
369 OKM = []byte{
370 0x83, 0x23, 0x90, 0x08, 0x6c, 0xda, 0x71, 0xfb,
371 0x47, 0x62, 0x5b, 0xb5, 0xce, 0xb1, 0x68, 0xe4,
372 0xc8, 0xe2, 0x6a, 0x1a, 0x16, 0xed, 0x34, 0xd9,
373 0xfc, 0x7f, 0xe9, 0x2c, 0x14, 0x81, 0x57, 0x93,
374 0x38, 0xda, 0x36, 0x2c, 0xb8, 0xd9, 0xf9, 0x25,
375 0xd7, 0xcb,
376 }
377 )
378
379 prk := hkdf.Extract(sha512.New, ikm, salt)
380 if testing.Verbose() {
381 t.Log("PRK(computed) = " + hex.EncodeToString(prk))
382 }
383 if !bytes.Equal(prk, PRK) {
384 t.Log("PRK(expected) = " + hex.EncodeToString(PRK))
385 t.Fatal("PRK mismatch")
386 }
387
388 rdr := hkdf.Expand(sha512.New, prk, info)
389 okm := make([]byte, len(OKM))
390 rdr.Read(okm)
391 if testing.Verbose() {
392 t.Log("OKM(computed) = " + hex.EncodeToString(okm))
393 }
394 if !bytes.Equal(okm, OKM) {
395 t.Log("OKM(expected) = " + hex.EncodeToString(OKM))
396 t.Fatal("OKM mismatch")
167 } 397 }
168} 398}
diff --git a/src/gnunet/crypto/key_derivation.go b/src/gnunet/crypto/key_derivation.go
deleted file mode 100644
index 1481f70..0000000
--- a/src/gnunet/crypto/key_derivation.go
+++ /dev/null
@@ -1,50 +0,0 @@
1// This file is part of gnunet-go, a GNUnet-implementation in Golang.
2// Copyright (C) 2019, 2020 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 crypto
20
21import (
22 "crypto/sha256"
23 "crypto/sha512"
24
25 "github.com/bfix/gospel/crypto/ed25519"
26 "github.com/bfix/gospel/math"
27 "golang.org/x/crypto/hkdf"
28)
29
30// Curve parameters
31var (
32 ED25519_N = ed25519.GetCurve().N
33)
34
35// DeriveH derives an integer 'h' from the arguments.
36func DeriveH(pub *ed25519.PublicKey, label, context string) *math.Int {
37 prk := hkdf.Extract(sha512.New, pub.Bytes(), []byte("key-derivation"))
38 data := append([]byte(label), []byte(context)...)
39 rdr := hkdf.Expand(sha256.New, prk, data)
40 b := make([]byte, 64)
41 rdr.Read(b)
42 return math.NewIntFromBytes(b).Mod(ED25519_N)
43}
44
45// DerivePublicKey "shifts" a public key 'Q' to a new point 'P' where
46// P = h*Q with 'h' being a factor derived from the arguments.
47func DerivePublicKey(pub *ed25519.PublicKey, label string, context string) *ed25519.PublicKey {
48 h := DeriveH(pub, label, context)
49 return pub.Mult(h)
50}
diff --git a/src/gnunet/crypto/key_derivation_test.go b/src/gnunet/crypto/key_derivation_test.go
deleted file mode 100644
index 4692c19..0000000
--- a/src/gnunet/crypto/key_derivation_test.go
+++ /dev/null
@@ -1,228 +0,0 @@
1// This file is part of gnunet-go, a GNUnet-implementation in Golang.
2// Copyright (C) 2019, 2020 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 crypto
20
21import (
22 "bytes"
23 "crypto/sha256"
24 "crypto/sha512"
25 "encoding/hex"
26 "testing"
27
28 "github.com/bfix/gospel/crypto/ed25519"
29 "github.com/bfix/gospel/math"
30 "gnunet/util"
31 "golang.org/x/crypto/hkdf"
32)
33
34func TestDeriveH(t *testing.T) {
35 var (
36 D = []byte{
37 0x74, 0x50, 0xf7, 0x1d, 0xef, 0x64, 0x11, 0xe0,
38 0xab, 0x0e, 0x6a, 0x1d, 0xfd, 0x1d, 0x9c, 0xcd,
39 0x0e, 0xaf, 0x71, 0x95, 0x24, 0x94, 0xcc, 0xf5,
40 0x1b, 0x85, 0xff, 0xac, 0x5d, 0xb0, 0x93, 0xc8,
41 }
42
43 ID = "4FC9MAET1XM0HHNPTQJSSQBADZ7KWAXG0VT6DNA27A9NTTTDFR80"
44 LABEL = "home"
45 CONTEXT = "gns"
46
47 H = []byte{
48 0x07, 0x1e, 0xfc, 0xa7, 0xdb, 0x28, 0x50, 0xbd,
49 0x6f, 0x35, 0x4e, 0xbf, 0xe3, 0x8c, 0x5b, 0xbf,
50 0xd6, 0xba, 0x2f, 0x80, 0x5c, 0xd8, 0xd3, 0xb5,
51 0x4e, 0xdd, 0x7f, 0x3d, 0xd0, 0x73, 0x0d, 0x1a,
52 }
53 Q = []byte{
54 0x9f, 0x27, 0xad, 0x25, 0xb5, 0x95, 0x4a, 0x46,
55 0x7b, 0xc6, 0x5a, 0x67, 0x6b, 0x7a, 0x6d, 0x23,
56 0xb2, 0xef, 0x30, 0x0f, 0x7f, 0xc7, 0x00, 0x58,
57 0x05, 0x9e, 0x7f, 0x29, 0xe5, 0x94, 0xb5, 0xc1,
58 }
59 QUERY = []byte{
60 0xd1, 0x8e, 0x5e, 0xff, 0xf7, 0x64, 0x6f, 0x9c,
61 0x87, 0xdb, 0x4f, 0xf5, 0xe9, 0x8d, 0xf8, 0xf5,
62 0x3d, 0x57, 0xb7, 0xa8, 0x13, 0x27, 0x1a, 0x48,
63 0x8f, 0xd8, 0x4e, 0x9e, 0x4e, 0xca, 0xe9, 0x26,
64 0x36, 0xab, 0x83, 0x1b, 0xd1, 0x7c, 0xd7, 0xe6,
65 0xc8, 0x79, 0xd0, 0x4e, 0x8a, 0x91, 0xb5, 0x55,
66 0x70, 0xa9, 0x4a, 0x6f, 0xef, 0x9e, 0xcf, 0x3c,
67 0x70, 0x20, 0x7f, 0x69, 0xa4, 0xa8, 0x38, 0x7a,
68 }
69 )
70
71 // compute keypair from seed
72 prv := ed25519.NewPrivateKeyFromD(math.NewIntFromBytes(D))
73 pub := prv.Public()
74 if bytes.Compare(pub.Bytes(), PUB) != 0 {
75 t.Fatal("Wrong public key")
76 }
77 ego := util.EncodeBinaryToString(pub.Bytes())
78 if ID != ego {
79 t.Logf("EGO = %s\n", ego)
80 t.Fatal("Wrong ego ID")
81 }
82
83 hBuf := make([]byte, 32)
84 hFull := DeriveH(pub, LABEL, CONTEXT)
85 h := hFull.Mod(ED25519_N)
86 util.CopyBlock(hBuf, h.Bytes())
87 if bytes.Compare(hBuf, H) != 0 {
88 if testing.Verbose() {
89 t.Logf("H(computed) = %s\n", hex.EncodeToString(hBuf))
90 t.Logf("H(expected) = %s\n", hex.EncodeToString(H))
91 }
92 t.Fatal("H mismatch")
93 }
94
95 dpub := pub.Mult(h)
96 dpub2 := DerivePublicKey(pub, LABEL, CONTEXT)
97 if !dpub.Q.Equals(dpub2.Q) {
98 t.Fatal("Q mismatch")
99 }
100
101 q := dpub.Q.Bytes()
102 if bytes.Compare(q, Q) != 0 {
103 if testing.Verbose() {
104 t.Logf("derived_x(computed) = %s\n", hex.EncodeToString(q))
105 t.Logf("derived_x(expected) = %s\n", hex.EncodeToString(Q))
106 }
107 t.Fatal("x-coordinate mismatch")
108 }
109 pk1 := dpub.Bytes()
110 pk2 := DerivePublicKey(pub, LABEL, CONTEXT).Bytes()
111 if bytes.Compare(pk1, pk2) != 0 {
112 if testing.Verbose() {
113 t.Logf("derived(1) = %s\n", hex.EncodeToString(pk1))
114 t.Logf("derived(2) = %s\n", hex.EncodeToString(pk2))
115 }
116 t.Fatal("Derived key mismatch")
117 }
118
119 out := sha512.Sum512(pk1)
120 if bytes.Compare(out[:], QUERY) != 0 {
121 if testing.Verbose() {
122 t.Log("query(expected) = " + hex.EncodeToString(QUERY))
123 t.Log("query(computed) = " + hex.EncodeToString(out[:]))
124 }
125 t.Fatal("Query mismatch")
126 }
127}
128
129func TestHKDF_gnunet(t *testing.T) {
130
131 var (
132 // SALT as defined in GNUnet
133 salt = []byte("key-derivation")
134 // expected PRK (as dumped in GNUnet)
135 PRK = []byte{
136 0xEB, 0xFE, 0x63, 0xBA, 0x68, 0x2D, 0xA5, 0x5C,
137 0xF8, 0x37, 0xCE, 0x8F, 0x94, 0x3B, 0x01, 0x44,
138 0x1B, 0xF9, 0x67, 0x3D, 0xFC, 0x91, 0xED, 0x61,
139 0x79, 0x94, 0xE8, 0x2A, 0x62, 0x0A, 0xE8, 0x6E,
140 0x59, 0xDB, 0x56, 0x63, 0x80, 0x94, 0x63, 0xAC,
141 0x8D, 0x35, 0xE2, 0xEA, 0xBA, 0xE6, 0xF3, 0xE8,
142 0xC1, 0x4B, 0xC9, 0x4F, 0xBD, 0xE3, 0xE6, 0x61,
143 0x01, 0xB3, 0xB2, 0x1C, 0x6F, 0x19, 0x73, 0x8B,
144 }
145 info = []byte("master-homegns")
146 // expected result (as dumped in GNUnet)
147 OKM = []byte{
148 0x30, 0x86, 0x34, 0x7F, 0x2E, 0x12, 0xD7, 0x65,
149 0x35, 0x70, 0x44, 0xE2, 0xF6, 0x9B, 0x84, 0x59,
150 0x6E, 0xE1, 0x7F, 0x62, 0x93, 0xAD, 0xAE, 0x56,
151 0x50, 0x6A, 0xA6, 0xD6, 0x8D, 0x39, 0x39, 0x95,
152 }
153 )
154 prk := hkdf.Extract(sha512.New, pub.Bytes(), salt)
155 if testing.Verbose() {
156 t.Log("PRK(computed) = " + hex.EncodeToString(prk))
157 }
158 if bytes.Compare(prk, PRK) != 0 {
159 t.Log("PRK(expected) = " + hex.EncodeToString(PRK))
160 t.Fatal("PRK mismatch")
161 }
162
163 rdr := hkdf.Expand(sha256.New, prk, info)
164 okm := make([]byte, len(OKM))
165 rdr.Read(okm)
166 if testing.Verbose() {
167 t.Log("OKM(computed) = " + hex.EncodeToString(okm))
168 }
169 if bytes.Compare(okm, OKM) != 0 {
170 t.Log("OKM(expected) = " + hex.EncodeToString(OKM))
171 t.Fatal("OKM mismatch")
172 }
173}
174
175func TestHDKF(t *testing.T) {
176 var (
177 ikm = []byte{
178 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
179 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
180 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
181 }
182 salt = []byte{
183 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
184 0x08, 0x09, 0x0a, 0x0b, 0x0c,
185 }
186 PRK = []byte{
187 0x66, 0x57, 0x99, 0x82, 0x37, 0x37, 0xde, 0xd0,
188 0x4a, 0x88, 0xe4, 0x7e, 0x54, 0xa5, 0x89, 0x0b,
189 0xb2, 0xc3, 0xd2, 0x47, 0xc7, 0xa4, 0x25, 0x4a,
190 0x8e, 0x61, 0x35, 0x07, 0x23, 0x59, 0x0a, 0x26,
191 0xc3, 0x62, 0x38, 0x12, 0x7d, 0x86, 0x61, 0xb8,
192 0x8c, 0xf8, 0x0e, 0xf8, 0x02, 0xd5, 0x7e, 0x2f,
193 0x7c, 0xeb, 0xcf, 0x1e, 0x00, 0xe0, 0x83, 0x84,
194 0x8b, 0xe1, 0x99, 0x29, 0xc6, 0x1b, 0x42, 0x37,
195 }
196 info = []byte{
197 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
198 }
199 OKM = []byte{
200 0x83, 0x23, 0x90, 0x08, 0x6c, 0xda, 0x71, 0xfb,
201 0x47, 0x62, 0x5b, 0xb5, 0xce, 0xb1, 0x68, 0xe4,
202 0xc8, 0xe2, 0x6a, 0x1a, 0x16, 0xed, 0x34, 0xd9,
203 0xfc, 0x7f, 0xe9, 0x2c, 0x14, 0x81, 0x57, 0x93,
204 0x38, 0xda, 0x36, 0x2c, 0xb8, 0xd9, 0xf9, 0x25,
205 0xd7, 0xcb,
206 }
207 )
208
209 prk := hkdf.Extract(sha512.New, ikm, salt)
210 if testing.Verbose() {
211 t.Log("PRK(computed) = " + hex.EncodeToString(prk))
212 }
213 if bytes.Compare(prk, PRK) != 0 {
214 t.Log("PRK(expected) = " + hex.EncodeToString(PRK))
215 t.Fatal("PRK mismatch")
216 }
217
218 rdr := hkdf.Expand(sha512.New, prk, info)
219 okm := make([]byte, len(OKM))
220 rdr.Read(okm)
221 if testing.Verbose() {
222 t.Log("OKM(computed) = " + hex.EncodeToString(okm))
223 }
224 if bytes.Compare(okm, OKM) != 0 {
225 t.Log("OKM(expected) = " + hex.EncodeToString(OKM))
226 t.Fatal("OKM mismatch")
227 }
228}
diff --git a/src/gnunet/crypto/key_exchange_test.go b/src/gnunet/crypto/key_exchange_test.go
index 3696cae..a433ec3 100644
--- a/src/gnunet/crypto/key_exchange_test.go
+++ b/src/gnunet/crypto/key_exchange_test.go
@@ -57,6 +57,8 @@ var (
57 prv_1, prv_2 *ed25519.PrivateKey 57 prv_1, prv_2 *ed25519.PrivateKey
58 pub_1, pub_2 *ed25519.PublicKey 58 pub_1, pub_2 *ed25519.PublicKey
59 ss_1, ss_2 []byte 59 ss_1, ss_2 []byte
60
61 ED25519_N = ed25519.GetCurve().N
60) 62)
61 63
62func calcSharedSecret() bool { 64func calcSharedSecret() bool {
@@ -67,7 +69,7 @@ func calcSharedSecret() bool {
67 // compute shared secret 69 // compute shared secret
68 ss_1 = calc(prv_1, pub_2) 70 ss_1 = calc(prv_1, pub_2)
69 ss_2 = calc(prv_2, pub_1) 71 ss_2 = calc(prv_2, pub_1)
70 return bytes.Compare(ss_1, ss_2) == 0 72 return bytes.Equal(ss_1, ss_2)
71} 73}
72 74
73func TestDHE(t *testing.T) { 75func TestDHE(t *testing.T) {
@@ -85,12 +87,11 @@ func TestDHE(t *testing.T) {
85 t.Logf("SS_2 = %s\n", hex.EncodeToString(ss_2)) 87 t.Logf("SS_2 = %s\n", hex.EncodeToString(ss_2))
86 } 88 }
87 89
88 if bytes.Compare(ss_1[:], ss) != 0 { 90 if !bytes.Equal(ss_1[:], ss) {
89 t.Logf("SS(expected) = %s\n", hex.EncodeToString(ss)) 91 t.Logf("SS(expected) = %s\n", hex.EncodeToString(ss))
90 t.Logf("SS(computed) = %s\n", hex.EncodeToString(ss_1[:])) 92 t.Logf("SS(computed) = %s\n", hex.EncodeToString(ss_1[:]))
91 t.Fatal("Wrong shared secret:") 93 t.Fatal("Wrong shared secret:")
92 } 94 }
93
94} 95}
95 96
96func TestDHERandom(t *testing.T) { 97func TestDHERandom(t *testing.T) {
diff --git a/src/gnunet/crypto/symmetric.go b/src/gnunet/crypto/symmetric.go
deleted file mode 100644
index c217c6d..0000000
--- a/src/gnunet/crypto/symmetric.go
+++ /dev/null
@@ -1,108 +0,0 @@
1// This file is part of gnunet-go, a GNUnet-implementation in Golang.
2// Copyright (C) 2019, 2020 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 crypto
20
21import (
22 "crypto/aes"
23 "crypto/cipher"
24 "crypto/rand"
25
26 "golang.org/x/crypto/twofish"
27)
28
29// Symmetric encryption in GNUnet uses a two-layer scheme:
30// * Encryption: OUT = twofish_cfb(aes_cfb(IN))
31// * Decryption: OUT = aes_cfb(twofish_cfb(IN))
32
33// SymmetricKey is a key for the GNUnet-specific two-layer encryption scheme.
34type SymmetricKey struct {
35 AESKey []byte `size:"32"` // key for AES-CFB
36 TwofishKey []byte `size:"32"` // key for Twofish-CFB
37}
38
39// NewSymmetricKey generates a new (random) symmetric key.
40func NewSymmetricKey() *SymmetricKey {
41 skey := &SymmetricKey{
42 AESKey: make([]byte, 32),
43 TwofishKey: make([]byte, 32),
44 }
45 rand.Read(skey.AESKey)
46 rand.Read(skey.TwofishKey)
47 return skey
48}
49
50// SymmetricIV is an initialization vector for the GNUnet-specific two-layer
51// encryption scheme.
52type SymmetricIV struct {
53 AESIv []byte `size:"16"` // IV for AES-CFB
54 TwofishIv []byte `size:"16"` // IV for Twofish-CFB
55}
56
57// NewSymmetricIV generates a new (random) initialization vector.
58func NewSymmetricIV() *SymmetricIV {
59 iv := &SymmetricIV{
60 AESIv: make([]byte, 16),
61 TwofishIv: make([]byte, 16),
62 }
63 rand.Read(iv.AESIv)
64 rand.Read(iv.TwofishIv)
65 return iv
66}
67
68// SymmetricDecrypt decrypts the data with given key and initialization vector.
69func SymmetricDecrypt(data []byte, skey *SymmetricKey, iv *SymmetricIV) ([]byte, error) {
70 // Decrypt with Twofish CFB stream cipher
71 tf, err := twofish.NewCipher(skey.TwofishKey)
72 if err != nil {
73 return nil, err
74 }
75 stream := cipher.NewCFBDecrypter(tf, iv.TwofishIv)
76 out := make([]byte, len(data))
77 stream.XORKeyStream(out, data)
78
79 // Decrypt with AES CFB stream cipher
80 aes, err := aes.NewCipher(skey.AESKey)
81 if err != nil {
82 return nil, err
83 }
84 stream = cipher.NewCFBDecrypter(aes, iv.AESIv)
85 stream.XORKeyStream(out, out)
86 return out, nil
87}
88
89// SymmetricEncrypt encrypts the data with given key and initialization vector.
90func SymmetricEncrypt(data []byte, skey *SymmetricKey, iv *SymmetricIV) ([]byte, error) {
91 // Encrypt with AES CFB stream cipher
92 aes, err := aes.NewCipher(skey.AESKey)
93 if err != nil {
94 return nil, err
95 }
96 stream := cipher.NewCFBEncrypter(aes, iv.AESIv)
97 out := make([]byte, len(data))
98 stream.XORKeyStream(out, data)
99
100 // Encrypt with Twofish CFB stream cipher
101 tf, err := twofish.NewCipher(skey.TwofishKey)
102 if err != nil {
103 return nil, err
104 }
105 stream = cipher.NewCFBEncrypter(tf, iv.TwofishIv)
106 stream.XORKeyStream(out, out)
107 return out, nil
108}
diff --git a/src/gnunet/enums/gns.go b/src/gnunet/enums/gns.go
index 6ba6f65..af9bbc7 100644
--- a/src/gnunet/enums/gns.go
+++ b/src/gnunet/enums/gns.go
@@ -85,6 +85,7 @@ var (
85 GNS_TYPE_RECLAIM_MASTER = 65551 // Record type for RECLAIM master 85 GNS_TYPE_RECLAIM_MASTER = 65551 // Record type for RECLAIM master
86 GNS_TYPE_RECLAIM_OIDC_CLIENT = 65552 // Record type for reclaim OIDC clients 86 GNS_TYPE_RECLAIM_OIDC_CLIENT = 65552 // Record type for reclaim OIDC clients
87 GNS_TYPE_RECLAIM_OIDC_REDIRECT = 65553 // Record type for reclaim OIDC redirect URIs 87 GNS_TYPE_RECLAIM_OIDC_REDIRECT = 65553 // Record type for reclaim OIDC redirect URIs
88 GNS_TYPE_EDKEY = 65556 // Record type for GNS zone transfer ("EDKEY").
88 89
89 GNS_TYPE = map[int]string{ 90 GNS_TYPE = map[int]string{
90 GNS_TYPE_ANY: "GNS_TYPE_ANY", 91 GNS_TYPE_ANY: "GNS_TYPE_ANY",
diff --git a/src/gnunet/go.mod b/src/gnunet/go.mod
index 443666f..8527379 100644
--- a/src/gnunet/go.mod
+++ b/src/gnunet/go.mod
@@ -1,9 +1,21 @@
1module gnunet 1module gnunet
2 2
3go 1.12 3go 1.17
4 4
5require ( 5require (
6 github.com/bfix/gospel v0.0.0-20200326093412-d1b2381f0c46 6 github.com/bfix/gospel v1.2.10
7 github.com/go-redis/redis/v8 v8.5.0
8 github.com/go-sql-driver/mysql v1.5.0
9 github.com/gorilla/mux v1.8.0
10 github.com/mattn/go-sqlite3 v1.14.6
7 github.com/miekg/dns v1.1.26 11 github.com/miekg/dns v1.1.26
8 golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 12 golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed
13)
14
15require (
16 github.com/cespare/xxhash/v2 v2.1.1 // indirect
17 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
18 go.opentelemetry.io/otel v0.16.0 // indirect
19 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
20 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
9) 21)
diff --git a/src/gnunet/go.sum b/src/gnunet/go.sum
index 8c956b4..4fa501c 100644
--- a/src/gnunet/go.sum
+++ b/src/gnunet/go.sum
@@ -1,30 +1,123 @@
1github.com/bfix/gospel v0.0.0-20190922182041-6fcd6d4fd449 h1:oIq3s14sMh1sq791v9VpR+GJvhVGbvuOWlfTjruRTDQ= 1github.com/bfix/gospel v1.2.10 h1:a8l/sET2y+FVKIO5M1l5hdTlqLxstvkhp+b6FpAkxOU=
2github.com/bfix/gospel v0.0.0-20190922182041-6fcd6d4fd449/go.mod h1:RQYETFV9SP+VriIsHVqCntRpSbbRvCBnNTtbUl9NAKA= 2github.com/bfix/gospel v1.2.10/go.mod h1:cdu63bA9ZdfeDoqZ+vnWOcbY9Puwdzmf5DMxMGMznRI=
3github.com/bfix/gospel v0.0.0-20200326093412-d1b2381f0c46 h1:5aNd1/ISbO1ltgmyUGza7kdaN4fD/Qal6uKZk9goMhw= 3github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
4github.com/bfix/gospel v0.0.0-20200326093412-d1b2381f0c46/go.mod h1:RQYETFV9SP+VriIsHVqCntRpSbbRvCBnNTtbUl9NAKA= 4github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
5github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
6github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
8github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
9github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
10github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
11github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
12github.com/go-redis/redis/v8 v8.5.0 h1:L3r1Q3I5WOUdXZGCP6g44EruKh0u3n6co5Hl5xWkdGA=
13github.com/go-redis/redis/v8 v8.5.0/go.mod h1:YmEcgBDttjnkbMzDAhDtQxY9yVA7jMN6PCR5HeMvqFE=
14github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
15github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
16github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
17github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
18github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
19github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
20github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
21github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
22github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
23github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
24github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
25github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
26github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
27github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
28github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
29github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
30github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
31github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
32github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
33github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
34github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
5github.com/miekg/dns v1.1.26 h1:gPxPSwALAeHJSjarOs00QjVdV9QoBvc1D2ujQUr5BzU= 35github.com/miekg/dns v1.1.26 h1:gPxPSwALAeHJSjarOs00QjVdV9QoBvc1D2ujQUr5BzU=
6github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= 36github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
37github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
38github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
39github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
40github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
41github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4=
42github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
43github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
44github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
45github.com/onsi/gomega v1.10.5 h1:7n6FEkpFmfCoo2t+YYqXH0evK+a9ICQz0xcAy9dYcaQ=
46github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
47github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
48github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
49github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
50github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
51github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
52github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
53go.opentelemetry.io/otel v0.16.0 h1:uIWEbdeb4vpKPGITLsRVUS44L5oDbDUCZxn8lkxhmgw=
54go.opentelemetry.io/otel v0.16.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA=
7golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 55golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
8golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM=
9golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
10golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
11golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= 56golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
12golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= 57golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
13golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 58golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
59golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
60golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed h1:YoWVYYAfvQ4ddHv3OKmIvX7NCAhFGTj62VP2l2kfBbA=
61golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
62golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
63golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
64golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
14golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 65golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
15golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 66golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
16golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
17golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 67golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
18golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= 68golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
69golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
70golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
71golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
72golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
73golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
19golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 74golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
75golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
76golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
77golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
20golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 78golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
21golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 79golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
80golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
22golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 81golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
23golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
24golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 82golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
83golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
84golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
85golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
86golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
87golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
88golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
89golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
90golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
91golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
92golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
93golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
94golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
25golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 95golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
26golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
27golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 96golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
97golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
98golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
99golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
100golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
28golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 101golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
29golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 102golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
103golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
104golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
30golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 105golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
106golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
107golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
108golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
109google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
110google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
111google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
112google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
113google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
114google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
115gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
116gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
117gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
118gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
119gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
120gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
121gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
122gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
123gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/src/gnunet/message/const.go b/src/gnunet/message/const.go
index b706478..b07d211 100644
--- a/src/gnunet/message/const.go
+++ b/src/gnunet/message/const.go
@@ -29,27 +29,27 @@ var (
29 // external addresses change an adversary cannot replay them indefinitely. 29 // external addresses change an adversary cannot replay them indefinitely.
30 // OTOH, we don't want to spend too much time generating PONG signatures, 30 // OTOH, we don't want to spend too much time generating PONG signatures,
31 // so they must have some lifetime to reduce our CPU usage. 31 // so they must have some lifetime to reduce our CPU usage.
32 PONG_SIGNATURE_LIFETIME = 1 * time.Hour 32 PongSignatureLifetime = 1 * time.Hour
33 33
34 // After how long do we expire an address in a HELLO that we just 34 // After how long do we expire an address in a HELLO that we just
35 // validated? This value is also used for our own addresses when we 35 // validated? This value is also used for our own addresses when we
36 // create a HELLO. 36 // create a HELLO.
37 HELLO_ADDRESS_EXPIRATION = 12 * time.Hour 37 HelloAddressExpiration = 12 * time.Hour
38 38
39 // How often do we allow PINGing an address that we have not yet 39 // How often do we allow PINGing an address that we have not yet
40 // validated? This also determines how long we track an address that 40 // validated? This also determines how long we track an address that
41 // we cannot validate (because after this time we can destroy the 41 // we cannot validate (because after this time we can destroy the
42 // validation record). 42 // validation record).
43 UNVALIDATED_PING_KEEPALIVE = 5 * time.Minute 43 UnvalidatedPingKeepAlive = 5 * time.Minute
44 44
45 // How often do we PING an address that we have successfully validated 45 // How often do we PING an address that we have successfully validated
46 // in the past but are not actively using? Should be (significantly) 46 // in the past but are not actively using? Should be (significantly)
47 // smaller than HELLO_ADDRESS_EXPIRATION. 47 // smaller than HELLO_ADDRESS_EXPIRATION.
48 VALIDATED_PING_FREQUENCY = 15 * time.Minute 48 ValidatedPingFrequency = 15 * time.Minute
49 49
50 // How often do we PING an address that we are currently using? 50 // How often do we PING an address that we are currently using?
51 CONNECTED_PING_FREQUENCY = 2 * time.Minute 51 ConnectedPingFrequency = 2 * time.Minute
52 52
53 // How much delay is acceptable for sending the PING or PONG? 53 // How much delay is acceptable for sending the PING or PONG?
54 ACCEPTABLE_PING_DELAY = 1 * time.Second 54 AcceptablePingDelay = 1 * time.Second
55) 55)
diff --git a/src/gnunet/message/factory.go b/src/gnunet/message/factory.go
index 68a24d5..8cbf9ce 100644
--- a/src/gnunet/message/factory.go
+++ b/src/gnunet/message/factory.go
@@ -19,7 +19,6 @@
19package message 19package message
20 20
21import ( 21import (
22 "errors"
23 "fmt" 22 "fmt"
24) 23)
25 24
@@ -30,7 +29,7 @@ func NewEmptyMessage(msgType uint16) (Message, error) {
30 // Transport 29 // Transport
31 //------------------------------------------------------------------ 30 //------------------------------------------------------------------
32 case TRANSPORT_TCP_WELCOME: 31 case TRANSPORT_TCP_WELCOME:
33 return NewTransportTcpWelcomeMsg(nil), nil 32 return NewTransportTCPWelcomeMsg(nil), nil
34 case HELLO: 33 case HELLO:
35 return NewHelloMsg(nil), nil 34 return NewHelloMsg(nil), nil
36 case TRANSPORT_SESSION_QUOTA: 35 case TRANSPORT_SESSION_QUOTA:
@@ -92,9 +91,9 @@ func NewEmptyMessage(msgType uint16) (Message, error) {
92 case REVOCATION_QUERY_RESPONSE: 91 case REVOCATION_QUERY_RESPONSE:
93 return NewRevocationQueryResponseMsg(true), nil 92 return NewRevocationQueryResponseMsg(true), nil
94 case REVOCATION_REVOKE: 93 case REVOCATION_REVOKE:
95 return NewRevocationRevokeMsg(nil, nil), nil 94 return NewRevocationRevokeMsg(nil), nil
96 case REVOCATION_REVOKE_RESPONSE: 95 case REVOCATION_REVOKE_RESPONSE:
97 return NewRevocationRevokeResponseMsg(false), nil 96 return NewRevocationRevokeResponseMsg(false), nil
98 } 97 }
99 return nil, errors.New(fmt.Sprintf("Unknown message type %d", msgType)) 98 return nil, fmt.Errorf("unknown message type %d", msgType)
100} 99}
diff --git a/src/gnunet/message/message.go b/src/gnunet/message/message.go
index fb9b4b0..1b826d7 100644
--- a/src/gnunet/message/message.go
+++ b/src/gnunet/message/message.go
@@ -31,33 +31,33 @@ var (
31 31
32// Message is an interface for all GNUnet-specific messages. 32// Message is an interface for all GNUnet-specific messages.
33type Message interface { 33type Message interface {
34 Header() *MessageHeader 34 Header() *Header
35} 35}
36 36
37// MessageHeader encapsulates the common part of all GNUnet messages (at the 37// Header encapsulates the common part of all GNUnet messages (at the
38// beginning of the data). 38// beginning of the data).
39type MessageHeader struct { 39type Header struct {
40 MsgSize uint16 `order:"big"` 40 MsgSize uint16 `order:"big"`
41 MsgType uint16 `order:"big"` 41 MsgType uint16 `order:"big"`
42} 42}
43 43
44// Size returns the total size of the message (header + body) 44// Size returns the total size of the message (header + body)
45func (mh *MessageHeader) Size() uint16 { 45func (mh *Header) Size() uint16 {
46 return mh.MsgSize 46 return mh.MsgSize
47} 47}
48 48
49// Type returns the message type (defines the layout of the body data) 49// Type returns the message type (defines the layout of the body data)
50func (mh *MessageHeader) Type() uint16 { 50func (mh *Header) Type() uint16 {
51 return mh.MsgType 51 return mh.MsgType
52} 52}
53 53
54// GetMsgHeader returns the header of a message from a byte array (as the 54// GetMsgHeader returns the header of a message from a byte array (as the
55// serialized form). 55// serialized form).
56func GetMsgHeader(b []byte) (mh *MessageHeader, err error) { 56func GetMsgHeader(b []byte) (mh *Header, err error) {
57 if b == nil || len(b) < 4 { 57 if b == nil || len(b) < 4 {
58 return nil, ErrMsgHeaderTooSmall 58 return nil, ErrMsgHeaderTooSmall
59 } 59 }
60 mh = new(MessageHeader) 60 mh = new(Header)
61 err = data.Unmarshal(mh, b) 61 err = data.Unmarshal(mh, b)
62 return 62 return
63} 63}
diff --git a/src/gnunet/message/msg_core.go b/src/gnunet/message/msg_core.go
index d6d427b..90c8804 100644
--- a/src/gnunet/message/msg_core.go
+++ b/src/gnunet/message/msg_core.go
@@ -80,8 +80,8 @@ func (m *EphemeralKeyMsg) String() string {
80} 80}
81 81
82// Header returns the message header in a separate instance. 82// Header returns the message header in a separate instance.
83func (msg *EphemeralKeyMsg) Header() *MessageHeader { 83func (m *EphemeralKeyMsg) Header() *Header {
84 return &MessageHeader{msg.MsgSize, msg.MsgType} 84 return &Header{m.MsgSize, m.MsgType}
85} 85}
86 86
87// Public extracts the public key of an announcing peer. 87// Public extracts the public key of an announcing peer.
@@ -105,9 +105,9 @@ func (m *EphemeralKeyMsg) Verify(pub *ed25519.PublicKey) (bool, error) {
105 105
106// NewEphemeralKey creates a new ephemeral key signed by a long-term private 106// NewEphemeralKey creates a new ephemeral key signed by a long-term private
107// key and the corresponding GNUnet message to announce the new key. 107// key and the corresponding GNUnet message to announce the new key.
108func NewEphemeralKey(peerId []byte, ltPrv *ed25519.PrivateKey) (*ed25519.PrivateKey, *EphemeralKeyMsg, error) { 108func NewEphemeralKey(peerID []byte, ltPrv *ed25519.PrivateKey) (*ed25519.PrivateKey, *EphemeralKeyMsg, error) {
109 msg := NewEphemeralKeyMsg() 109 msg := NewEphemeralKeyMsg()
110 copy(msg.SignedBlock.PeerID.Key, peerId) 110 copy(msg.SignedBlock.PeerID.Key, peerID)
111 seed := util.NewRndArray(32) 111 seed := util.NewRndArray(32)
112 prv := ed25519.NewPrivateKeyFromSeed(seed) 112 prv := ed25519.NewPrivateKeyFromSeed(seed)
113 copy(msg.SignedBlock.EphemeralKey, prv.Public().Bytes()) 113 copy(msg.SignedBlock.EphemeralKey, prv.Public().Bytes())
diff --git a/src/gnunet/message/msg_dht.go b/src/gnunet/message/msg_dht.go
index 62a233f..9b73557 100644
--- a/src/gnunet/message/msg_dht.go
+++ b/src/gnunet/message/msg_dht.go
@@ -31,7 +31,7 @@ import (
31// DHT_CLIENT_GET 31// DHT_CLIENT_GET
32//---------------------------------------------------------------------- 32//----------------------------------------------------------------------
33 33
34// DHTClientGetMsg 34// DHTClientGetMsg is the message for getting values from the DHT
35type DHTClientGetMsg struct { 35type DHTClientGetMsg struct {
36 MsgSize uint16 `order:"big"` // total size of message 36 MsgSize uint16 `order:"big"` // total size of message
37 MsgType uint16 `order:"big"` // DHT_CLIENT_GET (143) 37 MsgType uint16 `order:"big"` // DHT_CLIENT_GET (143)
@@ -39,7 +39,7 @@ type DHTClientGetMsg struct {
39 ReplLevel uint32 `order:"big"` // Replication level for this message 39 ReplLevel uint32 `order:"big"` // Replication level for this message
40 Type uint32 `order:"big"` // The type for the data for the GET request (BLOCK_TYPE_???) 40 Type uint32 `order:"big"` // The type for the data for the GET request (BLOCK_TYPE_???)
41 Key *crypto.HashCode // The key to search for 41 Key *crypto.HashCode // The key to search for
42 Id uint64 `order:"big"` // Unique ID identifying this request 42 ID uint64 `order:"big"` // Unique ID identifying this request
43 XQuery []byte `size:"*"` // Optional xquery 43 XQuery []byte `size:"*"` // Optional xquery
44} 44}
45 45
@@ -55,12 +55,12 @@ func NewDHTClientGetMsg(key *crypto.HashCode) *DHTClientGetMsg {
55 ReplLevel: 1, 55 ReplLevel: 1,
56 Type: uint32(enums.BLOCK_TYPE_ANY), 56 Type: uint32(enums.BLOCK_TYPE_ANY),
57 Key: key, 57 Key: key,
58 Id: 0, 58 ID: 0,
59 XQuery: nil, 59 XQuery: nil,
60 } 60 }
61} 61}
62 62
63// Set a (new) XQuery in this message and return previous XQuery. 63// SetXQuery sets a (new) XQuery in this message and return previous XQuery.
64func (m *DHTClientGetMsg) SetXQuery(xq []byte) []byte { 64func (m *DHTClientGetMsg) SetXQuery(xq []byte) []byte {
65 prev := m.XQuery 65 prev := m.XQuery
66 m.MsgSize -= uint16(len(prev)) 66 m.MsgSize -= uint16(len(prev))
@@ -72,26 +72,26 @@ func (m *DHTClientGetMsg) SetXQuery(xq []byte) []byte {
72// String returns a human-readable representation of the message. 72// String returns a human-readable representation of the message.
73func (m *DHTClientGetMsg) String() string { 73func (m *DHTClientGetMsg) String() string {
74 return fmt.Sprintf("DHTClientGetMsg{Id:%d,Type=%d,Options=%d,Repl=%d,Key=%s}", 74 return fmt.Sprintf("DHTClientGetMsg{Id:%d,Type=%d,Options=%d,Repl=%d,Key=%s}",
75 m.Id, m.Type, m.Options, m.ReplLevel, hex.EncodeToString(m.Key.Bits)) 75 m.ID, m.Type, m.Options, m.ReplLevel, hex.EncodeToString(m.Key.Bits))
76} 76}
77 77
78// Header returns the message header in a separate instance. 78// Header returns the message header in a separate instance.
79func (msg *DHTClientGetMsg) Header() *MessageHeader { 79func (m *DHTClientGetMsg) Header() *Header {
80 return &MessageHeader{msg.MsgSize, msg.MsgType} 80 return &Header{m.MsgSize, m.MsgType}
81} 81}
82 82
83//---------------------------------------------------------------------- 83//----------------------------------------------------------------------
84// DHT_CLIENT_RESULT 84// DHT_CLIENT_RESULT
85//---------------------------------------------------------------------- 85//----------------------------------------------------------------------
86 86
87// DHTClientResultMsg 87// DHTClientResultMsg is a message for DHT results
88type DHTClientResultMsg struct { 88type DHTClientResultMsg struct {
89 MsgSize uint16 `order:"big"` // total size of message 89 MsgSize uint16 `order:"big"` // total size of message
90 MsgType uint16 `order:"big"` // DHT_CLIENT_RESULT (145) 90 MsgType uint16 `order:"big"` // DHT_CLIENT_RESULT (145)
91 Type uint32 `order:"big"` // The type for the data 91 Type uint32 `order:"big"` // The type for the data
92 PutPathLen uint32 `order:"big"` // Number of peers recorded in outgoing path 92 PutPathLen uint32 `order:"big"` // Number of peers recorded in outgoing path
93 GetPathLen uint32 `order:"big"` // Number of peers recorded from storage location 93 GetPathLen uint32 `order:"big"` // Number of peers recorded from storage location
94 Id uint64 `order:"big"` // Unique ID of the matching GET request 94 ID uint64 `order:"big"` // Unique ID of the matching GET request
95 Expire util.AbsoluteTime // Expiration time 95 Expire util.AbsoluteTime // Expiration time
96 Key *crypto.HashCode // The key that was searched for 96 Key *crypto.HashCode // The key that was searched for
97 PutPath []*util.PeerID `size:"PutPathLen"` // put path 97 PutPath []*util.PeerID `size:"PutPathLen"` // put path
@@ -110,7 +110,7 @@ func NewDHTClientResultMsg(key *crypto.HashCode) *DHTClientResultMsg {
110 Type: 0, 110 Type: 0,
111 PutPathLen: 0, 111 PutPathLen: 0,
112 GetPathLen: 0, 112 GetPathLen: 0,
113 Id: 0, 113 ID: 0,
114 Expire: *new(util.AbsoluteTime), 114 Expire: *new(util.AbsoluteTime),
115 Key: key, 115 Key: key,
116 Data: make([]byte, 0), 116 Data: make([]byte, 0),
@@ -119,24 +119,24 @@ func NewDHTClientResultMsg(key *crypto.HashCode) *DHTClientResultMsg {
119 119
120// String returns a human-readable representation of the message. 120// String returns a human-readable representation of the message.
121func (m *DHTClientResultMsg) String() string { 121func (m *DHTClientResultMsg) String() string {
122 return fmt.Sprintf("DHTClientResultMsg{id:%d,expire=%s}", m.Id, m.Expire) 122 return fmt.Sprintf("DHTClientResultMsg{id:%d,expire=%s}", m.ID, m.Expire)
123} 123}
124 124
125// Header returns the message header in a separate instance. 125// Header returns the message header in a separate instance.
126func (msg *DHTClientResultMsg) Header() *MessageHeader { 126func (m *DHTClientResultMsg) Header() *Header {
127 return &MessageHeader{msg.MsgSize, msg.MsgType} 127 return &Header{m.MsgSize, m.MsgType}
128} 128}
129 129
130//---------------------------------------------------------------------- 130//----------------------------------------------------------------------
131// DHT_CLIENT_GET_STOP 131// DHT_CLIENT_GET_STOP
132//---------------------------------------------------------------------- 132//----------------------------------------------------------------------
133 133
134// DHTClientGetStopMsg 134// DHTClientGetStopMsg stops a pending DHT operation
135type DHTClientGetStopMsg struct { 135type DHTClientGetStopMsg struct {
136 MsgSize uint16 `order:"big"` // total size of message 136 MsgSize uint16 `order:"big"` // total size of message
137 MsgType uint16 `order:"big"` // DHT_CLIENT_GET_STOP (144) 137 MsgType uint16 `order:"big"` // DHT_CLIENT_GET_STOP (144)
138 Reserved uint32 `order:"big"` // Reserved (0) 138 Reserved uint32 `order:"big"` // Reserved (0)
139 Id uint64 `order:"big"` // Unique ID identifying this request 139 ID uint64 `order:"big"` // Unique ID identifying this request
140 Key *crypto.HashCode // The key to search for 140 Key *crypto.HashCode // The key to search for
141} 141}
142 142
@@ -149,17 +149,17 @@ func NewDHTClientGetStopMsg(key *crypto.HashCode) *DHTClientGetStopMsg {
149 MsgSize: 80, 149 MsgSize: 80,
150 MsgType: DHT_CLIENT_GET_STOP, 150 MsgType: DHT_CLIENT_GET_STOP,
151 Reserved: 0, // mandatory 151 Reserved: 0, // mandatory
152 Id: 0, 152 ID: 0,
153 Key: key, 153 Key: key,
154 } 154 }
155} 155}
156 156
157// String returns a human-readable representation of the message. 157// String returns a human-readable representation of the message.
158func (m *DHTClientGetStopMsg) String() string { 158func (m *DHTClientGetStopMsg) String() string {
159 return fmt.Sprintf("DHTClientGetStopMsg{Id:%d,Key=%s}", m.Id, hex.EncodeToString(m.Key.Bits)) 159 return fmt.Sprintf("DHTClientGetStopMsg{Id:%d,Key=%s}", m.ID, hex.EncodeToString(m.Key.Bits))
160} 160}
161 161
162// Header returns the message header in a separate instance. 162// Header returns the message header in a separate instance.
163func (msg *DHTClientGetStopMsg) Header() *MessageHeader { 163func (m *DHTClientGetStopMsg) Header() *Header {
164 return &MessageHeader{msg.MsgSize, msg.MsgType} 164 return &Header{m.MsgSize, m.MsgType}
165} 165}
diff --git a/src/gnunet/message/msg_gns.go b/src/gnunet/message/msg_gns.go
index fb84502..35630d6 100644
--- a/src/gnunet/message/msg_gns.go
+++ b/src/gnunet/message/msg_gns.go
@@ -25,11 +25,11 @@ import (
25 "gnunet/enums" 25 "gnunet/enums"
26 "gnunet/util" 26 "gnunet/util"
27 27
28 "github.com/bfix/gospel/crypto/ed25519"
29 "github.com/bfix/gospel/data" 28 "github.com/bfix/gospel/data"
30 "github.com/bfix/gospel/logger" 29 "github.com/bfix/gospel/logger"
31) 30)
32 31
32// Error messages
33var ( 33var (
34 ErrBlockNotDecrypted = fmt.Errorf("GNS block not decrypted") 34 ErrBlockNotDecrypted = fmt.Errorf("GNS block not decrypted")
35) 35)
@@ -38,25 +38,25 @@ var (
38// GNS_LOOKUP 38// GNS_LOOKUP
39//---------------------------------------------------------------------- 39//----------------------------------------------------------------------
40 40
41// GNSLookupMsg 41// LookupMsg is a request message for a GNS name lookup
42type GNSLookupMsg struct { 42type LookupMsg struct {
43 MsgSize uint16 `order:"big"` // total size of message 43 MsgSize uint16 `order:"big"` // total size of message
44 MsgType uint16 `order:"big"` // GNS_LOOKUP (500) 44 MsgType uint16 `order:"big"` // GNS_LOOKUP (500)
45 Id uint32 `order:"big"` // Unique identifier for this request (for key collisions). 45 ID uint32 `order:"big"` // Unique identifier for this request (for key collisions).
46 Zone []byte `size:"32"` // Zone that is to be used for lookup 46 Zone *crypto.ZoneKey `` // Zone that is to be used for lookup
47 Options uint16 `order:"big"` // Local options for where to look for results 47 Options uint16 `order:"big"` // Local options for where to look for results
48 Reserved uint16 `order:"big"` // Always 0 48 Reserved uint16 `order:"big"` // Always 0
49 Type uint32 `order:"big"` // the type of record to look up 49 Type uint32 `order:"big"` // the type of record to look up
50 Name []byte `size:"*"` // zero-terminated name to look up 50 Name []byte `size:"*"` // zero-terminated name to look up
51} 51}
52 52
53// NewGNSLookupMsg creates a new default message. 53// NewGNSLookupMsg creates a new default message.
54func NewGNSLookupMsg() *GNSLookupMsg { 54func NewGNSLookupMsg() *LookupMsg {
55 return &GNSLookupMsg{ 55 return &LookupMsg{
56 MsgSize: 48, // record size with no name 56 MsgSize: 48, // record size with no name
57 MsgType: GNS_LOOKUP, 57 MsgType: GNS_LOOKUP,
58 Id: 0, 58 ID: 0,
59 Zone: make([]byte, 32), 59 Zone: nil,
60 Options: uint16(enums.GNS_LO_DEFAULT), 60 Options: uint16(enums.GNS_LO_DEFAULT),
61 Reserved: 0, 61 Reserved: 0,
62 Type: uint32(enums.GNS_TYPE_ANY), 62 Type: uint32(enums.GNS_TYPE_ANY),
@@ -65,81 +65,105 @@ func NewGNSLookupMsg() *GNSLookupMsg {
65} 65}
66 66
67// SetName appends the name to lookup to the message 67// SetName appends the name to lookup to the message
68func (m *GNSLookupMsg) SetName(name string) { 68func (m *LookupMsg) SetName(name string) {
69 m.Name = util.Clone(append([]byte(name), 0)) 69 m.Name = util.Clone(append([]byte(name), 0))
70 m.MsgSize = uint16(48 + len(m.Name)) 70 m.MsgSize = uint16(48 + len(m.Name))
71} 71}
72 72
73// GetName returns the name to lookup from the message 73// GetName returns the name to lookup from the message
74func (m *GNSLookupMsg) GetName() string { 74func (m *LookupMsg) GetName() string {
75 size := len(m.Name) 75 size := len(m.Name)
76 if m.Name[size-1] != 0 { 76 if m.Name[size-1] != 0 {
77 logger.Println(logger.WARN, "GNS_LOOKUP name not NULL-terminated") 77 logger.Println(logger.WARN, "GNS_LOOKUP name not NULL-terminated")
78 } else { 78 } else {
79 size -= 1 79 size--
80 } 80 }
81 return string(m.Name[:size]) 81 return string(m.Name[:size])
82} 82}
83 83
84// String returns a human-readable representation of the message. 84// String returns a human-readable representation of the message.
85func (m *GNSLookupMsg) String() string { 85func (m *LookupMsg) String() string {
86 return fmt.Sprintf( 86 return fmt.Sprintf(
87 "GNSLookupMsg{Id=%d,Zone=%s,Options=%d,Type=%d,Name=%s}", 87 "GNSLookupMsg{Id=%d,Zone=%s,Options=%d,Type=%d,Name=%s}",
88 m.Id, util.EncodeBinaryToString(m.Zone), 88 m.ID, m.Zone.ID(), m.Options, m.Type, m.GetName())
89 m.Options, m.Type, m.GetName())
90} 89}
91 90
92// Header returns the message header in a separate instance. 91// Header returns the message header in a separate instance.
93func (msg *GNSLookupMsg) Header() *MessageHeader { 92func (m *LookupMsg) Header() *Header {
94 return &MessageHeader{msg.MsgSize, msg.MsgType} 93 return &Header{m.MsgSize, m.MsgType}
95} 94}
96 95
97//---------------------------------------------------------------------- 96//----------------------------------------------------------------------
98// GNS_LOOKUP_RESULT 97// GNS_LOOKUP_RESULT
99//---------------------------------------------------------------------- 98//----------------------------------------------------------------------
100 99
101// GNSRecordSet ist the GNUnet data structure for a list of resource records 100// RecordSet ist the GNUnet data structure for a list of resource records
102// in a GNSBlock. As part of GNUnet messages, the record set is padded so that 101// in a GNSBlock. As part of GNUnet messages, the record set is padded so that
103// the binary size of (records||padding) is the smallest power of two. 102// the binary size of (records||padding) is the smallest power of two.
104type GNSRecordSet struct { 103type RecordSet struct {
105 Count uint32 `order:"big"` // number of resource records 104 Count uint32 `order:"big"` // number of resource records
106 Records []*GNSResourceRecord `size:"Count"` // list of resource records 105 Records []*ResourceRecord `size:"Count"` // list of resource records
107 Padding []byte `size:"*"` // padding 106 Padding []byte `size:"*"` // padding
108} 107}
109 108
110// NewGNSRecordSet returns an empty resource record set. 109// NewRecordSet returns an empty resource record set.
111func NewGNSRecordSet() *GNSRecordSet { 110func NewRecordSet() *RecordSet {
112 return &GNSRecordSet{ 111 return &RecordSet{
113 Count: 0, 112 Count: 0,
114 Records: make([]*GNSResourceRecord, 0), 113 Records: make([]*ResourceRecord, 0),
115 Padding: make([]byte, 0), 114 Padding: make([]byte, 0),
116 } 115 }
117} 116}
118 117
119// AddRecord to append a resource record to the set. 118// AddRecord to append a resource record to the set.
120func (rs *GNSRecordSet) AddRecord(rec *GNSResourceRecord) { 119func (rs *RecordSet) AddRecord(rec *ResourceRecord) {
121 rs.Count++ 120 rs.Count++
122 rs.Records = append(rs.Records, rec) 121 rs.Records = append(rs.Records, rec)
123} 122}
124 123
125// SignedBlockData: signed and encrypted list of resource records stored 124// SetPadding (re-)calculates and allocates the padding.
126// in a GNSRecordSet 125func (rs *RecordSet) SetPadding() {
126 size := 0
127 for _, rr := range rs.Records {
128 size += int(rr.Size) + 20
129 }
130 n := 1
131 for n < size {
132 n <<= 1
133 }
134 rs.Padding = make([]byte, n-size)
135}
136
137// Expires returns the earliest expiration timestamp for the records.
138func (rs *RecordSet) Expires() util.AbsoluteTime {
139 var expires util.AbsoluteTime
140 for i, rr := range rs.Records {
141 if i == 0 {
142 expires = rr.Expires
143 } else if rr.Expires.Compare(expires) < 0 {
144 expires = rr.Expires
145 }
146 }
147 return expires
148}
149
150// SignedBlockData represents the signed and encrypted list of resource
151// records stored in a GNSRecordSet
127type SignedBlockData struct { 152type SignedBlockData struct {
128 Purpose *crypto.SignaturePurpose // Size and purpose of signature (8 bytes) 153 Purpose *crypto.SignaturePurpose `` // Size and purpose of signature (8 bytes)
129 Expire util.AbsoluteTime // Expiration time of the block. 154 Expire util.AbsoluteTime `` // Expiration time of the block.
130 EncData []byte `size:"*"` // encrypted GNSRecordSet 155 EncData []byte `size:"*"` // encrypted GNSRecordSet
131 156
132 // transient data (not serialized) 157 // transient data (not serialized)
133 data []byte // decrypted GNSRecord set 158 data []byte // decrypted GNSRecord set
134} 159}
135 160
136// GNSBlock is the result of GNS lookups for a given label in a zone. 161// Block is the result of GNS lookups for a given label in a zone.
137// An encrypted and signed container for GNS resource records that represents 162// An encrypted and signed container for GNS resource records that represents
138// the "atomic" data structure associated with a GNS label in a given zone. 163// the "atomic" data structure associated with a GNS label in a given zone.
139type GNSBlock struct { 164type Block struct {
140 Signature []byte `size:"64"` // Signature of the block. 165 DerivedKeySig *crypto.ZoneSignature // Derived key used for signing
141 DerivedKey []byte `size:"32"` // Derived key used for signing 166 Block *SignedBlockData
142 Block *SignedBlockData
143 167
144 // transient data (not serialized) 168 // transient data (not serialized)
145 checked bool // block integrity checked 169 checked bool // block integrity checked
@@ -148,19 +172,19 @@ type GNSBlock struct {
148} 172}
149 173
150// String returns the human-readable representation of a GNSBlock 174// String returns the human-readable representation of a GNSBlock
151func (b *GNSBlock) String() string { 175func (b *Block) String() string {
152 return fmt.Sprintf("GNSBlock{Verified=%v,Decrypted=%v,data=[%d]}", 176 return fmt.Sprintf("GNSBlock{Verified=%v,Decrypted=%v,data=[%d]}",
153 b.verified, b.decrypted, len(b.Block.EncData)) 177 b.verified, b.decrypted, len(b.Block.EncData))
154} 178}
155 179
156// Records returns the list of resource records in a block. 180// Records returns the list of resource records in a block.
157func (b *GNSBlock) Records() ([]*GNSResourceRecord, error) { 181func (b *Block) Records() ([]*ResourceRecord, error) {
158 // check if block is decrypted 182 // check if block is decrypted
159 if !b.decrypted { 183 if !b.decrypted {
160 return nil, ErrBlockNotDecrypted 184 return nil, ErrBlockNotDecrypted
161 } 185 }
162 // parse block data into record set 186 // parse block data into record set
163 rs := NewGNSRecordSet() 187 rs := NewRecordSet()
164 if err := data.Unmarshal(rs, b.Block.data); err != nil { 188 if err := data.Unmarshal(rs, b.Block.data); err != nil {
165 return nil, err 189 return nil, err
166 } 190 }
@@ -168,48 +192,37 @@ func (b *GNSBlock) Records() ([]*GNSResourceRecord, error) {
168} 192}
169 193
170// Verify the integrity of the block data from a signature. 194// Verify the integrity of the block data from a signature.
171func (b *GNSBlock) Verify(zoneKey *ed25519.PublicKey, label string) (err error) { 195func (b *Block) Verify(zkey *crypto.ZoneKey, label string) (err error) {
172 // Integrity check performed 196 // Integrity check performed
173 b.checked = true 197 b.checked = true
174 198
175 // verify derived key 199 // verify derived key
176 dkey := ed25519.NewPublicKeyFromBytes(b.DerivedKey) 200 dkey := b.DerivedKeySig.ZoneKey
177 dkey2 := crypto.DerivePublicKey(zoneKey, label, "gns") 201 dkey2, _ := zkey.Derive(label, "gns")
178 if !dkey.Q.Equals(dkey2.Q) { 202 if !dkey.Equal(dkey2) {
179 return fmt.Errorf("Invalid signature key for GNS Block") 203 return fmt.Errorf("invalid signature key for GNS Block")
180 } 204 }
181 // verify signature 205 // verify signature
182 var ( 206 var buf []byte
183 sig *ed25519.EcSignature
184 buf []byte
185 ok bool
186 )
187 if sig, err = ed25519.NewEcSignatureFromBytes(b.Signature); err != nil {
188 return
189 }
190 if buf, err = data.Marshal(b.Block); err != nil { 207 if buf, err = data.Marshal(b.Block); err != nil {
191 return 208 return
192 } 209 }
193 if ok, err = dkey.EcVerify(buf, sig); err == nil && !ok { 210 b.verified, err = b.DerivedKeySig.Verify(buf)
194 err = fmt.Errorf("Signature verification failed for GNS block")
195 }
196 b.verified = true
197 return 211 return
198} 212}
199 213
200// Decrypt block data with a key/iv combination derived from (PKEY,label) 214// Decrypt block data with a key derived from zone key and label.
201func (b *GNSBlock) Decrypt(zoneKey *ed25519.PublicKey, label string) (err error) { 215func (b *Block) Decrypt(zkey *crypto.ZoneKey, label string) (err error) {
202 // decrypt payload 216 // decrypt payload
203 b.Block.data, err = crypto.DecryptBlock(b.Block.EncData, zoneKey, label) 217 b.Block.data, err = zkey.Decrypt(b.Block.EncData, label, b.Block.Expire)
204 b.decrypted = true 218 b.decrypted = true
205 return 219 return
206} 220}
207 221
208// NewGNSBlock instantiates an empty GNS block 222// NewBlock instantiates an empty GNS block
209func NewGNSBlock() *GNSBlock { 223func NewBlock() *Block {
210 return &GNSBlock{ 224 return &Block{
211 Signature: make([]byte, 64), 225 DerivedKeySig: nil,
212 DerivedKey: make([]byte, 32),
213 Block: &SignedBlockData{ 226 Block: &SignedBlockData{
214 Purpose: new(crypto.SignaturePurpose), 227 Purpose: new(crypto.SignaturePurpose),
215 Expire: *new(util.AbsoluteTime), 228 Expire: *new(util.AbsoluteTime),
@@ -222,9 +235,9 @@ func NewGNSBlock() *GNSBlock {
222 } 235 }
223} 236}
224 237
225// GNSResourceRecord is the GNUnet-specific representation of resource 238// ResourceRecord is the GNUnet-specific representation of resource
226// records (not to be confused with DNS resource records). 239// records (not to be confused with DNS resource records).
227type GNSResourceRecord struct { 240type ResourceRecord struct {
228 Expires util.AbsoluteTime // Expiration time for the record 241 Expires util.AbsoluteTime // Expiration time for the record
229 Size uint32 `order:"big"` // Number of bytes in 'Data' 242 Size uint32 `order:"big"` // Number of bytes in 'Data'
230 Type uint32 `order:"big"` // Type of the GNS/DNS record 243 Type uint32 `order:"big"` // Type of the GNS/DNS record
@@ -233,33 +246,33 @@ type GNSResourceRecord struct {
233} 246}
234 247
235// String returns a human-readable representation of the message. 248// String returns a human-readable representation of the message.
236func (r *GNSResourceRecord) String() string { 249func (r *ResourceRecord) String() string {
237 return fmt.Sprintf("GNSResourceRecord{type=%s,expire=%s,flags=%d,size=%d}", 250 return fmt.Sprintf("GNSResourceRecord{type=%s,expire=%s,flags=%d,size=%d}",
238 enums.GNS_TYPE[int(r.Type)], r.Expires, r.Flags, r.Size) 251 enums.GNS_TYPE[int(r.Type)], r.Expires, r.Flags, r.Size)
239} 252}
240 253
241// GNSLookupResultMsg 254// LookupResultMsg is a response message for a GNS name lookup request
242type GNSLookupResultMsg struct { 255type LookupResultMsg struct {
243 MsgSize uint16 `order:"big"` // total size of message 256 MsgSize uint16 `order:"big"` // total size of message
244 MsgType uint16 `order:"big"` // GNS_LOOKUP_RESULT (501) 257 MsgType uint16 `order:"big"` // GNS_LOOKUP_RESULT (501)
245 Id uint32 `order:"big"` // Unique identifier for this request (for key collisions). 258 ID uint32 `order:"big"` // Unique identifier for this request (for key collisions).
246 Count uint32 `order:"big"` // The number of records contained in response 259 Count uint32 `order:"big"` // The number of records contained in response
247 Records []*GNSResourceRecord `size:"Count"` // GNS resource records 260 Records []*ResourceRecord `size:"Count"` // GNS resource records
248} 261}
249 262
250// NewGNSLookupResultMsg 263// NewGNSLookupResultMsg returns a new lookup result message
251func NewGNSLookupResultMsg(id uint32) *GNSLookupResultMsg { 264func NewGNSLookupResultMsg(id uint32) *LookupResultMsg {
252 return &GNSLookupResultMsg{ 265 return &LookupResultMsg{
253 MsgSize: 12, // Empty result (no records) 266 MsgSize: 12, // Empty result (no records)
254 MsgType: GNS_LOOKUP_RESULT, 267 MsgType: GNS_LOOKUP_RESULT,
255 Id: id, 268 ID: id,
256 Count: 0, 269 Count: 0,
257 Records: make([]*GNSResourceRecord, 0), 270 Records: make([]*ResourceRecord, 0),
258 } 271 }
259} 272}
260 273
261// AddRecord adds a GNS resource recordto the response message. 274// AddRecord adds a GNS resource recordto the response message.
262func (m *GNSLookupResultMsg) AddRecord(rec *GNSResourceRecord) error { 275func (m *LookupResultMsg) AddRecord(rec *ResourceRecord) error {
263 recSize := 20 + int(rec.Size) 276 recSize := 20 + int(rec.Size)
264 if int(m.MsgSize)+recSize > enums.GNS_MAX_BLOCK_SIZE { 277 if int(m.MsgSize)+recSize > enums.GNS_MAX_BLOCK_SIZE {
265 return fmt.Errorf("gns.AddRecord(): MAX_BLOCK_SIZE reached") 278 return fmt.Errorf("gns.AddRecord(): MAX_BLOCK_SIZE reached")
@@ -271,11 +284,11 @@ func (m *GNSLookupResultMsg) AddRecord(rec *GNSResourceRecord) error {
271} 284}
272 285
273// String returns a human-readable representation of the message. 286// String returns a human-readable representation of the message.
274func (m *GNSLookupResultMsg) String() string { 287func (m *LookupResultMsg) String() string {
275 return fmt.Sprintf("GNSLookupResultMsg{Id=%d,Count=%d}", m.Id, m.Count) 288 return fmt.Sprintf("GNSLookupResultMsg{Id=%d,Count=%d}", m.ID, m.Count)
276} 289}
277 290
278// Header returns the message header in a separate instance. 291// Header returns the message header in a separate instance.
279func (msg *GNSLookupResultMsg) Header() *MessageHeader { 292func (m *LookupResultMsg) Header() *Header {
280 return &MessageHeader{msg.MsgSize, msg.MsgType} 293 return &Header{m.MsgSize, m.MsgType}
281} 294}
diff --git a/src/gnunet/message/msg_gns_test.go b/src/gnunet/message/msg_gns_test.go
new file mode 100644
index 0000000..ff985c3
--- /dev/null
+++ b/src/gnunet/message/msg_gns_test.go
@@ -0,0 +1,353 @@
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 message
20
21import (
22 "bytes"
23 "encoding/hex"
24 "gnunet/crypto"
25 "gnunet/enums"
26 "gnunet/util"
27 "testing"
28
29 "github.com/bfix/gospel/data"
30)
31
32// TestRecordsetPKEY implements the test case as defined in the GNS draft
33// (see section 13. Test vectors, case "PKEY")
34func TestRecordsetPKEY(t *testing.T) {
35 var (
36 D = []byte{
37 // PKEY private scalar
38 0x50, 0xd7, 0xb6, 0x52, 0xa4, 0xef, 0xea, 0xdf,
39 0xf3, 0x73, 0x96, 0x90, 0x97, 0x85, 0xe5, 0x95,
40 0x21, 0x71, 0xa0, 0x21, 0x78, 0xc8, 0xe7, 0xd4,
41 0x50, 0xfa, 0x90, 0x79, 0x25, 0xfa, 0xfd, 0x98,
42 }
43 ZKEY = []byte{
44 // zone type
45 0x00, 0x01, 0x00, 0x00,
46 // PKEY public key
47 0x67, 0x7c, 0x47, 0x7d, 0x2d, 0x93, 0x09, 0x7c,
48 0x85, 0xb1, 0x95, 0xc6, 0xf9, 0x6d, 0x84, 0xff,
49 0x61, 0xf5, 0x98, 0x2c, 0x2c, 0x4f, 0xe0, 0x2d,
50 0x5a, 0x11, 0xfe, 0xdf, 0xb0, 0xc2, 0x90, 0x1f,
51 }
52 ZID = "000G0037FH3QTBCK15Y8BCCNRVWPV17ZC7TSGB1C9ZG2TPGHZVFV1GMG3W"
53 RECSET = &RecordSet{
54 Count: 2,
55 Records: []*ResourceRecord{
56 {
57 Expires: util.AbsoluteTime{
58 Val: uint64(14888744139323793),
59 },
60 Size: 4,
61 Type: 1,
62 Flags: 0,
63 Data: []byte{
64 0x01, 0x02, 0x03, 0x04,
65 },
66 },
67 {
68 Expires: util.AbsoluteTime{
69 Val: uint64(26147096139323793),
70 },
71 Size: 36,
72 Type: crypto.ZONE_PKEY,
73 Flags: 2,
74 Data: []byte{
75 0x00, 0x01, 0x00, 0x00,
76 0x0e, 0x60, 0x1b, 0xe4, 0x2e, 0xb5, 0x7f, 0xb4,
77 0x69, 0x76, 0x10, 0xcf, 0x3a, 0x3b, 0x18, 0x34,
78 0x7b, 0x65, 0xa3, 0x3f, 0x02, 0x5b, 0x5b, 0x17,
79 0x4a, 0xbe, 0xfb, 0x30, 0x80, 0x7b, 0xfe, 0xcf,
80 },
81 },
82 },
83 Padding: make([]byte, 0),
84 }
85 RDATA = []byte{
86 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0xe5, 0x3b,
87 0xe1, 0x93, 0x79, 0x91, 0x00, 0x00, 0x00, 0x04,
88 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
89 0x01, 0x02, 0x03, 0x04, 0x00, 0x5c, 0xe4, 0xa5,
90 0x39, 0x4a, 0xd9, 0x91, 0x00, 0x00, 0x00, 0x24,
91 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
92 0x00, 0x01, 0x00, 0x00, 0x0e, 0x60, 0x1b, 0xe4,
93 0x2e, 0xb5, 0x7f, 0xb4, 0x69, 0x76, 0x10, 0xcf,
94 0x3a, 0x3b, 0x18, 0x34, 0x7b, 0x65, 0xa3, 0x3f,
95 0x02, 0x5b, 0x5b, 0x17, 0x4a, 0xbe, 0xfb, 0x30,
96 0x80, 0x7b, 0xfe, 0xcf, 0x00, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x00,
103 }
104 NONCE = []byte{
105 0x67, 0xeb, 0xda, 0x27, 0x00, 0x34, 0xe5, 0x3b,
106 0xe1, 0x93, 0x79, 0x91, 0x00, 0x00, 0x00, 0x01,
107 }
108 SKEY = []byte{
109 0x55, 0x1f, 0x15, 0x7a, 0xcf, 0x2b, 0xf1, 0xd4,
110 0xa9, 0x75, 0x03, 0x69, 0x99, 0xea, 0x7c, 0x82,
111 0x86, 0xac, 0xb3, 0x18, 0xf1, 0x49, 0x3e, 0x63,
112 0xb5, 0x00, 0x60, 0x3a, 0x9b, 0x02, 0xe3, 0xe4,
113 }
114 BDATA = []byte{
115 0x00, 0xe4, 0x83, 0x7e, 0xb5, 0xd0, 0x4f, 0x92,
116 0x90, 0x3d, 0xe4, 0xb5, 0x23, 0x4e, 0x8c, 0xca,
117 0xc5, 0x73, 0x6c, 0x97, 0x93, 0x37, 0x9a, 0x59,
118 0xc3, 0x33, 0x75, 0xfc, 0x89, 0x51, 0xac, 0xa2,
119 0xeb, 0x7a, 0xad, 0x06, 0x7b, 0xf9, 0xaf, 0x60,
120 0xbf, 0x26, 0x75, 0x86, 0x46, 0xa1, 0x7f, 0x5e,
121 0x5c, 0x3b, 0x62, 0x15, 0xf9, 0x40, 0x79, 0x54,
122 0x5b, 0x1c, 0x4d, 0x4f, 0x1b, 0x2e, 0xbb, 0x22,
123 0xc2, 0xb4, 0xda, 0xd4, 0x41, 0x26, 0x81, 0x7b,
124 0x6f, 0x00, 0x15, 0x30, 0xd4, 0x76, 0x40, 0x1d,
125 0xd6, 0x7a, 0xc0, 0x14, 0x85, 0x54, 0xe8, 0x06,
126 0x35, 0x3d, 0xa9, 0xe4, 0x29, 0x80, 0x79, 0xf3,
127 0xe1, 0xb1, 0x69, 0x42, 0xc4, 0x8d, 0x90, 0xc4,
128 0x36, 0x0c, 0x61, 0x23, 0x8c, 0x40, 0xd9, 0xd5,
129 0x29, 0x11, 0xae, 0xa5, 0x2c, 0xc0, 0x03, 0x7a,
130 0xc7, 0x16, 0x0b, 0xb3, 0xcf, 0x5b, 0x2f, 0x4a,
131 0x72, 0x2f, 0xd9, 0x6b,
132 }
133 LABEL = "test"
134 )
135
136 // check zone key pair
137 prv, err := crypto.NewZonePrivate(crypto.ZONE_PKEY, D)
138 if err != nil {
139 t.Fatal(err)
140 }
141 zk := prv.Public()
142 if !bytes.Equal(zk.Bytes(), ZKEY) {
143 t.Logf("pub = %s\n", hex.EncodeToString(zk.Bytes()))
144 t.Logf(" != %s\n", hex.EncodeToString(ZKEY))
145 t.Fatal("zone key mismatch")
146 }
147 zid := zk.ID()
148 if zid != ZID {
149 t.Logf("id = %s\n", zid)
150 t.Logf("ID = %s\n", ZID)
151 t.Fatal("Zone ID mismatch")
152 }
153
154 // assemble and check recordset
155 RECSET.SetPadding()
156 rdata, err := data.Marshal(RECSET)
157 if err != nil {
158 t.Fatal(err)
159 }
160 if !bytes.Equal(rdata, RDATA) {
161 t.Logf("rdata = %s\n", hex.EncodeToString(rdata))
162 t.Logf("RDATA = %s\n", hex.EncodeToString(RDATA))
163 t.Fatal("RDATA mismatch")
164 }
165
166 // check symmetric keys and nonce
167 expires := RECSET.Expires()
168 skey := zk.BlockKey(LABEL, expires)
169 if !bytes.Equal(skey[32:], NONCE) {
170 t.Logf("nonce = %s\n", hex.EncodeToString(skey[32:]))
171 t.Logf("NONCE = %s\n", hex.EncodeToString(NONCE))
172 t.Fatal("NONCE mismatch")
173 }
174 if !bytes.Equal(skey[:32], SKEY) {
175 t.Logf("skey = %s\n", hex.EncodeToString(skey[:32]))
176 t.Logf("SKEY = %s\n", hex.EncodeToString(SKEY))
177 t.Fatal("SKEY mismatch")
178 }
179
180 // check block encryption
181 bdata, err := zk.Encrypt(rdata, LABEL, expires)
182 if err != nil {
183 t.Fatal(err)
184 }
185 if !bytes.Equal(bdata, BDATA) {
186 t.Logf("bdata = %s\n", hex.EncodeToString(bdata))
187 t.Logf("BDATA = %s\n", hex.EncodeToString(BDATA))
188 t.Fatal("BDATA mismatch")
189 }
190}
191
192// TestRecordsetEDKEY implements the test case as defined in the GNS draft
193// (see section 13. Test vectors, case "EDKEY")
194func TestRecordsetEDKEY(t *testing.T) {
195 var (
196 SEED = []byte{
197 // EDKEY private key (seed)
198 0x5a, 0xf7, 0x02, 0x0e, 0xe1, 0x91, 0x60, 0x32,
199 0x88, 0x32, 0x35, 0x2b, 0xbc, 0x6a, 0x68, 0xa8,
200 0xd7, 0x1a, 0x7c, 0xbe, 0x1b, 0x92, 0x99, 0x69,
201 0xa7, 0xc6, 0x6d, 0x41, 0x5a, 0x0d, 0x8f, 0x65,
202 }
203 ZKEY = []byte{
204 // zone type
205 0x00, 0x01, 0x00, 0x14,
206 // EDKEY public key data
207 0x3c, 0xf4, 0xb9, 0x24, 0x03, 0x20, 0x22, 0xf0,
208 0xdc, 0x50, 0x58, 0x14, 0x53, 0xb8, 0x5d, 0x93,
209 0xb0, 0x47, 0xb6, 0x3d, 0x44, 0x6c, 0x58, 0x45,
210 0xcb, 0x48, 0x44, 0x5d, 0xdb, 0x96, 0x68, 0x8f,
211 }
212 ZID = "000G051WYJWJ80S04BRDRM2R2H9VGQCKP13VCFA4DHC4BJT88HEXQ5K8HW"
213 RECSET = &RecordSet{
214 Count: 2,
215 Records: []*ResourceRecord{
216 {
217 Expires: util.AbsoluteTime{
218 Val: uint64(2463385894000000),
219 },
220 Size: 4,
221 Type: 1,
222 Flags: 0,
223 Data: []byte{
224 0x01, 0x02, 0x03, 0x04,
225 },
226 },
227 {
228 Expires: util.AbsoluteTime{
229 Val: uint64(49556645701000000),
230 },
231 Size: 36,
232 Type: uint32(enums.GNS_TYPE_NICK),
233 Flags: 2,
234 Data: []byte{
235 0x4d, 0x79, 0x20, 0x4e, 0x69, 0x63, 0x6b, 0x00,
236 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69,
237 0x6f, 0x6e, 0x20, 0x4e, 0x4f, 0x4e, 0x43, 0x45,
238 0x7c, 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, 0x54,
239 0x49, 0x4f, 0x4e, 0x3a,
240 },
241 },
242 },
243 Padding: make([]byte, 0),
244 }
245 RDATA = []byte{
246 0x00, 0x00, 0x00, 0x02, 0x00, 0x08, 0xc0, 0x6f,
247 0xb9, 0x28, 0x15, 0x80, 0x00, 0x00, 0x00, 0x04,
248 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
249 0x01, 0x02, 0x03, 0x04, 0x00, 0xb0, 0x0f, 0x81,
250 0xb7, 0x44, 0x9b, 0x40, 0x00, 0x00, 0x00, 0x24,
251 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
252 0x4d, 0x79, 0x20, 0x4e, 0x69, 0x63, 0x6b, 0x00,
253 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69,
254 0x6f, 0x6e, 0x20, 0x4e, 0x4f, 0x4e, 0x43, 0x45,
255 0x7c, 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, 0x54,
256 0x49, 0x4f, 0x4e, 0x3a, 0x00, 0x00, 0x00, 0x00,
257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
262 0x00, 0x00, 0x00, 0x00,
263 }
264 NONCE = []byte{
265 0x95, 0x4c, 0xb5, 0xd6, 0x31, 0x9f, 0x9e, 0x31,
266 0xff, 0x80, 0x4a, 0xe6, 0x83, 0xbc, 0x19, 0x37,
267 0x00, 0x08, 0xc0, 0x6f, 0xb9, 0x28, 0x15, 0x80,
268 }
269 SKEY = []byte{
270 0x08, 0x34, 0xa3, 0xa3, 0xae, 0x09, 0xcb, 0x3b,
271 0xd9, 0x8c, 0xec, 0xdb, 0x47, 0x7c, 0x3b, 0x32,
272 0x45, 0xd0, 0xce, 0xda, 0x94, 0x8f, 0x9e, 0xbb,
273 0xba, 0x3b, 0x17, 0x91, 0x61, 0x7b, 0xee, 0x69,
274 }
275 BDATA = []byte{
276 0x36, 0x07, 0xf8, 0x62, 0xfc, 0xf4, 0xc6, 0xd4,
277 0x86, 0x1c, 0x7a, 0x06, 0x08, 0x81, 0x28, 0xbb,
278 0x3d, 0x6c, 0xca, 0xe2, 0xb1, 0x4e, 0xf4, 0x25,
279 0xe3, 0xd6, 0xbb, 0xd6, 0x27, 0x1a, 0x71, 0xe5,
280 0x42, 0x1c, 0x25, 0x1c, 0xfb, 0x5e, 0xb6, 0xd7,
281 0xbc, 0x9e, 0x74, 0xb2, 0xe8, 0xc8, 0xd8, 0x6c,
282 0xe0, 0x65, 0x37, 0x12, 0x0c, 0x2e, 0xe2, 0x28,
283 0x5b, 0x93, 0xc5, 0xaf, 0xb7, 0x79, 0xf9, 0xcf,
284 0x50, 0x2e, 0x16, 0xa5, 0xad, 0x30, 0xe6, 0x22,
285 0xed, 0x58, 0x92, 0xd2, 0x46, 0xc0, 0x34, 0x11,
286 0x70, 0xf0, 0xc5, 0x1c, 0x39, 0x40, 0xab, 0x33,
287 0x47, 0xdc, 0x91, 0x56, 0x5f, 0x36, 0x6d, 0xb6,
288 0x23, 0x56, 0x73, 0x9a, 0xd8, 0xde, 0x68, 0x21,
289 0x12, 0x68, 0xf0, 0xc0, 0x44, 0x00, 0x81, 0xd8,
290 0xaf, 0x8a, 0x6e, 0x16, 0x45, 0xa6, 0x92, 0x46,
291 0xb4, 0x34, 0xe2, 0xc8, 0x76, 0x9f, 0x00, 0x1b,
292 0xd5, 0x1a, 0xb3, 0x73, 0x5e, 0x02, 0xb4, 0x81,
293 0xa6, 0x83, 0x0f, 0x00, 0xd2, 0xf6, 0xf3, 0x15,
294 0xdf, 0x54, 0x20, 0x90,
295 }
296 LABEL = "test"
297 )
298
299 // check zone key pair
300 prv, err := crypto.NewZonePrivate(crypto.ZONE_EDKEY, SEED)
301 if err != nil {
302 t.Fatal(err)
303 }
304 zk := prv.Public()
305 if !bytes.Equal(zk.Bytes(), ZKEY) {
306 t.Logf("zkey = %s\n", hex.EncodeToString(zk.Bytes()))
307 t.Logf(" != %s\n", hex.EncodeToString(ZKEY))
308 t.Fatal("zone key mismatch")
309 }
310 zid := zk.ID()
311 if zid != ZID {
312 t.Logf("id = %s\n", zid)
313 t.Logf("ID = %s\n", ZID)
314 t.Fatal("Zone ID mismatch")
315 }
316
317 // assemble and check recordset
318 RECSET.SetPadding()
319 rdata, err := data.Marshal(RECSET)
320 if err != nil {
321 t.Fatal(err)
322 }
323 if !bytes.Equal(rdata, RDATA) {
324 t.Logf("rdata = %s\n", hex.EncodeToString(rdata))
325 t.Logf("RDATA = %s\n", hex.EncodeToString(RDATA))
326 t.Fatal("RDATA mismatch")
327 }
328
329 // check symmetric keys and nonce
330 expires := RECSET.Expires()
331 skey := zk.BlockKey(LABEL, expires)
332 if !bytes.Equal(skey[32:], NONCE) {
333 t.Logf("nonce = %s\n", hex.EncodeToString(skey[32:]))
334 t.Logf("NONCE = %s\n", hex.EncodeToString(NONCE))
335 t.Fatal("NONCE mismatch")
336 }
337 if !bytes.Equal(skey[:32], SKEY) {
338 t.Logf("skey = %s\n", hex.EncodeToString(skey[:32]))
339 t.Logf("SKEY = %s\n", hex.EncodeToString(SKEY))
340 t.Fatal("SKEY mismatch")
341 }
342
343 // check block encryption
344 bdata, err := zk.Encrypt(rdata, LABEL, expires)
345 if err != nil {
346 t.Fatal(err)
347 }
348 if !bytes.Equal(bdata, BDATA) {
349 t.Logf("bdata = %s\n", hex.EncodeToString(bdata))
350 t.Logf("BDATA = %s\n", hex.EncodeToString(BDATA))
351 t.Fatal("BDATA mismatch")
352 }
353}
diff --git a/src/gnunet/message/msg_namecache.go b/src/gnunet/message/msg_namecache.go
index 1f69eed..c3a0ac7 100644
--- a/src/gnunet/message/msg_namecache.go
+++ b/src/gnunet/message/msg_namecache.go
@@ -30,11 +30,11 @@ import (
30// NAMECACHE_LOOKUP_BLOCK 30// NAMECACHE_LOOKUP_BLOCK
31//---------------------------------------------------------------------- 31//----------------------------------------------------------------------
32 32
33// NamecacheLookupMsg 33// NamecacheLookupMsg is request message for lookups in local namecache
34type NamecacheLookupMsg struct { 34type NamecacheLookupMsg struct {
35 MsgSize uint16 `order:"big"` // total size of message 35 MsgSize uint16 `order:"big"` // total size of message
36 MsgType uint16 `order:"big"` // NAMECACHE_LOOKUP_BLOCK (431) 36 MsgType uint16 `order:"big"` // NAMECACHE_LOOKUP_BLOCK (431)
37 Id uint32 `order:"big"` // Request Id 37 ID uint32 `order:"big"` // Request Id
38 Query *crypto.HashCode // Query data 38 Query *crypto.HashCode // Query data
39} 39}
40 40
@@ -46,7 +46,7 @@ func NewNamecacheLookupMsg(query *crypto.HashCode) *NamecacheLookupMsg {
46 return &NamecacheLookupMsg{ 46 return &NamecacheLookupMsg{
47 MsgSize: 72, 47 MsgSize: 72,
48 MsgType: NAMECACHE_LOOKUP_BLOCK, 48 MsgType: NAMECACHE_LOOKUP_BLOCK,
49 Id: 0, 49 ID: 0,
50 Query: query, 50 Query: query,
51 } 51 }
52} 52}
@@ -54,83 +54,78 @@ func NewNamecacheLookupMsg(query *crypto.HashCode) *NamecacheLookupMsg {
54// String returns a human-readable representation of the message. 54// String returns a human-readable representation of the message.
55func (m *NamecacheLookupMsg) String() string { 55func (m *NamecacheLookupMsg) String() string {
56 return fmt.Sprintf("NamecacheLookupMsg{Id=%d,Query=%s}", 56 return fmt.Sprintf("NamecacheLookupMsg{Id=%d,Query=%s}",
57 m.Id, hex.EncodeToString(m.Query.Bits)) 57 m.ID, hex.EncodeToString(m.Query.Bits))
58} 58}
59 59
60// Header returns the message header in a separate instance. 60// Header returns the message header in a separate instance.
61func (msg *NamecacheLookupMsg) Header() *MessageHeader { 61func (m *NamecacheLookupMsg) Header() *Header {
62 return &MessageHeader{msg.MsgSize, msg.MsgType} 62 return &Header{m.MsgSize, m.MsgType}
63} 63}
64 64
65//---------------------------------------------------------------------- 65//----------------------------------------------------------------------
66// NAMECACHE_LOOKUP_BLOCK_RESPONSE 66// NAMECACHE_LOOKUP_BLOCK_RESPONSE
67//---------------------------------------------------------------------- 67//----------------------------------------------------------------------
68 68
69// NamecacheLookupResultMsg 69// NamecacheLookupResultMsg is the response message for namecache lookups.
70type NamecacheLookupResultMsg struct { 70type NamecacheLookupResultMsg struct {
71 MsgSize uint16 `order:"big"` // total size of message 71 MsgSize uint16 `order:"big"` // total size of message
72 MsgType uint16 `order:"big"` // NAMECACHE_LOOKUP_BLOCK_RESPONSE (432) 72 MsgType uint16 `order:"big"` // NAMECACHE_LOOKUP_BLOCK_RESPONSE (432)
73 Id uint32 `order:"big"` // Request Id 73 ID uint32 `order:"big"` // Request Id
74 Expire util.AbsoluteTime // Expiration time 74 Expire util.AbsoluteTime `` // Expiration time
75 Signature []byte `size:"64"` // ECDSA signature 75 DerivedKeySig *crypto.ZoneSignature `` // Derived public key
76 DerivedKey []byte `size:"32"` // Derived public key 76 EncData []byte `size:"*"` // Encrypted block data
77 EncData []byte `size:"*"` // Encrypted block data
78} 77}
79 78
80// NewNamecacheLookupResultMsg creates a new default message. 79// NewNamecacheLookupResultMsg creates a new default message.
81func NewNamecacheLookupResultMsg() *NamecacheLookupResultMsg { 80func NewNamecacheLookupResultMsg() *NamecacheLookupResultMsg {
82 return &NamecacheLookupResultMsg{ 81 return &NamecacheLookupResultMsg{
83 MsgSize: 112, 82 MsgSize: 112,
84 MsgType: NAMECACHE_LOOKUP_BLOCK_RESPONSE, 83 MsgType: NAMECACHE_LOOKUP_BLOCK_RESPONSE,
85 Id: 0, 84 ID: 0,
86 Expire: *new(util.AbsoluteTime), 85 Expire: *new(util.AbsoluteTime),
87 Signature: make([]byte, 64), 86 DerivedKeySig: nil,
88 DerivedKey: make([]byte, 32), 87 EncData: nil,
89 EncData: make([]byte, 0),
90 } 88 }
91} 89}
92 90
93// String returns a human-readable representation of the message. 91// String returns a human-readable representation of the message.
94func (m *NamecacheLookupResultMsg) String() string { 92func (m *NamecacheLookupResultMsg) String() string {
95 return fmt.Sprintf("NamecacheLookupResultMsg{id=%d,expire=%s}", 93 return fmt.Sprintf("NamecacheLookupResultMsg{id=%d,expire=%s}",
96 m.Id, m.Expire) 94 m.ID, m.Expire)
97} 95}
98 96
99// Header returns the message header in a separate instance. 97// Header returns the message header in a separate instance.
100func (msg *NamecacheLookupResultMsg) Header() *MessageHeader { 98func (m *NamecacheLookupResultMsg) Header() *Header {
101 return &MessageHeader{msg.MsgSize, msg.MsgType} 99 return &Header{m.MsgSize, m.MsgType}
102} 100}
103 101
104//---------------------------------------------------------------------- 102//----------------------------------------------------------------------
105// NAMECACHE_CACHE_BLOCK 103// NAMECACHE_CACHE_BLOCK
106//---------------------------------------------------------------------- 104//----------------------------------------------------------------------
107 105
108// NamecacheCacheMsg 106// NamecacheCacheMsg is the request message to put a name into the local cache.
109type NamecacheCacheMsg struct { 107type NamecacheCacheMsg struct {
110 MsgSize uint16 `order:"big"` // total size of message 108 MsgSize uint16 `order:"big"` // total size of message
111 MsgType uint16 `order:"big"` // NAMECACHE_CACHE_BLOCK (433) 109 MsgType uint16 `order:"big"` // NAMECACHE_CACHE_BLOCK (433)
112 Id uint32 `order:"big"` // Request Id 110 ID uint32 `order:"big"` // Request Id
113 Expire util.AbsoluteTime // Expiration time 111 Expire util.AbsoluteTime `` // Expiration time
114 Signature []byte `size:"64"` // ECDSA signature 112 DerivedKeySig *crypto.ZoneSignature `` // Derived public key and signature
115 DerivedKey []byte `size:"32"` // Derived public key 113 EncData []byte `size:"*"` // Encrypted block data
116 EncData []byte `size:"*"` // Encrypted block data
117} 114}
118 115
119// NewNamecacheLookupMsg creates a new default message. 116// NewNamecacheCacheMsg creates a new default message.
120func NewNamecacheCacheMsg(block *GNSBlock) *NamecacheCacheMsg { 117func NewNamecacheCacheMsg(block *Block) *NamecacheCacheMsg {
121 msg := &NamecacheCacheMsg{ 118 msg := &NamecacheCacheMsg{
122 MsgSize: 108, 119 MsgSize: 108,
123 MsgType: NAMECACHE_BLOCK_CACHE, 120 MsgType: NAMECACHE_BLOCK_CACHE,
124 Id: 0, 121 ID: 0,
125 Expire: *new(util.AbsoluteTime), 122 Expire: *new(util.AbsoluteTime),
126 Signature: make([]byte, 64), 123 DerivedKeySig: nil,
127 DerivedKey: make([]byte, 32), 124 EncData: make([]byte, 0),
128 EncData: make([]byte, 0),
129 } 125 }
130 if block != nil { 126 if block != nil {
127 msg.DerivedKeySig = block.DerivedKeySig
131 msg.Expire = block.Block.Expire 128 msg.Expire = block.Block.Expire
132 copy(msg.Signature, block.Signature)
133 copy(msg.DerivedKey, block.DerivedKey)
134 size := len(block.Block.EncData) 129 size := len(block.Block.EncData)
135 msg.EncData = make([]byte, size) 130 msg.EncData = make([]byte, size)
136 copy(msg.EncData, block.Block.EncData) 131 copy(msg.EncData, block.Block.EncData)
@@ -142,23 +137,23 @@ func NewNamecacheCacheMsg(block *GNSBlock) *NamecacheCacheMsg {
142// String returns a human-readable representation of the message. 137// String returns a human-readable representation of the message.
143func (m *NamecacheCacheMsg) String() string { 138func (m *NamecacheCacheMsg) String() string {
144 return fmt.Sprintf("NewNamecacheCacheMsg{id=%d,expire=%s}", 139 return fmt.Sprintf("NewNamecacheCacheMsg{id=%d,expire=%s}",
145 m.Id, m.Expire) 140 m.ID, m.Expire)
146} 141}
147 142
148// Header returns the message header in a separate instance. 143// Header returns the message header in a separate instance.
149func (msg *NamecacheCacheMsg) Header() *MessageHeader { 144func (m *NamecacheCacheMsg) Header() *Header {
150 return &MessageHeader{msg.MsgSize, msg.MsgType} 145 return &Header{m.MsgSize, m.MsgType}
151} 146}
152 147
153//---------------------------------------------------------------------- 148//----------------------------------------------------------------------
154// NAMECACHE_BLOCK_CACHE_RESPONSE 149// NAMECACHE_BLOCK_CACHE_RESPONSE
155//---------------------------------------------------------------------- 150//----------------------------------------------------------------------
156 151
157// NamecacheCacheResponseMsg 152// NamecacheCacheResponseMsg is the reponse message for a put request
158type NamecacheCacheResponseMsg struct { 153type NamecacheCacheResponseMsg struct {
159 MsgSize uint16 `order:"big"` // total size of message 154 MsgSize uint16 `order:"big"` // total size of message
160 MsgType uint16 `order:"big"` // NAMECACHE_LOOKUP_BLOCK_RESPONSE (432) 155 MsgType uint16 `order:"big"` // NAMECACHE_LOOKUP_BLOCK_RESPONSE (432)
161 Id uint32 `order:"big"` // Request Id 156 ID uint32 `order:"big"` // Request Id
162 Result int32 `order:"big"` // Result code 157 Result int32 `order:"big"` // Result code
163} 158}
164 159
@@ -167,7 +162,7 @@ func NewNamecacheCacheResponseMsg() *NamecacheCacheResponseMsg {
167 return &NamecacheCacheResponseMsg{ 162 return &NamecacheCacheResponseMsg{
168 MsgSize: 12, 163 MsgSize: 12,
169 MsgType: NAMECACHE_BLOCK_CACHE_RESPONSE, 164 MsgType: NAMECACHE_BLOCK_CACHE_RESPONSE,
170 Id: 0, 165 ID: 0,
171 Result: 0, 166 Result: 0,
172 } 167 }
173} 168}
@@ -175,10 +170,10 @@ func NewNamecacheCacheResponseMsg() *NamecacheCacheResponseMsg {
175// String returns a human-readable representation of the message. 170// String returns a human-readable representation of the message.
176func (m *NamecacheCacheResponseMsg) String() string { 171func (m *NamecacheCacheResponseMsg) String() string {
177 return fmt.Sprintf("NamecacheCacheResponseMsg{id=%d,result=%d}", 172 return fmt.Sprintf("NamecacheCacheResponseMsg{id=%d,result=%d}",
178 m.Id, m.Result) 173 m.ID, m.Result)
179} 174}
180 175
181// Header returns the message header in a separate instance. 176// Header returns the message header in a separate instance.
182func (msg *NamecacheCacheResponseMsg) Header() *MessageHeader { 177func (m *NamecacheCacheResponseMsg) Header() *Header {
183 return &MessageHeader{msg.MsgSize, msg.MsgType} 178 return &Header{m.MsgSize, m.MsgType}
184} 179}
diff --git a/src/gnunet/message/msg_revocation.go b/src/gnunet/message/msg_revocation.go
index c17f440..3174c55 100644
--- a/src/gnunet/message/msg_revocation.go
+++ b/src/gnunet/message/msg_revocation.go
@@ -21,52 +21,47 @@ package message
21import ( 21import (
22 "fmt" 22 "fmt"
23 23
24 "gnunet/crypto"
24 "gnunet/util" 25 "gnunet/util"
25
26 "github.com/bfix/gospel/crypto/ed25519"
27) 26)
28 27
29//---------------------------------------------------------------------- 28//----------------------------------------------------------------------
30// REVOCATION_QUERY 29// REVOCATION_QUERY
31//---------------------------------------------------------------------- 30//----------------------------------------------------------------------
32 31
33// RevocationQueryMsg 32// RevocationQueryMsg is a request message to check if a key is revoked
34type RevocationQueryMsg struct { 33type RevocationQueryMsg struct {
35 MsgSize uint16 `order:"big"` // total size of message 34 MsgSize uint16 `order:"big"` // total size of message
36 MsgType uint16 `order:"big"` // REVOCATION_QUERY (636) 35 MsgType uint16 `order:"big"` // REVOCATION_QUERY (636)
37 Reserved uint32 `order:"big"` // Reserved for future use 36 Reserved uint32 `order:"big"` // Reserved for future use
38 Zone []byte `size:"32"` // Zone that is to be checked for revocation 37 Zone *crypto.ZoneKey // Zone that is to be checked for revocation
39} 38}
40 39
41// NewRevocationQueryMsg creates a new message for a given zone. 40// NewRevocationQueryMsg creates a new message for a given zone.
42func NewRevocationQueryMsg(zone *ed25519.PublicKey) *RevocationQueryMsg { 41func NewRevocationQueryMsg(zkey *crypto.ZoneKey) *RevocationQueryMsg {
43 msg := &RevocationQueryMsg{ 42 return &RevocationQueryMsg{
44 MsgSize: 40, 43 MsgSize: 40,
45 MsgType: REVOCATION_QUERY, 44 MsgType: REVOCATION_QUERY,
46 Reserved: 0, 45 Reserved: 0,
47 Zone: make([]byte, 32), 46 Zone: zkey,
48 }
49 if zone != nil {
50 copy(msg.Zone, zone.Bytes())
51 } 47 }
52 return msg
53} 48}
54 49
55// String returns a human-readable representation of the message. 50// String returns a human-readable representation of the message.
56func (m *RevocationQueryMsg) String() string { 51func (m *RevocationQueryMsg) String() string {
57 return fmt.Sprintf("RevocationQueryMsg{zone=%s}", util.EncodeBinaryToString(m.Zone)) 52 return fmt.Sprintf("RevocationQueryMsg{zone=%s}", m.Zone.ID())
58} 53}
59 54
60// Header returns the message header in a separate instance. 55// Header returns the message header in a separate instance.
61func (msg *RevocationQueryMsg) Header() *MessageHeader { 56func (m *RevocationQueryMsg) Header() *Header {
62 return &MessageHeader{msg.MsgSize, msg.MsgType} 57 return &Header{m.MsgSize, m.MsgType}
63} 58}
64 59
65//---------------------------------------------------------------------- 60//----------------------------------------------------------------------
66// REVOCATION_QUERY_RESPONSE 61// REVOCATION_QUERY_RESPONSE
67//---------------------------------------------------------------------- 62//----------------------------------------------------------------------
68 63
69// RevocationQueryResponseMsg 64// RevocationQueryResponseMsg is a response message for revocation checks.
70type RevocationQueryResponseMsg struct { 65type RevocationQueryResponseMsg struct {
71 MsgSize uint16 `order:"big"` // total size of message 66 MsgSize uint16 `order:"big"` // total size of message
72 MsgType uint16 `order:"big"` // REVOCATION_QUERY_RESPONSE (637) 67 MsgType uint16 `order:"big"` // REVOCATION_QUERY_RESPONSE (637)
@@ -92,60 +87,51 @@ func (m *RevocationQueryResponseMsg) String() string {
92} 87}
93 88
94// Header returns the message header in a separate instance. 89// Header returns the message header in a separate instance.
95func (msg *RevocationQueryResponseMsg) Header() *MessageHeader { 90func (m *RevocationQueryResponseMsg) Header() *Header {
96 return &MessageHeader{msg.MsgSize, msg.MsgType} 91 return &Header{m.MsgSize, m.MsgType}
97} 92}
98 93
99//---------------------------------------------------------------------- 94//----------------------------------------------------------------------
100// REVOCATION_REVOKE 95// REVOCATION_REVOKE
101//---------------------------------------------------------------------- 96//----------------------------------------------------------------------
102 97
103// RevocationRevokeMsg 98// RevocationRevokeMsg is a request to revoke a given key with PoW data
104type RevocationRevokeMsg struct { 99type RevocationRevokeMsg struct {
105 MsgSize uint16 `order:"big"` // total size of message 100 MsgSize uint16 `order:"big"` // total size of message
106 MsgType uint16 `order:"big"` // REVOCATION_REVOKE (638) 101 MsgType uint16 `order:"big"` // REVOCATION_REVOKE (638)
107 Timestamp util.AbsoluteTime // Timestamp of revocation creation 102 Timestamp util.AbsoluteTime `` // Timestamp of revocation creation
108 TTL util.RelativeTime // TTL of revocation 103 TTL util.RelativeTime `` // TTL of revocation
109 PoWs []uint64 `size:"32" order:"big"` // (Sorted) list of PoW values 104 PoWs []uint64 `size:"32" order:"big"` // (Sorted) list of PoW values
110 Signature []byte `size:"64"` // Signature (Proof-of-ownership). 105 ZoneKeySig *crypto.ZoneSignature `` // public zone key (with signature) to be revoked
111 ZoneKey []byte `size:"32"` // public zone key to be revoked
112} 106}
113 107
114// NewRevocationRevokeMsg creates a new message for a given zone. 108// NewRevocationRevokeMsg creates a new message for a given zone.
115func NewRevocationRevokeMsg(zoneKey *ed25519.PublicKey, sig *ed25519.EcSignature) *RevocationRevokeMsg { 109func NewRevocationRevokeMsg(zsig *crypto.ZoneSignature) *RevocationRevokeMsg {
116 msg := &RevocationRevokeMsg{ 110 return &RevocationRevokeMsg{
117 MsgSize: 364, 111 MsgSize: 364,
118 MsgType: REVOCATION_REVOKE, 112 MsgType: REVOCATION_REVOKE,
119 Timestamp: util.AbsoluteTimeNow(), 113 Timestamp: util.AbsoluteTimeNow(),
120 TTL: util.RelativeTime{0}, 114 TTL: util.RelativeTime{},
121 PoWs: make([]uint64, 32), 115 PoWs: make([]uint64, 32),
122 Signature: make([]byte, 64), 116 ZoneKeySig: zsig,
123 ZoneKey: make([]byte, 32),
124 }
125 if zoneKey != nil {
126 copy(msg.ZoneKey, zoneKey.Bytes())
127 }
128 if sig != nil {
129 copy(msg.Signature, sig.Bytes())
130 } 117 }
131 return msg
132} 118}
133 119
134// String returns a human-readable representation of the message. 120// String returns a human-readable representation of the message.
135func (m *RevocationRevokeMsg) String() string { 121func (m *RevocationRevokeMsg) String() string {
136 return fmt.Sprintf("RevocationRevokeMsg{zone=%s}", util.EncodeBinaryToString(m.ZoneKey)) 122 return fmt.Sprintf("RevocationRevokeMsg{zone=%s}", m.ZoneKeySig.ID())
137} 123}
138 124
139// Header returns the message header in a separate instance. 125// Header returns the message header in a separate instance.
140func (msg *RevocationRevokeMsg) Header() *MessageHeader { 126func (m *RevocationRevokeMsg) Header() *Header {
141 return &MessageHeader{msg.MsgSize, msg.MsgType} 127 return &Header{m.MsgSize, m.MsgType}
142} 128}
143 129
144//---------------------------------------------------------------------- 130//----------------------------------------------------------------------
145// REVOCATION_REVOKE_RESPONSE 131// REVOCATION_REVOKE_RESPONSE
146//---------------------------------------------------------------------- 132//----------------------------------------------------------------------
147 133
148// RevocationRevokeResponseMsg 134// RevocationRevokeResponseMsg is a response message for a revocation request
149type RevocationRevokeResponseMsg struct { 135type RevocationRevokeResponseMsg struct {
150 MsgSize uint16 `order:"big"` // total size of message 136 MsgSize uint16 `order:"big"` // total size of message
151 MsgType uint16 `order:"big"` // REVOCATION_REVOKE_RESPONSE (639) 137 MsgType uint16 `order:"big"` // REVOCATION_REVOKE_RESPONSE (639)
@@ -171,6 +157,6 @@ func (m *RevocationRevokeResponseMsg) String() string {
171} 157}
172 158
173// Header returns the message header in a separate instance. 159// Header returns the message header in a separate instance.
174func (msg *RevocationRevokeResponseMsg) Header() *MessageHeader { 160func (m *RevocationRevokeResponseMsg) Header() *Header {
175 return &MessageHeader{msg.MsgSize, msg.MsgType} 161 return &Header{m.MsgSize, m.MsgType}
176} 162}
diff --git a/src/gnunet/message/msg_transport.go b/src/gnunet/message/msg_transport.go
index b2e4346..6e64c4d 100644
--- a/src/gnunet/message/msg_transport.go
+++ b/src/gnunet/message/msg_transport.go
@@ -34,19 +34,19 @@ import (
34// TRANSPORT_TCP_WELCOME 34// TRANSPORT_TCP_WELCOME
35//---------------------------------------------------------------------- 35//----------------------------------------------------------------------
36 36
37// TransportTcpWelcomeMsg 37// TransportTCPWelcomeMsg is a welcome message for new TCP connections.
38type TransportTcpWelcomeMsg struct { 38type TransportTCPWelcomeMsg struct {
39 MsgSize uint16 `order:"big"` // total size of message 39 MsgSize uint16 `order:"big"` // total size of message
40 MsgType uint16 `order:"big"` // TRANSPORT_TCP_WELCOME (61) 40 MsgType uint16 `order:"big"` // TRANSPORT_TCP_WELCOME (61)
41 PeerID *util.PeerID // Peer identity (EdDSA public key) 41 PeerID *util.PeerID // Peer identity (EdDSA public key)
42} 42}
43 43
44// NewTransportTcpWelcomeMsg creates a new message for a given peer. 44// NewTransportTCPWelcomeMsg creates a new message for a given peer.
45func NewTransportTcpWelcomeMsg(peerid *util.PeerID) *TransportTcpWelcomeMsg { 45func NewTransportTCPWelcomeMsg(peerid *util.PeerID) *TransportTCPWelcomeMsg {
46 if peerid == nil { 46 if peerid == nil {
47 peerid = util.NewPeerID(nil) 47 peerid = util.NewPeerID(nil)
48 } 48 }
49 return &TransportTcpWelcomeMsg{ 49 return &TransportTCPWelcomeMsg{
50 MsgSize: 36, 50 MsgSize: 36,
51 MsgType: TRANSPORT_TCP_WELCOME, 51 MsgType: TRANSPORT_TCP_WELCOME,
52 PeerID: peerid, 52 PeerID: peerid,
@@ -54,13 +54,13 @@ func NewTransportTcpWelcomeMsg(peerid *util.PeerID) *TransportTcpWelcomeMsg {
54} 54}
55 55
56// String returns a human-readable representation of the message. 56// String returns a human-readable representation of the message.
57func (m *TransportTcpWelcomeMsg) String() string { 57func (m *TransportTCPWelcomeMsg) String() string {
58 return fmt.Sprintf("TransportTcpWelcomeMsg{peer=%s}", m.PeerID) 58 return fmt.Sprintf("TransportTcpWelcomeMsg{peer=%s}", m.PeerID)
59} 59}
60 60
61// Header returns the message header in a separate instance. 61// Header returns the message header in a separate instance.
62func (msg *TransportTcpWelcomeMsg) Header() *MessageHeader { 62func (m *TransportTCPWelcomeMsg) Header() *Header {
63 return &MessageHeader{msg.MsgSize, msg.MsgType} 63 return &Header{m.MsgSize, m.MsgType}
64} 64}
65 65
66//---------------------------------------------------------------------- 66//----------------------------------------------------------------------
@@ -72,7 +72,7 @@ func (msg *TransportTcpWelcomeMsg) Header() *MessageHeader {
72// connection which the receiver (of the PING) initiated is still valid. 72// connection which the receiver (of the PING) initiated is still valid.
73//---------------------------------------------------------------------- 73//----------------------------------------------------------------------
74 74
75// TransportPingMsg 75// TransportPingMsg is a PING request message
76type TransportPingMsg struct { 76type TransportPingMsg struct {
77 MsgSize uint16 `order:"big"` // total size of message 77 MsgSize uint16 `order:"big"` // total size of message
78 MsgType uint16 `order:"big"` // TRANSPORT_PING (372) 78 MsgType uint16 `order:"big"` // TRANSPORT_PING (372)
@@ -81,7 +81,7 @@ type TransportPingMsg struct {
81 Address []byte `size:"*"` // encoded address 81 Address []byte `size:"*"` // encoded address
82} 82}
83 83
84// TransportPingMsg creates a new message for given peer with an address to 84// NewTransportPingMsg creates a new message for given peer with an address to
85// be validated. 85// be validated.
86func NewTransportPingMsg(target *util.PeerID, a *util.Address) *TransportPingMsg { 86func NewTransportPingMsg(target *util.PeerID, a *util.Address) *TransportPingMsg {
87 if target == nil { 87 if target == nil {
@@ -112,8 +112,8 @@ func (m *TransportPingMsg) String() string {
112} 112}
113 113
114// Header returns the message header in a separate instance. 114// Header returns the message header in a separate instance.
115func (msg *TransportPingMsg) Header() *MessageHeader { 115func (m *TransportPingMsg) Header() *Header {
116 return &MessageHeader{msg.MsgSize, msg.MsgType} 116 return &Header{m.MsgSize, m.MsgType}
117} 117}
118 118
119//---------------------------------------------------------------------- 119//----------------------------------------------------------------------
@@ -155,7 +155,7 @@ func NewSignedAddress(a *util.Address) *SignedAddress {
155 return addr 155 return addr
156} 156}
157 157
158// TransportPongMsg 158// TransportPongMsg is a reponse message for a PING request
159type TransportPongMsg struct { 159type TransportPongMsg struct {
160 MsgSize uint16 `order:"big"` // total size of message 160 MsgSize uint16 `order:"big"` // total size of message
161 MsgType uint16 `order:"big"` // TRANSPORT_PING (372) 161 MsgType uint16 `order:"big"` // TRANSPORT_PING (372)
@@ -193,8 +193,8 @@ func (m *TransportPongMsg) String() string {
193} 193}
194 194
195// Header returns the message header in a separate instance. 195// Header returns the message header in a separate instance.
196func (msg *TransportPongMsg) Header() *MessageHeader { 196func (m *TransportPongMsg) Header() *Header {
197 return &MessageHeader{msg.MsgSize, msg.MsgType} 197 return &Header{m.MsgSize, m.MsgType}
198} 198}
199 199
200// Sign the address block of a pong message. 200// Sign the address block of a pong message.
@@ -238,7 +238,7 @@ func (m *TransportPongMsg) Verify(pub *ed25519.PublicKey) (bool, error) {
238// 4) address (address-length bytes) 238// 4) address (address-length bytes)
239//---------------------------------------------------------------------- 239//----------------------------------------------------------------------
240 240
241// HelloAddress 241// HelloAddress represents a (generic) peer address with expiration date
242type HelloAddress struct { 242type HelloAddress struct {
243 Transport string // Name of transport 243 Transport string // Name of transport
244 AddrSize uint16 `order:"big"` // Size of address entry 244 AddrSize uint16 `order:"big"` // Size of address entry
@@ -247,7 +247,7 @@ type HelloAddress struct {
247} 247}
248 248
249// NewHelloAddress create a new HELLO address from the given address 249// NewHelloAddress create a new HELLO address from the given address
250func NewAddress(a *util.Address) *HelloAddress { 250func NewHelloAddress(a *util.Address) *HelloAddress {
251 addr := &HelloAddress{ 251 addr := &HelloAddress{
252 Transport: a.Transport, 252 Transport: a.Transport,
253 AddrSize: uint16(len(a.Address)), 253 AddrSize: uint16(len(a.Address)),
@@ -264,7 +264,7 @@ func (a *HelloAddress) String() string {
264 util.AddressString(a.Transport, a.Address), a.ExpireOn) 264 util.AddressString(a.Transport, a.Address), a.ExpireOn)
265} 265}
266 266
267// HelloMsg 267// HelloMsg is a message send by peers to announce their presence
268type HelloMsg struct { 268type HelloMsg struct {
269 MsgSize uint16 `order:"big"` // total size of message 269 MsgSize uint16 `order:"big"` // total size of message
270 MsgType uint16 `order:"big"` // HELLO (17) 270 MsgType uint16 `order:"big"` // HELLO (17)
@@ -300,15 +300,15 @@ func (m *HelloMsg) AddAddress(a *HelloAddress) {
300} 300}
301 301
302// Header returns the message header in a separate instance. 302// Header returns the message header in a separate instance.
303func (msg *HelloMsg) Header() *MessageHeader { 303func (m *HelloMsg) Header() *Header {
304 return &MessageHeader{msg.MsgSize, msg.MsgType} 304 return &Header{m.MsgSize, m.MsgType}
305} 305}
306 306
307//---------------------------------------------------------------------- 307//----------------------------------------------------------------------
308// TRANSPORT_SESSION_ACK 308// TRANSPORT_SESSION_ACK
309//---------------------------------------------------------------------- 309//----------------------------------------------------------------------
310 310
311// SessionAckMsg 311// SessionAckMsg is a message to acknowlege a session request
312type SessionAckMsg struct { 312type SessionAckMsg struct {
313 MsgSize uint16 `order:"big"` // total size of message 313 MsgSize uint16 `order:"big"` // total size of message
314 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_ACK (377) 314 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_ACK (377)
@@ -328,15 +328,15 @@ func (m *SessionAckMsg) String() string {
328} 328}
329 329
330// Header returns the message header in a separate instance. 330// Header returns the message header in a separate instance.
331func (msg *SessionAckMsg) Header() *MessageHeader { 331func (m *SessionAckMsg) Header() *Header {
332 return &MessageHeader{msg.MsgSize, msg.MsgType} 332 return &Header{m.MsgSize, m.MsgType}
333} 333}
334 334
335//---------------------------------------------------------------------- 335//----------------------------------------------------------------------
336// TRANSPORT_SESSION_SYN 336// TRANSPORT_SESSION_SYN
337//---------------------------------------------------------------------- 337//----------------------------------------------------------------------
338 338
339// SessionSynMsg 339// SessionSynMsg is a synchronization request message for sessions
340type SessionSynMsg struct { 340type SessionSynMsg struct {
341 MsgSize uint16 `order:"big"` // total size of message 341 MsgSize uint16 `order:"big"` // total size of message
342 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_SYN (375) 342 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_SYN (375)
@@ -360,15 +360,15 @@ func (m *SessionSynMsg) String() string {
360} 360}
361 361
362// Header returns the message header in a separate instance. 362// Header returns the message header in a separate instance.
363func (msg *SessionSynMsg) Header() *MessageHeader { 363func (m *SessionSynMsg) Header() *Header {
364 return &MessageHeader{msg.MsgSize, msg.MsgType} 364 return &Header{m.MsgSize, m.MsgType}
365} 365}
366 366
367//---------------------------------------------------------------------- 367//----------------------------------------------------------------------
368// TRANSPORT_SESSION_SYN_ACK 368// TRANSPORT_SESSION_SYN_ACK
369//---------------------------------------------------------------------- 369//----------------------------------------------------------------------
370 370
371// SessionSynAckMsg 371// SessionSynAckMsg responds to a SYN request message
372type SessionSynAckMsg struct { 372type SessionSynAckMsg struct {
373 MsgSize uint16 `order:"big"` // total size of message 373 MsgSize uint16 `order:"big"` // total size of message
374 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_SYN_ACK (376) 374 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_SYN_ACK (376)
@@ -392,15 +392,15 @@ func (m *SessionSynAckMsg) String() string {
392} 392}
393 393
394// Header returns the message header in a separate instance. 394// Header returns the message header in a separate instance.
395func (msg *SessionSynAckMsg) Header() *MessageHeader { 395func (m *SessionSynAckMsg) Header() *Header {
396 return &MessageHeader{msg.MsgSize, msg.MsgType} 396 return &Header{m.MsgSize, m.MsgType}
397} 397}
398 398
399//---------------------------------------------------------------------- 399//----------------------------------------------------------------------
400// TRANSPORT_SESSION_QUOTA 400// TRANSPORT_SESSION_QUOTA
401//---------------------------------------------------------------------- 401//----------------------------------------------------------------------
402 402
403// SessionQuotaMsg 403// SessionQuotaMsg is a message to announce quotas for a session
404type SessionQuotaMsg struct { 404type SessionQuotaMsg struct {
405 MsgSize uint16 `order:"big"` // total size of message 405 MsgSize uint16 `order:"big"` // total size of message
406 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_QUOTA (379) 406 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_QUOTA (379)
@@ -424,15 +424,15 @@ func (m *SessionQuotaMsg) String() string {
424} 424}
425 425
426// Header returns the message header in a separate instance. 426// Header returns the message header in a separate instance.
427func (msg *SessionQuotaMsg) Header() *MessageHeader { 427func (m *SessionQuotaMsg) Header() *Header {
428 return &MessageHeader{msg.MsgSize, msg.MsgType} 428 return &Header{m.MsgSize, m.MsgType}
429} 429}
430 430
431//---------------------------------------------------------------------- 431//----------------------------------------------------------------------
432// TRANSPORT_SESSION_KEEPALIVE 432// TRANSPORT_SESSION_KEEPALIVE
433//---------------------------------------------------------------------- 433//----------------------------------------------------------------------
434 434
435// SessionKeepAliveMsg 435// SessionKeepAliveMsg is a message send by peers to keep a session alive.
436type SessionKeepAliveMsg struct { 436type SessionKeepAliveMsg struct {
437 MsgSize uint16 `order:"big"` // total size of message 437 MsgSize uint16 `order:"big"` // total size of message
438 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_KEEPALIVE (381) 438 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_KEEPALIVE (381)
@@ -455,15 +455,15 @@ func (m *SessionKeepAliveMsg) String() string {
455} 455}
456 456
457// Header returns the message header in a separate instance. 457// Header returns the message header in a separate instance.
458func (msg *SessionKeepAliveMsg) Header() *MessageHeader { 458func (m *SessionKeepAliveMsg) Header() *Header {
459 return &MessageHeader{msg.MsgSize, msg.MsgType} 459 return &Header{m.MsgSize, m.MsgType}
460} 460}
461 461
462//---------------------------------------------------------------------- 462//----------------------------------------------------------------------
463// TRANSPORT_SESSION_KEEPALIVE_RESPONSE 463// TRANSPORT_SESSION_KEEPALIVE_RESPONSE
464//---------------------------------------------------------------------- 464//----------------------------------------------------------------------
465 465
466// SessionKeepAliveRespMsg 466// SessionKeepAliveRespMsg is a response for a peer to a "keep-alive" request.
467type SessionKeepAliveRespMsg struct { 467type SessionKeepAliveRespMsg struct {
468 MsgSize uint16 `order:"big"` // total size of message 468 MsgSize uint16 `order:"big"` // total size of message
469 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_KEEPALIVE_RESPONSE (382) 469 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_KEEPALIVE_RESPONSE (382)
@@ -486,6 +486,6 @@ func (m *SessionKeepAliveRespMsg) String() string {
486} 486}
487 487
488// Header returns the message header in a separate instance. 488// Header returns the message header in a separate instance.
489func (msg *SessionKeepAliveRespMsg) Header() *MessageHeader { 489func (m *SessionKeepAliveRespMsg) Header() *Header {
490 return &MessageHeader{msg.MsgSize, msg.MsgType} 490 return &Header{m.MsgSize, m.MsgType}
491} 491}
diff --git a/src/gnunet/modules.go b/src/gnunet/modules.go
index 24dc92b..f4fdb1b 100644
--- a/src/gnunet/modules.go
+++ b/src/gnunet/modules.go
@@ -33,14 +33,23 @@ import (
33 "gnunet/service/gns" 33 "gnunet/service/gns"
34 "gnunet/service/namecache" 34 "gnunet/service/namecache"
35 "gnunet/service/revocation" 35 "gnunet/service/revocation"
36 "net/rpc"
36) 37)
37 38
38// List of all GNUnet service module instances 39// Instances holds a list of all GNUnet service modules
39type Instances struct { 40type Instances struct {
40 GNS *gns.GNSModule 41 GNS *gns.Module
41 Namecache *namecache.NamecacheModule 42 Namecache *namecache.NamecacheModule
42 DHT *dht.DHTModule 43 DHT *dht.Module
43 Revocation *revocation.RevocationModule 44 Revocation *revocation.Module
45}
46
47// Register modules for JSON-RPC
48func (inst Instances) Register() {
49 rpc.Register(inst.GNS)
50 rpc.Register(inst.Namecache)
51 rpc.Register(inst.DHT)
52 rpc.Register(inst.Revocation)
44} 53}
45 54
46// Local reference to instance list 55// Local reference to instance list
@@ -55,13 +64,13 @@ func init() {
55 Modules.Namecache = new(namecache.NamecacheModule) 64 Modules.Namecache = new(namecache.NamecacheModule)
56 65
57 // DHT (no calls to other modules) 66 // DHT (no calls to other modules)
58 Modules.DHT = new(dht.DHTModule) 67 Modules.DHT = new(dht.Module)
59 68
60 // Revocation (no calls to other modules) 69 // Revocation (no calls to other modules)
61 Modules.Revocation = revocation.NewRevocationModule() 70 Modules.Revocation = revocation.NewModule()
62 71
63 // GNS (calls Namecache, DHT and Identity) 72 // GNS (calls Namecache, DHT and Identity)
64 Modules.GNS = &gns.GNSModule{ 73 Modules.GNS = &gns.Module{
65 LookupLocal: Modules.Namecache.Get, 74 LookupLocal: Modules.Namecache.Get,
66 StoreLocal: Modules.Namecache.Put, 75 StoreLocal: Modules.Namecache.Put,
67 LookupRemote: Modules.DHT.Get, 76 LookupRemote: Modules.DHT.Get,
diff --git a/src/gnunet/rpc/server.go b/src/gnunet/rpc/server.go
new file mode 100644
index 0000000..760ecfc
--- /dev/null
+++ b/src/gnunet/rpc/server.go
@@ -0,0 +1,66 @@
1// This file is part of gnunet-go, a GNUnet-implementation in Golang.
2// Copyright (C) 2019, 2020 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 rpc
20
21import (
22 "context"
23 "gnunet/config"
24 "gnunet/service"
25 "net/http"
26 "time"
27
28 "github.com/bfix/gospel/logger"
29 "github.com/gorilla/mux"
30)
31
32// Router for JSON-RPC requests
33var Router = mux.NewRouter()
34var srv *http.Server
35
36// Start the JSON-RPC server. It can be terminated by context
37func Start(ctx context.Context) error {
38 // instantiate a server and run it
39 srv = &http.Server{
40 Handler: Router,
41 Addr: config.Cfg.RPC.Endpoint,
42 WriteTimeout: 15 * time.Second,
43 ReadTimeout: 15 * time.Second,
44 }
45 go func() {
46 // start listening
47 go func() {
48 if err := srv.ListenAndServe(); err != nil {
49 logger.Printf(logger.WARN, "[RPC] Server listen failed: %s", err.Error())
50 }
51 }()
52 select {
53 case <-ctx.Done():
54 if err := srv.Shutdown(context.Background()); err != nil {
55 logger.Printf(logger.WARN, "[RPC] Server shutdownn failed: %s", err.Error())
56 }
57 }
58 }()
59 return nil
60}
61
62// Register a JSON-RPC path in a service-specific processor
63func Register(m service.Module) {
64 path, hdlr := m.RPC()
65 Router.HandleFunc(path, hdlr)
66}
diff --git a/src/gnunet/service/client.go b/src/gnunet/service/client.go
index b153bab..a196c09 100644
--- a/src/gnunet/service/client.go
+++ b/src/gnunet/service/client.go
@@ -59,9 +59,9 @@ func (c *Client) Close() error {
59 return c.ch.Close() 59 return c.ch.Close()
60} 60}
61 61
62// ServiceRequestResponse is a helper method for a one request - one response 62// RequestResponse is a helper method for a one request - one response
63// secenarios of client/serice interactions. 63// secenarios of client/serice interactions.
64func ServiceRequestResponse( 64func RequestResponse(
65 ctx *SessionContext, 65 ctx *SessionContext,
66 caller string, 66 caller string,
67 callee string, 67 callee string,
diff --git a/src/gnunet/service/context.go b/src/gnunet/service/context.go
index 120d460..4ae786d 100644
--- a/src/gnunet/service/context.go
+++ b/src/gnunet/service/context.go
@@ -30,7 +30,7 @@ import (
30// by a service; the session is handled by the 'ServeClient' method of a 30// by a service; the session is handled by the 'ServeClient' method of a
31// service implementation. 31// service implementation.
32type SessionContext struct { 32type SessionContext struct {
33 Id int // session identifier 33 ID int // session identifier
34 wg *sync.WaitGroup // wait group for the session 34 wg *sync.WaitGroup // wait group for the session
35 sig *concurrent.Signaller // signaller for the session 35 sig *concurrent.Signaller // signaller for the session
36 pending int // number of pending go-routines 36 pending int // number of pending go-routines
@@ -41,7 +41,7 @@ type SessionContext struct {
41// NewSessionContext instantiates a new session context. 41// NewSessionContext instantiates a new session context.
42func NewSessionContext() *SessionContext { 42func NewSessionContext() *SessionContext {
43 return &SessionContext{ 43 return &SessionContext{
44 Id: util.NextID(), 44 ID: util.NextID(),
45 wg: new(sync.WaitGroup), 45 wg: new(sync.WaitGroup),
46 sig: concurrent.NewSignaller(), 46 sig: concurrent.NewSignaller(),
47 pending: 0, 47 pending: 0,
diff --git a/src/gnunet/service/dht/module.go b/src/gnunet/service/dht/module.go
index 61c2540..1588a06 100644
--- a/src/gnunet/service/dht/module.go
+++ b/src/gnunet/service/dht/module.go
@@ -32,14 +32,16 @@ import (
32// Put and get blocks into/from a DHT. 32// Put and get blocks into/from a DHT.
33//---------------------------------------------------------------------- 33//----------------------------------------------------------------------
34 34
35// DHT handles the permanent storage of blocks under the query key. 35// Module handles the permanent storage of blocks under the query key.
36type DHTModule struct { 36type Module struct {
37} 37}
38 38
39func (nc *DHTModule) Get(ctx *service.SessionContext, query *gns.Query) (*message.GNSBlock, error) { 39// Get a GNS block from the DHT
40func (nc *Module) Get(ctx *service.SessionContext, query *gns.Query) (*message.Block, error) {
40 return nil, nil 41 return nil, nil
41} 42}
42 43
43func (nc *DHTModule) Put(ctx *service.SessionContext, block *message.GNSBlock) error { 44// Put a GNS block into the DHT
45func (nc *Module) Put(ctx *service.SessionContext, block *message.Block) error {
44 return nil 46 return nil
45} 47}
diff --git a/src/gnunet/service/gns/block_handler.go b/src/gnunet/service/gns/block_handler.go
index 3b3438d..b05c59e 100644
--- a/src/gnunet/service/gns/block_handler.go
+++ b/src/gnunet/service/gns/block_handler.go
@@ -22,32 +22,33 @@ import (
22 "encoding/hex" 22 "encoding/hex"
23 "fmt" 23 "fmt"
24 24
25 "gnunet/crypto"
25 "gnunet/enums" 26 "gnunet/enums"
26 "gnunet/message" 27 "gnunet/message"
27 "gnunet/util" 28 "gnunet/util"
28 29
29 "github.com/bfix/gospel/crypto/ed25519"
30 "github.com/bfix/gospel/logger" 30 "github.com/bfix/gospel/logger"
31) 31)
32 32
33// HdlrInst is the type for functions that instanciate custom block handlers. 33// HdlrInst is the type for functions that instanciate custom block handlers.
34type HdlrInst func(*message.GNSResourceRecord, []string) (BlockHandler, error) 34type HdlrInst func(*message.ResourceRecord, []string) (BlockHandler, error)
35 35
36// Error codes 36// Error codes
37var ( 37var (
38 ErrInvalidRecordType = fmt.Errorf("Invalid resource record type") 38 ErrInvalidRecordType = fmt.Errorf("invalid resource record type")
39 ErrInvalidRecordBody = fmt.Errorf("Invalid resource record body") 39 ErrInvalidRecordBody = fmt.Errorf("invalid resource record body")
40 ErrInvalidPKEY = fmt.Errorf("Invalid PKEY resource record") 40 ErrInvalidZoneKey = fmt.Errorf("invalid zone key resource record")
41 ErrInvalidCNAME = fmt.Errorf("Invalid CNAME resource record") 41 ErrInvalidCNAME = fmt.Errorf("invalid CNAME resource record")
42 ErrInvalidVPN = fmt.Errorf("Invalid VPN resource record") 42 ErrInvalidVPN = fmt.Errorf("invalid VPN resource record")
43 ErrInvalidRecordMix = fmt.Errorf("Invalid mix of RR types in block") 43 ErrInvalidRecordMix = fmt.Errorf("invalid mix of RR types in block")
44 ErrBlockHandler = fmt.Errorf("Internal block handler failure") 44 ErrBlockHandler = fmt.Errorf("internal block handler failure")
45) 45)
46 46
47// Mapping of RR types to BlockHandler instanciation functions 47// Mapping of RR types to BlockHandler instanciation functions
48var ( 48var (
49 customHandler = map[int]HdlrInst{ 49 customHandler = map[int]HdlrInst{
50 enums.GNS_TYPE_PKEY: NewPkeyHandler, 50 enums.GNS_TYPE_PKEY: NewZoneHandler,
51 enums.GNS_TYPE_EDKEY: NewZoneHandler,
51 enums.GNS_TYPE_GNS2DNS: NewGns2DnsHandler, 52 enums.GNS_TYPE_GNS2DNS: NewGns2DnsHandler,
52 enums.GNS_TYPE_BOX: NewBoxHandler, 53 enums.GNS_TYPE_BOX: NewBoxHandler,
53 enums.GNS_TYPE_LEHO: NewLehoHandler, 54 enums.GNS_TYPE_LEHO: NewLehoHandler,
@@ -69,7 +70,7 @@ type BlockHandler interface {
69 // processing. The handler can inspect the remaining labels in a path 70 // processing. The handler can inspect the remaining labels in a path
70 // if required. The method returns an error if a record is not accepted 71 // if required. The method returns an error if a record is not accepted
71 // by the block handler (RR not of required type). 72 // by the block handler (RR not of required type).
72 AddRecord(rr *message.GNSResourceRecord, labels []string) error 73 AddRecord(rr *message.ResourceRecord, labels []string) error
73 74
74 // Coexist checks if a custom block handler can co-exist with other 75 // Coexist checks if a custom block handler can co-exist with other
75 // resource records in the same block. 'cm' maps the resource type 76 // resource records in the same block. 'cm' maps the resource type
@@ -79,7 +80,7 @@ type BlockHandler interface {
79 80
80 // Records returns a list of RR of the given types associated with 81 // Records returns a list of RR of the given types associated with
81 // the custom handler 82 // the custom handler
82 Records(kind RRTypeList) *message.GNSRecordSet 83 Records(kind RRTypeList) *message.RecordSet
83 84
84 // Name returns the human-readable name of the handler 85 // Name returns the human-readable name of the handler
85 Name() string 86 Name() string
@@ -107,7 +108,7 @@ type BlockHandlerList struct {
107 108
108// NewBlockHandlerList instantiates an a list of active block handlers 109// NewBlockHandlerList instantiates an a list of active block handlers
109// for a given set of records (GNS block). 110// for a given set of records (GNS block).
110func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string) (*BlockHandlerList, []*message.GNSResourceRecord, error) { 111func NewBlockHandlerList(records []*message.ResourceRecord, labels []string) (*BlockHandlerList, []*message.ResourceRecord, error) {
111 // initialize block handler list 112 // initialize block handler list
112 hl := &BlockHandlerList{ 113 hl := &BlockHandlerList{
113 list: make(map[int]BlockHandler), 114 list: make(map[int]BlockHandler),
@@ -115,7 +116,7 @@ func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string)
115 } 116 }
116 117
117 // first pass: build list of shadow records in this block 118 // first pass: build list of shadow records in this block
118 shadows := make([]*message.GNSResourceRecord, 0) 119 shadows := make([]*message.ResourceRecord, 0)
119 for _, rec := range records { 120 for _, rec := range records {
120 // filter out shadow records... 121 // filter out shadow records...
121 if (int(rec.Flags) & enums.GNS_FLAG_SHADOW) != 0 { 122 if (int(rec.Flags) & enums.GNS_FLAG_SHADOW) != 0 {
@@ -124,7 +125,7 @@ func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string)
124 } 125 }
125 // second pass: normalize block by filtering out expired records (and 126 // second pass: normalize block by filtering out expired records (and
126 // replacing them with shadow records if available 127 // replacing them with shadow records if available
127 active := make([]*message.GNSResourceRecord, 0) 128 active := make([]*message.ResourceRecord, 0)
128 for _, rec := range records { 129 for _, rec := range records {
129 // don't process shadow records again 130 // don't process shadow records again
130 if (int(rec.Flags) & enums.GNS_FLAG_SHADOW) != 0 { 131 if (int(rec.Flags) & enums.GNS_FLAG_SHADOW) != 0 {
@@ -190,41 +191,48 @@ func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string)
190 return hl, active, nil 191 return hl, active, nil
191} 192}
192 193
193// GetHandler returns a BlockHandler for the given key. If no block handler exists 194// GetHandler returns a BlockHandler for the given GNS block type.
194// under the given name, a new one is created and stored in the list. The type of 195// If more than one type is given, the first matching hanlder is
195// the new block handler is derived from the key value. 196// returned.
196func (hl *BlockHandlerList) GetHandler(t int) BlockHandler { 197func (hl *BlockHandlerList) GetHandler(types ...int) BlockHandler {
197 // return handler for given key if it exists 198 for _, t := range types {
198 if hdlr, ok := hl.list[t]; ok { 199 // return handler for given type if it exists
199 return hdlr 200 if hdlr, ok := hl.list[t]; ok {
201 return hdlr
202 }
200 } 203 }
201 return nil 204 return nil
202} 205}
203 206
204// FinalizeRecord post-processes records 207// FinalizeRecord post-processes records
205func (hl *BlockHandlerList) FinalizeRecord(rec *message.GNSResourceRecord) *message.GNSResourceRecord { 208func (hl *BlockHandlerList) FinalizeRecord(rec *message.ResourceRecord) *message.ResourceRecord {
206 // no implementation yet 209 // no implementation yet
207 return rec 210 return rec
208} 211}
209 212
210//---------------------------------------------------------------------- 213//----------------------------------------------------------------------
211// PKEY handler: Only one PKEY as sole record in a block 214// Zone key handler: Only one zone key as sole record in a block
212//---------------------------------------------------------------------- 215//----------------------------------------------------------------------
213 216
214// PkeyHandler implementing the BlockHandler interface 217// ZoneKeyHandler implementing the BlockHandler interface
215type PkeyHandler struct { 218type ZoneKeyHandler struct {
216 pkey *ed25519.PublicKey // Zone key 219 ztype uint32 // zone type
217 rec *message.GNSResourceRecord // associated recource record 220 zkey *crypto.ZoneKey // Zone key
221 rec *message.ResourceRecord // associated recource record
218} 222}
219 223
220// NewPkeyHandler returns a new BlockHandler instance 224// NewZoneHandler returns a new BlockHandler instance
221func NewPkeyHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) { 225func NewZoneHandler(rec *message.ResourceRecord, labels []string) (BlockHandler, error) {
222 if int(rec.Type) != enums.GNS_TYPE_PKEY { 226 // check if we have an implementation for the zone type
227 if crypto.GetImplementation(rec.Type) == nil {
223 return nil, ErrInvalidRecordType 228 return nil, ErrInvalidRecordType
224 } 229 }
225 h := &PkeyHandler{ 230 // assemble handler
226 pkey: nil, 231 h := &ZoneKeyHandler{
232 ztype: rec.Type,
233 zkey: nil,
227 } 234 }
235 // add the record to the handler
228 if err := h.AddRecord(rec, labels); err != nil { 236 if err := h.AddRecord(rec, labels); err != nil {
229 return nil, err 237 return nil, err
230 } 238 }
@@ -232,34 +240,34 @@ func NewPkeyHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandl
232} 240}
233 241
234// AddRecord inserts a PKEY record into the handler. 242// AddRecord inserts a PKEY record into the handler.
235func (h *PkeyHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error { 243func (h *ZoneKeyHandler) AddRecord(rec *message.ResourceRecord, labels []string) (err error) {
236 if int(rec.Type) != enums.GNS_TYPE_PKEY { 244 // check record type
245 if rec.Type != h.ztype {
237 return ErrInvalidRecordType 246 return ErrInvalidRecordType
238 } 247 }
239 // check for sole PKEY record in block 248 // check for sole zone key record in block
240 if h.pkey != nil { 249 if h.zkey != nil {
241 return ErrInvalidPKEY 250 return ErrInvalidZoneKey
242 } 251 }
243 // check for sane key data 252 // set zone key
244 if len(rec.Data) != 32 { 253 h.zkey, err = crypto.NewZoneKey(rec.Data)
245 return ErrInvalidPKEY 254 if err != nil {
255 return
246 } 256 }
247 // set a PKEY handler
248 h.pkey = ed25519.NewPublicKeyFromBytes(rec.Data)
249 h.rec = rec 257 h.rec = rec
250 return nil 258 return
251} 259}
252 260
253// Coexist return a flag indicating how a resource record of a given type 261// Coexist return a flag indicating how a resource record of a given type
254// is to be treated (see BlockHandler interface) 262// is to be treated (see BlockHandler interface)
255func (h *PkeyHandler) Coexist(cm util.CounterMap) bool { 263func (h *ZoneKeyHandler) Coexist(cm util.CounterMap) bool {
256 // only one type (GNS_TYPE_PKEY) is present 264 // only one type (GNS_TYPE_PKEY) is present
257 return len(cm) == 1 && cm.Num(enums.GNS_TYPE_PKEY) == 1 265 return len(cm) == 1 && cm.Num(enums.GNS_TYPE_PKEY) == 1
258} 266}
259 267
260// Records returns a list of RR of the given type associated with this handler 268// Records returns a list of RR of the given type associated with this handler
261func (h *PkeyHandler) Records(kind RRTypeList) *message.GNSRecordSet { 269func (h *ZoneKeyHandler) Records(kind RRTypeList) *message.RecordSet {
262 rs := message.NewGNSRecordSet() 270 rs := message.NewRecordSet()
263 if kind.HasType(enums.GNS_TYPE_PKEY) { 271 if kind.HasType(enums.GNS_TYPE_PKEY) {
264 rs.AddRecord(h.rec) 272 rs.AddRecord(h.rec)
265 } 273 }
@@ -267,7 +275,7 @@ func (h *PkeyHandler) Records(kind RRTypeList) *message.GNSRecordSet {
267} 275}
268 276
269// Name returns the human-readable name of the handler. 277// Name returns the human-readable name of the handler.
270func (h *PkeyHandler) Name() string { 278func (h *ZoneKeyHandler) Name() string {
271 return "PKEY_Handler" 279 return "PKEY_Handler"
272} 280}
273 281
@@ -277,20 +285,20 @@ func (h *PkeyHandler) Name() string {
277 285
278// Gns2DnsHandler implementing the BlockHandler interface 286// Gns2DnsHandler implementing the BlockHandler interface
279type Gns2DnsHandler struct { 287type Gns2DnsHandler struct {
280 Query string // DNS query name 288 Query string // DNS query name
281 Servers []string // DNS servers to ask 289 Servers []string // DNS servers to ask
282 recs []*message.GNSResourceRecord // list of rersource records 290 recs []*message.ResourceRecord // list of rersource records
283} 291}
284 292
285// NewGns2DnsHandler returns a new BlockHandler instance 293// NewGns2DnsHandler returns a new BlockHandler instance
286func NewGns2DnsHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) { 294func NewGns2DnsHandler(rec *message.ResourceRecord, labels []string) (BlockHandler, error) {
287 if int(rec.Type) != enums.GNS_TYPE_GNS2DNS { 295 if int(rec.Type) != enums.GNS_TYPE_GNS2DNS {
288 return nil, ErrInvalidRecordType 296 return nil, ErrInvalidRecordType
289 } 297 }
290 h := &Gns2DnsHandler{ 298 h := &Gns2DnsHandler{
291 Query: "", 299 Query: "",
292 Servers: make([]string, 0), 300 Servers: make([]string, 0),
293 recs: make([]*message.GNSResourceRecord, 0), 301 recs: make([]*message.ResourceRecord, 0),
294 } 302 }
295 if err := h.AddRecord(rec, labels); err != nil { 303 if err := h.AddRecord(rec, labels); err != nil {
296 return nil, err 304 return nil, err
@@ -299,7 +307,7 @@ func NewGns2DnsHandler(rec *message.GNSResourceRecord, labels []string) (BlockHa
299} 307}
300 308
301// AddRecord inserts a GNS2DNS record into the handler. 309// AddRecord inserts a GNS2DNS record into the handler.
302func (h *Gns2DnsHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error { 310func (h *Gns2DnsHandler) AddRecord(rec *message.ResourceRecord, labels []string) error {
303 if int(rec.Type) != enums.GNS_TYPE_GNS2DNS { 311 if int(rec.Type) != enums.GNS_TYPE_GNS2DNS {
304 return ErrInvalidRecordType 312 return ErrInvalidRecordType
305 } 313 }
@@ -333,8 +341,8 @@ func (h *Gns2DnsHandler) Coexist(cm util.CounterMap) bool {
333} 341}
334 342
335// Records returns a list of RR of the given type associated with this handler 343// Records returns a list of RR of the given type associated with this handler
336func (h *Gns2DnsHandler) Records(kind RRTypeList) *message.GNSRecordSet { 344func (h *Gns2DnsHandler) Records(kind RRTypeList) *message.RecordSet {
337 rs := message.NewGNSRecordSet() 345 rs := message.NewRecordSet()
338 if kind.HasType(enums.GNS_TYPE_GNS2DNS) { 346 if kind.HasType(enums.GNS_TYPE_GNS2DNS) {
339 for _, rec := range h.recs { 347 for _, rec := range h.recs {
340 rs.AddRecord(rec) 348 rs.AddRecord(rec)
@@ -358,7 +366,7 @@ type BoxHandler struct {
358} 366}
359 367
360// NewBoxHandler returns a new BlockHandler instance 368// NewBoxHandler returns a new BlockHandler instance
361func NewBoxHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) { 369func NewBoxHandler(rec *message.ResourceRecord, labels []string) (BlockHandler, error) {
362 if int(rec.Type) != enums.GNS_TYPE_BOX { 370 if int(rec.Type) != enums.GNS_TYPE_BOX {
363 return nil, ErrInvalidRecordType 371 return nil, ErrInvalidRecordType
364 } 372 }
@@ -372,7 +380,7 @@ func NewBoxHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandle
372} 380}
373 381
374// AddRecord inserts a BOX record into the handler. 382// AddRecord inserts a BOX record into the handler.
375func (h *BoxHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error { 383func (h *BoxHandler) AddRecord(rec *message.ResourceRecord, labels []string) error {
376 if int(rec.Type) != enums.GNS_TYPE_BOX { 384 if int(rec.Type) != enums.GNS_TYPE_BOX {
377 return ErrInvalidRecordType 385 return ErrInvalidRecordType
378 } 386 }
@@ -403,12 +411,12 @@ func (h *BoxHandler) Coexist(cm util.CounterMap) bool {
403} 411}
404 412
405// Records returns a list of RR of the given type associated with this handler 413// Records returns a list of RR of the given type associated with this handler
406func (h *BoxHandler) Records(kind RRTypeList) *message.GNSRecordSet { 414func (h *BoxHandler) Records(kind RRTypeList) *message.RecordSet {
407 rs := message.NewGNSRecordSet() 415 rs := message.NewRecordSet()
408 for _, box := range h.boxes { 416 for _, box := range h.boxes {
409 if kind.HasType(int(box.Type)) { 417 if kind.HasType(int(box.Type)) {
410 // valid box found: assemble new resource record. 418 // valid box found: assemble new resource record.
411 rr := new(message.GNSResourceRecord) 419 rr := new(message.ResourceRecord)
412 rr.Expires = box.rec.Expires 420 rr.Expires = box.rec.Expires
413 rr.Flags = box.rec.Flags 421 rr.Flags = box.rec.Flags
414 rr.Type = box.Type 422 rr.Type = box.Type
@@ -432,11 +440,11 @@ func (h *BoxHandler) Name() string {
432// LehoHandler implementing the BlockHandler interface 440// LehoHandler implementing the BlockHandler interface
433type LehoHandler struct { 441type LehoHandler struct {
434 name string 442 name string
435 rec *message.GNSResourceRecord 443 rec *message.ResourceRecord
436} 444}
437 445
438// NewLehoHandler returns a new BlockHandler instance 446// NewLehoHandler returns a new BlockHandler instance
439func NewLehoHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) { 447func NewLehoHandler(rec *message.ResourceRecord, labels []string) (BlockHandler, error) {
440 if int(rec.Type) != enums.GNS_TYPE_LEHO { 448 if int(rec.Type) != enums.GNS_TYPE_LEHO {
441 return nil, ErrInvalidRecordType 449 return nil, ErrInvalidRecordType
442 } 450 }
@@ -450,7 +458,7 @@ func NewLehoHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandl
450} 458}
451 459
452// AddRecord inserts a LEHO record into the handler. 460// AddRecord inserts a LEHO record into the handler.
453func (h *LehoHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error { 461func (h *LehoHandler) AddRecord(rec *message.ResourceRecord, labels []string) error {
454 if int(rec.Type) != enums.GNS_TYPE_LEHO { 462 if int(rec.Type) != enums.GNS_TYPE_LEHO {
455 return ErrInvalidRecordType 463 return ErrInvalidRecordType
456 } 464 }
@@ -467,8 +475,8 @@ func (h *LehoHandler) Coexist(cm util.CounterMap) bool {
467} 475}
468 476
469// Records returns a list of RR of the given type associated with this handler 477// Records returns a list of RR of the given type associated with this handler
470func (h *LehoHandler) Records(kind RRTypeList) *message.GNSRecordSet { 478func (h *LehoHandler) Records(kind RRTypeList) *message.RecordSet {
471 rs := message.NewGNSRecordSet() 479 rs := message.NewRecordSet()
472 if kind.HasType(enums.GNS_TYPE_LEHO) { 480 if kind.HasType(enums.GNS_TYPE_LEHO) {
473 rs.AddRecord(h.rec) 481 rs.AddRecord(h.rec)
474 } 482 }
@@ -487,11 +495,11 @@ func (h *LehoHandler) Name() string {
487// CnameHandler implementing the BlockHandler interface 495// CnameHandler implementing the BlockHandler interface
488type CnameHandler struct { 496type CnameHandler struct {
489 name string 497 name string
490 rec *message.GNSResourceRecord 498 rec *message.ResourceRecord
491} 499}
492 500
493// NewCnameHandler returns a new BlockHandler instance 501// NewCnameHandler returns a new BlockHandler instance
494func NewCnameHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) { 502func NewCnameHandler(rec *message.ResourceRecord, labels []string) (BlockHandler, error) {
495 if int(rec.Type) != enums.GNS_TYPE_DNS_CNAME { 503 if int(rec.Type) != enums.GNS_TYPE_DNS_CNAME {
496 return nil, ErrInvalidRecordType 504 return nil, ErrInvalidRecordType
497 } 505 }
@@ -505,7 +513,7 @@ func NewCnameHandler(rec *message.GNSResourceRecord, labels []string) (BlockHand
505} 513}
506 514
507// AddRecord inserts a CNAME record into the handler. 515// AddRecord inserts a CNAME record into the handler.
508func (h *CnameHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error { 516func (h *CnameHandler) AddRecord(rec *message.ResourceRecord, labels []string) error {
509 if int(rec.Type) != enums.GNS_TYPE_DNS_CNAME { 517 if int(rec.Type) != enums.GNS_TYPE_DNS_CNAME {
510 return ErrInvalidRecordType 518 return ErrInvalidRecordType
511 } 519 }
@@ -525,8 +533,8 @@ func (h *CnameHandler) Coexist(cm util.CounterMap) bool {
525} 533}
526 534
527// Records returns a list of RR of the given type associated with this handler 535// Records returns a list of RR of the given type associated with this handler
528func (h *CnameHandler) Records(kind RRTypeList) *message.GNSRecordSet { 536func (h *CnameHandler) Records(kind RRTypeList) *message.RecordSet {
529 rs := message.NewGNSRecordSet() 537 rs := message.NewRecordSet()
530 if kind.HasType(enums.GNS_TYPE_DNS_CNAME) { 538 if kind.HasType(enums.GNS_TYPE_DNS_CNAME) {
531 rs.AddRecord(h.rec) 539 rs.AddRecord(h.rec)
532 } 540 }
@@ -544,11 +552,11 @@ func (h *CnameHandler) Name() string {
544 552
545// VpnHandler implementing the BlockHandler interface 553// VpnHandler implementing the BlockHandler interface
546type VpnHandler struct { 554type VpnHandler struct {
547 rec *message.GNSResourceRecord 555 rec *message.ResourceRecord
548} 556}
549 557
550// NewVpnHandler returns a new BlockHandler instance 558// NewVpnHandler returns a new BlockHandler instance
551func NewVpnHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) { 559func NewVpnHandler(rec *message.ResourceRecord, labels []string) (BlockHandler, error) {
552 if int(rec.Type) != enums.GNS_TYPE_VPN { 560 if int(rec.Type) != enums.GNS_TYPE_VPN {
553 return nil, ErrInvalidRecordType 561 return nil, ErrInvalidRecordType
554 } 562 }
@@ -560,7 +568,7 @@ func NewVpnHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandle
560} 568}
561 569
562// AddRecord inserts a VPN record into the handler. 570// AddRecord inserts a VPN record into the handler.
563func (h *VpnHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error { 571func (h *VpnHandler) AddRecord(rec *message.ResourceRecord, labels []string) error {
564 if int(rec.Type) != enums.GNS_TYPE_VPN { 572 if int(rec.Type) != enums.GNS_TYPE_VPN {
565 return ErrInvalidRecordType 573 return ErrInvalidRecordType
566 } 574 }
@@ -579,8 +587,8 @@ func (h *VpnHandler) Coexist(cm util.CounterMap) bool {
579} 587}
580 588
581// Records returns a list of RR of the given type associated with this handler 589// Records returns a list of RR of the given type associated with this handler
582func (h *VpnHandler) Records(kind RRTypeList) *message.GNSRecordSet { 590func (h *VpnHandler) Records(kind RRTypeList) *message.RecordSet {
583 rs := message.NewGNSRecordSet() 591 rs := message.NewRecordSet()
584 if kind.HasType(enums.GNS_TYPE_VPN) { 592 if kind.HasType(enums.GNS_TYPE_VPN) {
585 rs.AddRecord(h.rec) 593 rs.AddRecord(h.rec)
586 } 594 }
diff --git a/src/gnunet/service/gns/box.go b/src/gnunet/service/gns/box.go
index 306ca68..1afd843 100644
--- a/src/gnunet/service/gns/box.go
+++ b/src/gnunet/service/gns/box.go
@@ -37,12 +37,12 @@ type Box struct {
37 RR []byte `size:"*"` // embedded RR 37 RR []byte `size:"*"` // embedded RR
38 38
39 // transient attributes (not serialized) 39 // transient attributes (not serialized)
40 key string // map key for box instance 40 key string // map key for box instance
41 rec *message.GNSResourceRecord // originating RR 41 rec *message.ResourceRecord // originating RR
42} 42}
43 43
44// NewBox creates a new box instance from a BOX resource record. 44// NewBox creates a new box instance from a BOX resource record.
45func NewBox(rec *message.GNSResourceRecord) *Box { 45func NewBox(rec *message.ResourceRecord) *Box {
46 b := new(Box) 46 b := new(Box)
47 if err := data.Unmarshal(b, rec.Data); err != nil { 47 if err := data.Unmarshal(b, rec.Data); err != nil {
48 logger.Printf(logger.ERROR, "[gns] Can't unmarshal BOX") 48 logger.Printf(logger.ERROR, "[gns] Can't unmarshal BOX")
diff --git a/src/gnunet/service/gns/dns.go b/src/gnunet/service/gns/dns.go
index 7a9a30c..3bcc35e 100644
--- a/src/gnunet/service/gns/dns.go
+++ b/src/gnunet/service/gns/dns.go
@@ -24,21 +24,21 @@ import (
24 "strings" 24 "strings"
25 "time" 25 "time"
26 26
27 "gnunet/crypto"
27 "gnunet/enums" 28 "gnunet/enums"
28 "gnunet/message" 29 "gnunet/message"
29 "gnunet/service" 30 "gnunet/service"
30 "gnunet/util" 31 "gnunet/util"
31 32
32 "github.com/bfix/gospel/crypto/ed25519"
33 "github.com/bfix/gospel/logger" 33 "github.com/bfix/gospel/logger"
34 "github.com/miekg/dns" 34 "github.com/miekg/dns"
35) 35)
36 36
37// Error codes 37// Error codes
38var ( 38var (
39 ErrDNSTimedOut = fmt.Errorf("DNS query timed out") 39 ErrDNSTimedOut = fmt.Errorf("query timed out (DNS)")
40 ErrNoDNSQueries = fmt.Errorf("No valid DNS queries") 40 ErrNoDNSQueries = fmt.Errorf("no valid DNS queries")
41 ErrNoDNSResults = fmt.Errorf("No valid DNS results") 41 ErrNoDNSResults = fmt.Errorf("no valid DNS results")
42) 42)
43 43
44//---------------------------------------------------------------------- 44//----------------------------------------------------------------------
@@ -48,7 +48,7 @@ var (
48// RRTypeList is a list of integers representing RR types. 48// RRTypeList is a list of integers representing RR types.
49type RRTypeList []int 49type RRTypeList []int
50 50
51// Initialize a new type list with given type values 51// NewRRTypeList initializes a new type list with given type values
52func NewRRTypeList(args ...int) (res RRTypeList) { 52func NewRRTypeList(args ...int) (res RRTypeList) {
53 for _, val := range args { 53 for _, val := range args {
54 // if GNS_TYPE_ANY is encountered, it becomes the sole type 54 // if GNS_TYPE_ANY is encountered, it becomes the sole type
@@ -92,7 +92,7 @@ func (tl RRTypeList) HasType(t int) bool {
92// Helper functions 92// Helper functions
93//---------------------------------------------------------------------- 93//----------------------------------------------------------------------
94 94
95// Convert DNS name from its binary representation [RFC1034]: 95// DNSNameFromBytes converts DNS name from its binary representation [RFC1034]:
96// A string is a sequence of a (len,chars...) tupels terminated by a (len=0,). 96// A string is a sequence of a (len,chars...) tupels terminated by a (len=0,).
97// The name parts are concatenated with "." as separator. 97// The name parts are concatenated with "." as separator.
98// The parsing starts at offset in the byte array; the function returns the 98// The parsing starts at offset in the byte array; the function returns the
@@ -115,7 +115,8 @@ func DNSNameFromBytes(b []byte, offset int) (int, string) {
115 return pos + 1, str 115 return pos + 1, str
116} 116}
117 117
118func QueryDNS(id int, name string, server net.IP, kind RRTypeList) *message.GNSRecordSet { 118// QueryDNS queries the specified DNS server for a given name and expected result types.
119func QueryDNS(id int, name string, server net.IP, kind RRTypeList) *message.RecordSet {
119 // get default nameserver if not defined. 120 // get default nameserver if not defined.
120 if server == nil { 121 if server == nil {
121 server = net.IPv4(8, 8, 8, 8) 122 server = net.IPv4(8, 8, 8, 8)
@@ -134,9 +135,9 @@ func QueryDNS(id int, name string, server net.IP, kind RRTypeList) *message.GNSR
134 Question: make([]dns.Question, 1), 135 Question: make([]dns.Question, 1),
135 } 136 }
136 m.Question[0] = dns.Question{ 137 m.Question[0] = dns.Question{
137 dns.Fqdn(name), 138 Name: dns.Fqdn(name),
138 dns.TypeANY, 139 Qtype: dns.TypeANY,
139 dns.ClassINET, 140 Qclass: dns.ClassINET,
140 } 141 }
141 142
142 // perform query in retry-loop 143 // perform query in retry-loop
@@ -160,7 +161,7 @@ func QueryDNS(id int, name string, server net.IP, kind RRTypeList) *message.GNSR
160 logger.Printf(logger.ERROR, "[dns][%d] No results\n", id) 161 logger.Printf(logger.ERROR, "[dns][%d] No results\n", id)
161 return nil 162 return nil
162 } 163 }
163 set := message.NewGNSRecordSet() 164 set := message.NewRecordSet()
164 for _, record := range in.Answer { 165 for _, record := range in.Answer {
165 // check if answer record is of requested type 166 // check if answer record is of requested type
166 if kind.HasType(int(record.Header().Rrtype)) { 167 if kind.HasType(int(record.Header().Rrtype)) {
@@ -173,7 +174,7 @@ func QueryDNS(id int, name string, server net.IP, kind RRTypeList) *message.GNSR
173 } 174 }
174 175
175 // create a new GNS resource record 176 // create a new GNS resource record
176 rr := new(message.GNSResourceRecord) 177 rr := new(message.ResourceRecord)
177 expires := time.Now().Add(time.Duration(record.Header().Ttl) * time.Second) 178 expires := time.Now().Add(time.Duration(record.Header().Ttl) * time.Second)
178 rr.Expires = util.NewAbsoluteTime(expires) 179 rr.Expires = util.NewAbsoluteTime(expires)
179 rr.Flags = 0 180 rr.Flags = 0
@@ -203,17 +204,17 @@ func QueryDNS(id int, name string, server net.IP, kind RRTypeList) *message.GNSR
203// ResolveDNS resolves a name in DNS. Multiple DNS servers are queried in 204// ResolveDNS resolves a name in DNS. Multiple DNS servers are queried in
204// parallel; the first result delivered by any of the servers is returned 205// parallel; the first result delivered by any of the servers is returned
205// as the result list of matching resource records. 206// as the result list of matching resource records.
206func (gns *GNSModule) ResolveDNS( 207func (gns *Module) ResolveDNS(
207 ctx *service.SessionContext, 208 ctx *service.SessionContext,
208 name string, 209 name string,
209 servers []string, 210 servers []string,
210 kind RRTypeList, 211 kind RRTypeList,
211 pkey *ed25519.PublicKey, 212 zkey *crypto.ZoneKey,
212 depth int) (set *message.GNSRecordSet, err error) { 213 depth int) (set *message.RecordSet, err error) {
213 214
214 // start DNS queries concurrently 215 // start DNS queries concurrently
215 logger.Printf(logger.DBG, "[dns] Resolution of '%s' starting...\n", name) 216 logger.Printf(logger.DBG, "[dns] Resolution of '%s' starting...\n", name)
216 res := make(chan *message.GNSRecordSet) 217 res := make(chan *message.RecordSet)
217 running := 0 218 running := 0
218 for _, srv := range servers { 219 for _, srv := range servers {
219 // check if srv is an IPv4/IPv6 address 220 // check if srv is an IPv4/IPv6 address
@@ -222,7 +223,7 @@ func (gns *GNSModule) ResolveDNS(
222 if addr == nil { 223 if addr == nil {
223 // no, it is a name... try to resolve an IP address from the name 224 // no, it is a name... try to resolve an IP address from the name
224 query := NewRRTypeList(enums.GNS_TYPE_DNS_A, enums.GNS_TYPE_DNS_AAAA) 225 query := NewRRTypeList(enums.GNS_TYPE_DNS_A, enums.GNS_TYPE_DNS_AAAA)
225 if set, err = gns.ResolveUnknown(ctx, srv, nil, pkey, query, depth+1); err != nil { 226 if set, err = gns.ResolveUnknown(ctx, srv, nil, zkey, query, depth+1); err != nil {
226 logger.Printf(logger.ERROR, "[dns] Can't resolve NS server '%s': %s\n", srv, err.Error()) 227 logger.Printf(logger.ERROR, "[dns] Can't resolve NS server '%s': %s\n", srv, err.Error())
227 continue 228 continue
228 } 229 }
@@ -255,7 +256,7 @@ func (gns *GNSModule) ResolveDNS(
255 return nil, ErrNoDNSQueries 256 return nil, ErrNoDNSQueries
256 } 257 }
257 // wait for query results 258 // wait for query results
258 timeout := time.Tick(10 * time.Second) 259 timeout := time.NewTicker(10 * time.Second)
259 for { 260 for {
260 select { 261 select {
261 case set = <-res: 262 case set = <-res:
@@ -271,7 +272,7 @@ func (gns *GNSModule) ResolveDNS(
271 return nil, ErrNoDNSResults 272 return nil, ErrNoDNSResults
272 } 273 }
273 274
274 case <-timeout: 275 case <-timeout.C:
275 // no results 276 // no results
276 logger.Println(logger.WARN, "[dns] Queries timed out.") 277 logger.Println(logger.WARN, "[dns] Queries timed out.")
277 return nil, ErrNoDNSResults 278 return nil, ErrNoDNSResults
diff --git a/src/gnunet/service/gns/module.go b/src/gnunet/service/gns/module.go
index 5e787d5..5ff81f2 100644
--- a/src/gnunet/service/gns/module.go
+++ b/src/gnunet/service/gns/module.go
@@ -20,6 +20,7 @@ package gns
20 20
21import ( 21import (
22 "fmt" 22 "fmt"
23 "net/http"
23 "strings" 24 "strings"
24 25
25 "gnunet/config" 26 "gnunet/config"
@@ -30,7 +31,6 @@ import (
30 "gnunet/service/revocation" 31 "gnunet/service/revocation"
31 "gnunet/util" 32 "gnunet/util"
32 33
33 "github.com/bfix/gospel/crypto/ed25519"
34 "github.com/bfix/gospel/logger" 34 "github.com/bfix/gospel/logger"
35) 35)
36 36
@@ -40,8 +40,8 @@ import (
40 40
41// Error codes 41// Error codes
42var ( 42var (
43 ErrUnknownTLD = fmt.Errorf("Unknown TLD in name") 43 ErrUnknownTLD = fmt.Errorf("unknown TLD in name")
44 ErrGNSRecursionExceeded = fmt.Errorf("GNS recursion depth exceeded") 44 ErrGNSRecursionExceeded = fmt.Errorf("recursion depth exceeded")
45) 45)
46 46
47//---------------------------------------------------------------------- 47//----------------------------------------------------------------------
@@ -51,20 +51,21 @@ var (
51// Query specifies the context for a basic GNS name lookup of an (atomic) 51// Query specifies the context for a basic GNS name lookup of an (atomic)
52// label in a given zone identified by its public key. 52// label in a given zone identified by its public key.
53type Query struct { 53type Query struct {
54 Zone *ed25519.PublicKey // Public zone key 54 Zone *crypto.ZoneKey // Public zone key
55 Label string // Atomic label 55 Label string // Atomic label
56 Derived *ed25519.PublicKey // Derived key from (pkey,label) 56 Derived *crypto.ZoneKey // Derived key from (pkey,label)
57 Key *crypto.HashCode // Key for repository queries (local/remote) 57 Key *crypto.HashCode // Key for repository queries (local/remote)
58} 58}
59 59
60// NewQuery assembles a new Query object for the given zone and label. 60// NewQuery assembles a new Query object for the given zone and label.
61func NewQuery(pkey *ed25519.PublicKey, label string) *Query { 61func NewQuery(zkey *crypto.ZoneKey, label string) *Query {
62 // derive a public key from (pkey,label) and set the repository 62 // derive a public key from (pkey,label) and set the repository
63 // key as the SHA512 hash of the binary key representation. 63 // key as the SHA512 hash of the binary key representation.
64 pd := crypto.DerivePublicKey(pkey, label, "gns") 64 // (key blinding)
65 pd, _ := zkey.Derive(label, "gns")
65 key := crypto.Hash(pd.Bytes()) 66 key := crypto.Hash(pd.Bytes())
66 return &Query{ 67 return &Query{
67 Zone: pkey, 68 Zone: zkey,
68 Label: label, 69 Label: label,
69 Derived: pd, 70 Derived: pd,
70 Key: key, 71 Key: key,
@@ -109,25 +110,32 @@ func NewQuery(pkey *ed25519.PublicKey, label string) *Query {
109// resource record types). 110// resource record types).
110//---------------------------------------------------------------------- 111//----------------------------------------------------------------------
111 112
112// GNSModule handles the resolution of GNS names to RRs bundled in a block. 113// Module handles the resolution of GNS names to RRs bundled in a block.
113type GNSModule struct { 114type Module struct {
114 // Use function references for calls to methods in other modules: 115 // Use function references for calls to methods in other modules:
115 LookupLocal func(ctx *service.SessionContext, query *Query) (*message.GNSBlock, error) 116 LookupLocal func(ctx *service.SessionContext, query *Query) (*message.Block, error)
116 StoreLocal func(ctx *service.SessionContext, block *message.GNSBlock) error 117 StoreLocal func(ctx *service.SessionContext, block *message.Block) error
117 LookupRemote func(ctx *service.SessionContext, query *Query) (*message.GNSBlock, error) 118 LookupRemote func(ctx *service.SessionContext, query *Query) (*message.Block, error)
118 RevocationQuery func(ctx *service.SessionContext, pkey *ed25519.PublicKey) (valid bool, err error) 119 RevocationQuery func(ctx *service.SessionContext, zkey *crypto.ZoneKey) (valid bool, err error)
119 RevocationRevoke func(ctx *service.SessionContext, rd *revocation.RevData) (success bool, err error) 120 RevocationRevoke func(ctx *service.SessionContext, rd *revocation.RevData) (success bool, err error)
120} 121}
121 122
123// RPC returns the route and handler function for a JSON-RPC request
124func (m *Module) RPC() (string, func(http.ResponseWriter, *http.Request)) {
125 return "/gns/", func(wrt http.ResponseWriter, req *http.Request) {
126 wrt.Write([]byte(`{"msg": "This is GNS" }`))
127 }
128}
129
122// Resolve a GNS name with multiple labels. If pkey is not nil, the name 130// Resolve a GNS name with multiple labels. If pkey is not nil, the name
123// is interpreted as "relative to current zone". 131// is interpreted as "relative to current zone".
124func (gns *GNSModule) Resolve( 132func (m *Module) Resolve(
125 ctx *service.SessionContext, 133 ctx *service.SessionContext,
126 path string, 134 path string,
127 pkey *ed25519.PublicKey, 135 zkey *crypto.ZoneKey,
128 kind RRTypeList, 136 kind RRTypeList,
129 mode int, 137 mode int,
130 depth int) (set *message.GNSRecordSet, err error) { 138 depth int) (set *message.RecordSet, err error) {
131 139
132 // check for recursion depth 140 // check for recursion depth
133 if depth > config.Cfg.GNS.MaxDepth { 141 if depth > config.Cfg.GNS.MaxDepth {
@@ -138,60 +146,62 @@ func (gns *GNSModule) Resolve(
138 logger.Printf(logger.DBG, "[gns] Resolver called for %v\n", names) 146 logger.Printf(logger.DBG, "[gns] Resolver called for %v\n", names)
139 147
140 // check for relative path 148 // check for relative path
141 if pkey != nil { 149 if zkey != nil {
142 //resolve relative path 150 //resolve relative path
143 return gns.ResolveRelative(ctx, names, pkey, kind, mode, depth) 151 return m.ResolveRelative(ctx, names, zkey, kind, mode, depth)
144 } 152 }
145 // resolve absolute path 153 // resolve absolute path
146 return gns.ResolveAbsolute(ctx, names, kind, mode, depth) 154 return m.ResolveAbsolute(ctx, names, kind, mode, depth)
147} 155}
148 156
149// Resolve a fully qualified GNS absolute name (with multiple labels). 157// ResolveAbsolute resolves a fully qualified GNS absolute name
150func (gns *GNSModule) ResolveAbsolute( 158// (with multiple labels).
159func (m *Module) ResolveAbsolute(
151 ctx *service.SessionContext, 160 ctx *service.SessionContext,
152 labels []string, 161 labels []string,
153 kind RRTypeList, 162 kind RRTypeList,
154 mode int, 163 mode int,
155 depth int) (set *message.GNSRecordSet, err error) { 164 depth int) (set *message.RecordSet, err error) {
156 165
157 // get the zone key for the TLD 166 // get the zone key for the TLD
158 pkey := gns.GetZoneKey(labels[0]) 167 zkey := m.GetZoneKey(labels[0])
159 if pkey == nil { 168 if zkey == nil {
160 // we can't resolve this TLD 169 // we can't resolve this TLD
161 err = ErrUnknownTLD 170 err = ErrUnknownTLD
162 return 171 return
163 } 172 }
164 // check if zone key has been revoked 173 // check if zone key has been revoked
165 var valid bool 174 var valid bool
166 set = message.NewGNSRecordSet() 175 set = message.NewRecordSet()
167 if valid, err = gns.RevocationQuery(ctx, pkey); err != nil || !valid { 176 if valid, err = m.RevocationQuery(ctx, zkey); err != nil || !valid {
168 return 177 return
169 } 178 }
170 // continue with resolution relative to a zone. 179 // continue with resolution relative to a zone.
171 return gns.ResolveRelative(ctx, labels[1:], pkey, kind, mode, depth) 180 return m.ResolveRelative(ctx, labels[1:], zkey, kind, mode, depth)
172} 181}
173 182
174// Resolve relative path (to a given zone) recursively by processing simple 183// ResolveRelative resolves a relative path (to a given zone) recursively by
175// (PKEY,Label) lookups in sequence and handle intermediate GNS record types 184// processing simple (PKEY,Label) lookups in sequence and handle intermediate
176func (gns *GNSModule) ResolveRelative( 185// GNS record types
186func (m *Module) ResolveRelative(
177 ctx *service.SessionContext, 187 ctx *service.SessionContext,
178 labels []string, 188 labels []string,
179 pkey *ed25519.PublicKey, 189 zkey *crypto.ZoneKey,
180 kind RRTypeList, 190 kind RRTypeList,
181 mode int, 191 mode int,
182 depth int) (set *message.GNSRecordSet, err error) { 192 depth int) (set *message.RecordSet, err error) {
183 193
184 // Process all names in sequence 194 // Process all names in sequence
185 var ( 195 var (
186 records []*message.GNSResourceRecord // final resource records from resolution 196 records []*message.ResourceRecord // final resource records from resolution
187 hdlrs *BlockHandlerList // list of block handlers in final step 197 hdlrs *BlockHandlerList // list of block handlers in final step
188 ) 198 )
189 for ; len(labels) > 0; labels = labels[1:] { 199 for ; len(labels) > 0; labels = labels[1:] {
190 logger.Printf(logger.DBG, "[gns] ResolveRelative '%s' in '%s'\n", labels[0], util.EncodeBinaryToString(pkey.Bytes())) 200 logger.Printf(logger.DBG, "[gns] ResolveRelative '%s' in '%s'\n", labels[0], util.EncodeBinaryToString(zkey.Bytes()))
191 201
192 // resolve next level 202 // resolve next level
193 var block *message.GNSBlock 203 var block *message.Block
194 if block, err = gns.Lookup(ctx, pkey, labels[0], mode); err != nil { 204 if block, err = m.Lookup(ctx, zkey, labels[0], mode); err != nil {
195 // failed to resolve name 205 // failed to resolve name
196 return 206 return
197 } 207 }
@@ -200,7 +210,7 @@ func (gns *GNSModule) ResolveRelative(
200 // if we have no results at this point, return NXDOMAIN 210 // if we have no results at this point, return NXDOMAIN
201 if block == nil { 211 if block == nil {
202 // return record set with no entries as signal for NXDOMAIN 212 // return record set with no entries as signal for NXDOMAIN
203 set = message.NewGNSRecordSet() 213 set = message.NewRecordSet()
204 return 214 return
205 } 215 }
206 mode = enums.GNS_LO_DEFAULT 216 mode = enums.GNS_LO_DEFAULT
@@ -228,20 +238,22 @@ func (gns *GNSModule) ResolveRelative(
228 // handle special block cases in priority order: 238 // handle special block cases in priority order:
229 //-------------------------------------------------------------- 239 //--------------------------------------------------------------
230 240
231 if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_PKEY); hdlr != nil { 241 if hdlr := hdlrs.GetHandler(
232 // (1) PKEY record: 242 enums.GNS_TYPE_PKEY,
233 inst := hdlr.(*PkeyHandler) 243 enums.GNS_TYPE_EDKEY,
244 ); hdlr != nil {
245 // (1) zone key record:
246 inst := hdlr.(*ZoneKeyHandler)
234 // if labels are pending, set new zone and continue resolution; 247 // if labels are pending, set new zone and continue resolution;
235 // otherwise resolve "@" label for the zone if no PKEY record 248 // otherwise resolve "@" label for the zone if no zone key record
236 // was requested. 249 // was requested.
237 pkey = inst.pkey
238 if len(labels) == 1 && !kind.HasType(enums.GNS_TYPE_PKEY) { 250 if len(labels) == 1 && !kind.HasType(enums.GNS_TYPE_PKEY) {
239 labels = append(labels, "@") 251 labels = append(labels, "@")
240 } 252 }
241 // check if zone key has been revoked 253 // check if zone key has been revoked
242 if valid, err := gns.RevocationQuery(ctx, pkey); err != nil || !valid { 254 if valid, err := m.RevocationQuery(ctx, inst.zkey); err != nil || !valid {
243 // revoked key -> no results! 255 // revoked key -> no results!
244 records = make([]*message.GNSResourceRecord, 0) 256 records = make([]*message.ResourceRecord, 0)
245 break 257 break
246 } 258 }
247 } else if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_GNS2DNS); hdlr != nil { 259 } else if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_GNS2DNS); hdlr != nil {
@@ -260,7 +272,7 @@ func (gns *GNSModule) ResolveRelative(
260 lbls += "." 272 lbls += "."
261 } 273 }
262 fqdn := lbls + inst.Query 274 fqdn := lbls + inst.Query
263 if set, err = gns.ResolveDNS(ctx, fqdn, inst.Servers, kind, pkey, depth); err != nil { 275 if set, err = m.ResolveDNS(ctx, fqdn, inst.Servers, kind, zkey, depth); err != nil {
264 logger.Println(logger.ERROR, "[gns] GNS2DNS resolution failed.") 276 logger.Println(logger.ERROR, "[gns] GNS2DNS resolution failed.")
265 return 277 return
266 } 278 }
@@ -275,7 +287,7 @@ func (gns *GNSModule) ResolveRelative(
275 expires = rec.Expires 287 expires = rec.Expires
276 } 288 }
277 } 289 }
278 set.Records = append(set.Records, gns.newLEHORecord(inst.Query, expires)) 290 set.Records = append(set.Records, m.newLEHORecord(inst.Query, expires))
279 } 291 }
280 // we are done with resolution; pass on records to caller 292 // we are done with resolution; pass on records to caller
281 records = set.Records 293 records = set.Records
@@ -283,9 +295,9 @@ func (gns *GNSModule) ResolveRelative(
283 } else if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_BOX); hdlr != nil { 295 } else if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_BOX); hdlr != nil {
284 // (3) BOX records: 296 // (3) BOX records:
285 inst := hdlr.(*BoxHandler) 297 inst := hdlr.(*BoxHandler)
286 new_records := inst.Records(kind).Records 298 newRecords := inst.Records(kind).Records
287 if len(new_records) > 0 { 299 if len(newRecords) > 0 {
288 records = new_records 300 records = newRecords
289 break 301 break
290 } 302 }
291 } else if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_DNS_CNAME); hdlr != nil { 303 } else if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_DNS_CNAME); hdlr != nil {
@@ -298,7 +310,7 @@ func (gns *GNSModule) ResolveRelative(
298 break 310 break
299 } 311 }
300 logger.Println(logger.DBG, "[gns] CNAME resolution required.") 312 logger.Println(logger.DBG, "[gns] CNAME resolution required.")
301 if set, err = gns.ResolveUnknown(ctx, inst.name, labels, pkey, kind, depth+1); err != nil { 313 if set, err = m.ResolveUnknown(ctx, inst.name, labels, zkey, kind, depth+1); err != nil {
302 logger.Println(logger.ERROR, "[gns] CNAME resolution failed.") 314 logger.Println(logger.ERROR, "[gns] CNAME resolution failed.")
303 return 315 return
304 } 316 }
@@ -309,7 +321,7 @@ func (gns *GNSModule) ResolveRelative(
309 } 321 }
310 // Assemble resulting resource record set by filtering for requested types. 322 // Assemble resulting resource record set by filtering for requested types.
311 // Records might get transformed by active block handlers. 323 // Records might get transformed by active block handlers.
312 set = message.NewGNSRecordSet() 324 set = message.NewRecordSet()
313 for _, rec := range records { 325 for _, rec := range records {
314 // is this the record type we are looking for? 326 // is this the record type we are looking for?
315 if kind.HasType(int(rec.Type)) { 327 if kind.HasType(int(rec.Type)) {
@@ -348,13 +360,13 @@ func (gns *GNSModule) ResolveRelative(
348// relative to the zone PKEY. If the name is an absolute GNS name (ending in 360// relative to the zone PKEY. If the name is an absolute GNS name (ending in
349// a PKEY TLD), it is also resolved with GNS. All other names are resolved 361// a PKEY TLD), it is also resolved with GNS. All other names are resolved
350// via DNS queries. 362// via DNS queries.
351func (gns *GNSModule) ResolveUnknown( 363func (m *Module) ResolveUnknown(
352 ctx *service.SessionContext, 364 ctx *service.SessionContext,
353 name string, 365 name string,
354 labels []string, 366 labels []string,
355 pkey *ed25519.PublicKey, 367 zkey *crypto.ZoneKey,
356 kind RRTypeList, 368 kind RRTypeList,
357 depth int) (set *message.GNSRecordSet, err error) { 369 depth int) (set *message.RecordSet, err error) {
358 370
359 // relative GNS-based server name? 371 // relative GNS-based server name?
360 if strings.HasSuffix(name, ".+") { 372 if strings.HasSuffix(name, ".+") {
@@ -363,14 +375,14 @@ func (gns *GNSModule) ResolveUnknown(
363 for _, label := range util.ReverseStringList(labels) { 375 for _, label := range util.ReverseStringList(labels) {
364 name += "." + label 376 name += "." + label
365 } 377 }
366 if set, err = gns.Resolve(ctx, name, pkey, kind, enums.GNS_LO_DEFAULT, depth+1); err != nil { 378 if set, err = m.Resolve(ctx, name, zkey, kind, enums.GNS_LO_DEFAULT, depth+1); err != nil {
367 return 379 return
368 } 380 }
369 } else { 381 } else {
370 // check for absolute GNS name (with PKEY as TLD) 382 // check for absolute GNS name (with PKEY as TLD)
371 if zk := gns.GetZoneKey(name); zk != nil { 383 if zk := m.GetZoneKey(name); zk != nil {
372 // resolve absolute GNS name (name ends in a PKEY) 384 // resolve absolute GNS name (name ends in a PKEY)
373 if set, err = gns.Resolve(ctx, util.StripPathRight(name), zk, kind, enums.GNS_LO_DEFAULT, depth+1); err != nil { 385 if set, err = m.Resolve(ctx, util.StripPathRight(name), zk, kind, enums.GNS_LO_DEFAULT, depth+1); err != nil {
374 return 386 return
375 } 387 }
376 } else { 388 } else {
@@ -383,13 +395,13 @@ func (gns *GNSModule) ResolveUnknown(
383 return 395 return
384} 396}
385 397
386// GetZoneKey returns the PKEY (or nil) from an absolute GNS path. 398// GetZoneKey returns the zone key (or nil) from an absolute GNS path.
387func (gns *GNSModule) GetZoneKey(path string) *ed25519.PublicKey { 399func (m *Module) GetZoneKey(path string) *crypto.ZoneKey {
388 labels := util.ReverseStringList(strings.Split(path, ".")) 400 labels := util.ReverseStringList(strings.Split(path, "."))
389 if len(labels[0]) == 52 { 401 if len(labels[0]) == 52 {
390 if data, err := util.DecodeStringToBinary(labels[0], 32); err == nil { 402 if data, err := util.DecodeStringToBinary(labels[0], 32); err == nil {
391 if pkey := ed25519.NewPublicKeyFromBytes(data); pkey != nil { 403 if zkey, err := crypto.NewZoneKey(data); err == nil {
392 return pkey 404 return zkey
393 } 405 }
394 } 406 }
395 } 407 }
@@ -397,17 +409,17 @@ func (gns *GNSModule) GetZoneKey(path string) *ed25519.PublicKey {
397} 409}
398 410
399// Lookup name in GNS. 411// Lookup name in GNS.
400func (gns *GNSModule) Lookup( 412func (m *Module) Lookup(
401 ctx *service.SessionContext, 413 ctx *service.SessionContext,
402 pkey *ed25519.PublicKey, 414 zkey *crypto.ZoneKey,
403 label string, 415 label string,
404 mode int) (block *message.GNSBlock, err error) { 416 mode int) (block *message.Block, err error) {
405 417
406 // create query (lookup key) 418 // create query (lookup key)
407 query := NewQuery(pkey, label) 419 query := NewQuery(zkey, label)
408 420
409 // try local lookup first 421 // try local lookup first
410 if block, err = gns.LookupLocal(ctx, query); err != nil { 422 if block, err = m.LookupLocal(ctx, query); err != nil {
411 logger.Printf(logger.ERROR, "[gns] local Lookup: %s\n", err.Error()) 423 logger.Printf(logger.ERROR, "[gns] local Lookup: %s\n", err.Error())
412 block = nil 424 block = nil
413 return 425 return
@@ -415,7 +427,7 @@ func (gns *GNSModule) Lookup(
415 if block == nil { 427 if block == nil {
416 if mode == enums.GNS_LO_DEFAULT { 428 if mode == enums.GNS_LO_DEFAULT {
417 // get the block from a remote lookup 429 // get the block from a remote lookup
418 if block, err = gns.LookupRemote(ctx, query); err != nil || block == nil { 430 if block, err = m.LookupRemote(ctx, query); err != nil || block == nil {
419 if err != nil { 431 if err != nil {
420 logger.Printf(logger.ERROR, "[gns] remote Lookup failed: %s\n", err.Error()) 432 logger.Printf(logger.ERROR, "[gns] remote Lookup failed: %s\n", err.Error())
421 block = nil 433 block = nil
@@ -426,15 +438,15 @@ func (gns *GNSModule) Lookup(
426 return 438 return
427 } 439 }
428 // store RRs from remote locally. 440 // store RRs from remote locally.
429 gns.StoreLocal(ctx, block) 441 m.StoreLocal(ctx, block)
430 } 442 }
431 } 443 }
432 return 444 return
433} 445}
434 446
435// newLEHORecord creates a new supplemental GNS record of type LEHO. 447// newLEHORecord creates a new supplemental GNS record of type LEHO.
436func (gns *GNSModule) newLEHORecord(name string, expires util.AbsoluteTime) *message.GNSResourceRecord { 448func (m *Module) newLEHORecord(name string, expires util.AbsoluteTime) *message.ResourceRecord {
437 rr := new(message.GNSResourceRecord) 449 rr := new(message.ResourceRecord)
438 rr.Expires = expires 450 rr.Expires = expires
439 rr.Flags = uint32(enums.GNS_FLAG_SUPPL) 451 rr.Flags = uint32(enums.GNS_FLAG_SUPPL)
440 rr.Type = uint32(enums.GNS_TYPE_LEHO) 452 rr.Type = uint32(enums.GNS_TYPE_LEHO)
diff --git a/src/gnunet/service/gns/service.go b/src/gnunet/service/gns/service.go
index f6310de..6fa1eb2 100644
--- a/src/gnunet/service/gns/service.go
+++ b/src/gnunet/service/gns/service.go
@@ -32,31 +32,30 @@ import (
32 "gnunet/transport" 32 "gnunet/transport"
33 "gnunet/util" 33 "gnunet/util"
34 34
35 "github.com/bfix/gospel/crypto/ed25519"
36 "github.com/bfix/gospel/data" 35 "github.com/bfix/gospel/data"
37 "github.com/bfix/gospel/logger" 36 "github.com/bfix/gospel/logger"
38) 37)
39 38
40// Error codes 39// Error codes
41var ( 40var (
42 ErrInvalidID = fmt.Errorf("Invalid/unassociated ID") 41 ErrInvalidID = fmt.Errorf("invalid/unassociated ID")
43 ErrBlockExpired = fmt.Errorf("Block expired") 42 ErrBlockExpired = fmt.Errorf("block expired")
44 ErrInvalidResponseType = fmt.Errorf("Invald response type") 43 ErrInvalidResponseType = fmt.Errorf("invald response type")
45) 44)
46 45
47//---------------------------------------------------------------------- 46//----------------------------------------------------------------------
48// "GNUnet Name System" service implementation 47// "GNUnet Name System" service implementation
49//---------------------------------------------------------------------- 48//----------------------------------------------------------------------
50 49
51// GNSService 50// Service implements a GNS service
52type GNSService struct { 51type Service struct {
53 GNSModule 52 Module
54} 53}
55 54
56// NewGNSService 55// NewService creates a new GNS service instance
57func NewGNSService() service.Service { 56func NewService() service.Service {
58 // instantiate service and assemble a new GNS handler. 57 // instantiate service and assemble a new GNS handler.
59 inst := new(GNSService) 58 inst := new(Service)
60 inst.LookupLocal = inst.LookupNamecache 59 inst.LookupLocal = inst.LookupNamecache
61 inst.StoreLocal = inst.StoreNamecache 60 inst.StoreLocal = inst.StoreNamecache
62 inst.LookupRemote = inst.LookupDHT 61 inst.LookupRemote = inst.LookupDHT
@@ -66,67 +65,65 @@ func NewGNSService() service.Service {
66} 65}
67 66
68// Start the GNS service 67// Start the GNS service
69func (s *GNSService) Start(spec string) error { 68func (s *Service) Start(spec string) error {
70 return nil 69 return nil
71} 70}
72 71
73// Stop the GNS service 72// Stop the GNS service
74func (s *GNSService) Stop() error { 73func (s *Service) Stop() error {
75 return nil 74 return nil
76} 75}
77 76
78// Serve a client channel. 77// ServeClient processes a client channel.
79func (s *GNSService) ServeClient(ctx *service.SessionContext, mc *transport.MsgChannel) { 78func (s *Service) ServeClient(ctx *service.SessionContext, mc *transport.MsgChannel) {
80 79 reqID := 0
81 reqId := 0
82loop: 80loop:
83 for { 81 for {
84 // receive next message from client 82 // receive next message from client
85 reqId++ 83 reqID++
86 logger.Printf(logger.DBG, "[gns:%d:%d] Waiting for client request...\n", ctx.Id, reqId) 84 logger.Printf(logger.DBG, "[gns:%d:%d] Waiting for client request...\n", ctx.ID, reqID)
87 msg, err := mc.Receive(ctx.Signaller()) 85 msg, err := mc.Receive(ctx.Signaller())
88 if err != nil { 86 if err != nil {
89 if err == io.EOF { 87 if err == io.EOF {
90 logger.Printf(logger.INFO, "[gns:%d:%d] Client channel closed.\n", ctx.Id, reqId) 88 logger.Printf(logger.INFO, "[gns:%d:%d] Client channel closed.\n", ctx.ID, reqID)
91 } else if err == transport.ErrChannelInterrupted { 89 } else if err == transport.ErrChannelInterrupted {
92 logger.Printf(logger.INFO, "[gns:%d:%d] Service operation interrupted.\n", ctx.Id, reqId) 90 logger.Printf(logger.INFO, "[gns:%d:%d] Service operation interrupted.\n", ctx.ID, reqID)
93 } else { 91 } else {
94 logger.Printf(logger.ERROR, "[gns:%d:%d] Message-receive failed: %s\n", ctx.Id, reqId, err.Error()) 92 logger.Printf(logger.ERROR, "[gns:%d:%d] Message-receive failed: %s\n", ctx.ID, reqID, err.Error())
95 } 93 }
96 break loop 94 break loop
97 } 95 }
98 logger.Printf(logger.INFO, "[gns:%d:%d] Received request: %v\n", ctx.Id, reqId, msg) 96 logger.Printf(logger.INFO, "[gns:%d:%d] Received request: %v\n", ctx.ID, reqID, msg)
99 97
100 // perform lookup 98 // perform lookup
101 switch m := msg.(type) { 99 switch m := msg.(type) {
102 case *message.GNSLookupMsg: 100 case *message.LookupMsg:
103 //---------------------------------------------------------- 101 //----------------------------------------------------------
104 // GNS_LOOKUP 102 // GNS_LOOKUP
105 //---------------------------------------------------------- 103 //----------------------------------------------------------
106 104
107 // perform lookup on block (locally and remote) 105 // perform lookup on block (locally and remote)
108 go func(id int, m *message.GNSLookupMsg) { 106 go func(id int, m *message.LookupMsg) {
109 logger.Printf(logger.INFO, "[gns:%d:%d] Lookup request received.\n", ctx.Id, id) 107 logger.Printf(logger.INFO, "[gns:%d:%d] Lookup request received.\n", ctx.ID, id)
110 resp := message.NewGNSLookupResultMsg(m.Id) 108 resp := message.NewGNSLookupResultMsg(m.ID)
111 ctx.Add() 109 ctx.Add()
112 defer func() { 110 defer func() {
113 // send response 111 // send response
114 if resp != nil { 112 if resp != nil {
115 if err := mc.Send(resp, ctx.Signaller()); err != nil { 113 if err := mc.Send(resp, ctx.Signaller()); err != nil {
116 logger.Printf(logger.ERROR, "[gns:%d:%d] Failed to send response: %s\n", ctx.Id, id, err.Error()) 114 logger.Printf(logger.ERROR, "[gns:%d:%d] Failed to send response: %s\n", ctx.ID, id, err.Error())
117 } 115 }
118 } 116 }
119 // go-routine finished 117 // go-routine finished
120 logger.Printf(logger.DBG, "[gns:%d:%d] Lookup request finished.\n", ctx.Id, id) 118 logger.Printf(logger.DBG, "[gns:%d:%d] Lookup request finished.\n", ctx.ID, id)
121 ctx.Remove() 119 ctx.Remove()
122 }() 120 }()
123 121
124 pkey := ed25519.NewPublicKeyFromBytes(m.Zone)
125 label := m.GetName() 122 label := m.GetName()
126 kind := NewRRTypeList(int(m.Type)) 123 kind := NewRRTypeList(int(m.Type))
127 recset, err := s.Resolve(ctx, label, pkey, kind, int(m.Options), 0) 124 recset, err := s.Resolve(ctx, label, m.Zone, kind, int(m.Options), 0)
128 if err != nil { 125 if err != nil {
129 logger.Printf(logger.ERROR, "[gns:%d:%d] Failed to lookup block: %s\n", ctx.Id, id, err.Error()) 126 logger.Printf(logger.ERROR, "[gns:%d:%d] Failed to lookup block: %s\n", ctx.ID, id, err.Error())
130 if err == transport.ErrChannelInterrupted { 127 if err == transport.ErrChannelInterrupted {
131 resp = nil 128 resp = nil
132 } 129 }
@@ -134,16 +131,16 @@ loop:
134 } 131 }
135 // handle records 132 // handle records
136 if recset != nil { 133 if recset != nil {
137 logger.Printf(logger.DBG, "[gns:%d:%d] Received record set with %d entries\n", ctx.Id, id, recset.Count) 134 logger.Printf(logger.DBG, "[gns:%d:%d] Received record set with %d entries\n", ctx.ID, id, recset.Count)
138 135
139 // get records from block 136 // get records from block
140 if recset.Count == 0 { 137 if recset.Count == 0 {
141 logger.Printf(logger.WARN, "[gns:%d:%d] No records in block\n", ctx.Id, id) 138 logger.Printf(logger.WARN, "[gns:%d:%d] No records in block\n", ctx.ID, id)
142 return 139 return
143 } 140 }
144 // process records 141 // process records
145 for i, rec := range recset.Records { 142 for i, rec := range recset.Records {
146 logger.Printf(logger.DBG, "[gns:%d:%d] Record #%d: %v\n", ctx.Id, id, i, rec) 143 logger.Printf(logger.DBG, "[gns:%d:%d] Record #%d: %v\n", ctx.ID, id, i, rec)
147 144
148 // is this the record type we are looking for? 145 // is this the record type we are looking for?
149 if rec.Type == m.Type || int(m.Type) == enums.GNS_TYPE_ANY { 146 if rec.Type == m.Type || int(m.Type) == enums.GNS_TYPE_ANY {
@@ -152,13 +149,13 @@ loop:
152 } 149 }
153 } 150 }
154 } 151 }
155 }(reqId, m) 152 }(reqID, m)
156 153
157 default: 154 default:
158 //---------------------------------------------------------- 155 //----------------------------------------------------------
159 // UNKNOWN message type received 156 // UNKNOWN message type received
160 //---------------------------------------------------------- 157 //----------------------------------------------------------
161 logger.Printf(logger.ERROR, "[gns:%d:%d] Unhandled message of type (%d)\n", ctx.Id, reqId, msg.Header().MsgType) 158 logger.Printf(logger.ERROR, "[gns:%d:%d] Unhandled message of type (%d)\n", ctx.ID, reqID, msg.Header().MsgType)
162 break loop 159 break loop
163 } 160 }
164 } 161 }
@@ -166,22 +163,24 @@ loop:
166 mc.Close() 163 mc.Close()
167 164
168 // cancel all tasks running for this session/connection 165 // cancel all tasks running for this session/connection
169 logger.Printf(logger.INFO, "[gns:%d] Start closing session... [%d]\n", ctx.Id, ctx.Waiting()) 166 logger.Printf(logger.INFO, "[gns:%d] Start closing session... [%d]\n", ctx.ID, ctx.Waiting())
170 ctx.Cancel() 167 ctx.Cancel()
171} 168}
172 169
173//====================================================================== 170//======================================================================
171// Revocationrelated methods
172//======================================================================
174 173
175// 174// QueryKeyRevocation checks if a key has been revoked
176func (s *GNSService) QueryKeyRevocation(ctx *service.SessionContext, pkey *ed25519.PublicKey) (valid bool, err error) { 175func (s *Service) QueryKeyRevocation(ctx *service.SessionContext, zkey *crypto.ZoneKey) (valid bool, err error) {
177 logger.Printf(logger.DBG, "[gns] QueryKeyRev(%s)...\n", util.EncodeBinaryToString(pkey.Bytes())) 176 logger.Printf(logger.DBG, "[gns] QueryKeyRev(%s)...\n", util.EncodeBinaryToString(zkey.Bytes()))
178 177
179 // assemble request 178 // assemble request
180 req := message.NewRevocationQueryMsg(pkey) 179 req := message.NewRevocationQueryMsg(zkey)
181 180
182 // get response from Revocation service 181 // get response from Revocation service
183 var resp message.Message 182 var resp message.Message
184 if resp, err = service.ServiceRequestResponse(ctx, "gns", "Revocation", config.Cfg.Revocation.Endpoint, req); err != nil { 183 if resp, err = service.RequestResponse(ctx, "gns", "Revocation", config.Cfg.Revocation.Endpoint, req); err != nil {
185 return 184 return
186 } 185 }
187 186
@@ -195,20 +194,19 @@ func (s *GNSService) QueryKeyRevocation(ctx *service.SessionContext, pkey *ed255
195 return 194 return
196} 195}
197 196
198// 197// RevokeKey revokes a key with given revocation data
199func (s *GNSService) RevokeKey(ctx *service.SessionContext, rd *revocation.RevData) (success bool, err error) { 198func (s *Service) RevokeKey(ctx *service.SessionContext, rd *revocation.RevData) (success bool, err error) {
200 logger.Printf(logger.DBG, "[gns] RevokeKey(%s)...\n", util.EncodeBinaryToString(rd.ZoneKey)) 199 logger.Printf(logger.DBG, "[gns] RevokeKey(%s)...\n", rd.ZoneKeySig.ID())
201 200
202 // assemble request 201 // assemble request
203 req := message.NewRevocationRevokeMsg(nil, nil) 202 req := message.NewRevocationRevokeMsg(nil)
204 req.Timestamp = rd.Timestamp 203 req.Timestamp = rd.Timestamp
205 copy(req.PoWs, rd.PoWs) 204 copy(req.PoWs, rd.PoWs)
206 copy(req.Signature, rd.Signature) 205 req.ZoneKeySig = rd.ZoneKeySig
207 copy(req.ZoneKey, rd.ZoneKey)
208 206
209 // get response from Revocation service 207 // get response from Revocation service
210 var resp message.Message 208 var resp message.Message
211 if resp, err = service.ServiceRequestResponse(ctx, "gns", "Revocation", config.Cfg.Revocation.Endpoint, req); err != nil { 209 if resp, err = service.RequestResponse(ctx, "gns", "Revocation", config.Cfg.Revocation.Endpoint, req); err != nil {
212 return 210 return
213 } 211 }
214 212
@@ -223,19 +221,21 @@ func (s *GNSService) RevokeKey(ctx *service.SessionContext, rd *revocation.RevDa
223} 221}
224 222
225//====================================================================== 223//======================================================================
224// Namecache-related methods
225//======================================================================
226 226
227// LookupNamecache 227// LookupNamecache returns a cached lookup (if available)
228func (s *GNSService) LookupNamecache(ctx *service.SessionContext, query *Query) (block *message.GNSBlock, err error) { 228func (s *Service) LookupNamecache(ctx *service.SessionContext, query *Query) (block *message.Block, err error) {
229 logger.Printf(logger.DBG, "[gns] LookupNamecache(%s)...\n", hex.EncodeToString(query.Key.Bits)) 229 logger.Printf(logger.DBG, "[gns] LookupNamecache(%s)...\n", hex.EncodeToString(query.Key.Bits))
230 230
231 // assemble Namecache request 231 // assemble Namecache request
232 req := message.NewNamecacheLookupMsg(query.Key) 232 req := message.NewNamecacheLookupMsg(query.Key)
233 req.Id = uint32(util.NextID()) 233 req.ID = uint32(util.NextID())
234 block = nil 234 block = nil
235 235
236 // get response from Namecache service 236 // get response from Namecache service
237 var resp message.Message 237 var resp message.Message
238 if resp, err = service.ServiceRequestResponse(ctx, "gns", "Namecache", config.Cfg.Namecache.Endpoint, req); err != nil { 238 if resp, err = service.RequestResponse(ctx, "gns", "Namecache", config.Cfg.Namecache.Endpoint, req); err != nil {
239 return 239 return
240 } 240 }
241 241
@@ -244,7 +244,7 @@ func (s *GNSService) LookupNamecache(ctx *service.SessionContext, query *Query)
244 switch m := resp.(type) { 244 switch m := resp.(type) {
245 case *message.NamecacheLookupResultMsg: 245 case *message.NamecacheLookupResultMsg:
246 // check for matching IDs 246 // check for matching IDs
247 if m.Id != req.Id { 247 if m.ID != req.ID {
248 logger.Println(logger.ERROR, "[gns] Got response for unknown ID") 248 logger.Println(logger.ERROR, "[gns] Got response for unknown ID")
249 err = ErrInvalidID 249 err = ErrInvalidID
250 break 250 break
@@ -262,9 +262,8 @@ func (s *GNSService) LookupNamecache(ctx *service.SessionContext, query *Query)
262 } 262 }
263 263
264 // assemble GNSBlock from message 264 // assemble GNSBlock from message
265 block = new(message.GNSBlock) 265 block = new(message.Block)
266 block.Signature = m.Signature 266 block.DerivedKeySig = m.DerivedKeySig
267 block.DerivedKey = m.DerivedKey
268 sb := new(message.SignedBlockData) 267 sb := new(message.SignedBlockData)
269 sb.Purpose = new(crypto.SignaturePurpose) 268 sb.Purpose = new(crypto.SignaturePurpose)
270 sb.Purpose.Purpose = enums.SIG_GNS_RECORD_SIGN 269 sb.Purpose.Purpose = enums.SIG_GNS_RECORD_SIGN
@@ -287,17 +286,17 @@ func (s *GNSService) LookupNamecache(ctx *service.SessionContext, query *Query)
287 return 286 return
288} 287}
289 288
290// StoreNamecache 289// StoreNamecache stores a lookup in the local namecache.
291func (s *GNSService) StoreNamecache(ctx *service.SessionContext, block *message.GNSBlock) (err error) { 290func (s *Service) StoreNamecache(ctx *service.SessionContext, block *message.Block) (err error) {
292 logger.Println(logger.DBG, "[gns] StoreNamecache()...") 291 logger.Println(logger.DBG, "[gns] StoreNamecache()...")
293 292
294 // assemble Namecache request 293 // assemble Namecache request
295 req := message.NewNamecacheCacheMsg(block) 294 req := message.NewNamecacheCacheMsg(block)
296 req.Id = uint32(util.NextID()) 295 req.ID = uint32(util.NextID())
297 296
298 // get response from Namecache service 297 // get response from Namecache service
299 var resp message.Message 298 var resp message.Message
300 if resp, err = service.ServiceRequestResponse(ctx, "gns", "Namecache", config.Cfg.Namecache.Endpoint, req); err != nil { 299 if resp, err = service.RequestResponse(ctx, "gns", "Namecache", config.Cfg.Namecache.Endpoint, req); err != nil {
301 return 300 return
302 } 301 }
303 302
@@ -306,7 +305,7 @@ func (s *GNSService) StoreNamecache(ctx *service.SessionContext, block *message.
306 switch m := resp.(type) { 305 switch m := resp.(type) {
307 case *message.NamecacheCacheResponseMsg: 306 case *message.NamecacheCacheResponseMsg:
308 // check for matching IDs 307 // check for matching IDs
309 if m.Id != req.Id { 308 if m.ID != req.ID {
310 logger.Println(logger.ERROR, "[gns] Got response for unknown ID") 309 logger.Println(logger.ERROR, "[gns] Got response for unknown ID")
311 err = ErrInvalidID 310 err = ErrInvalidID
312 break 311 break
@@ -315,7 +314,7 @@ func (s *GNSService) StoreNamecache(ctx *service.SessionContext, block *message.
315 if m.Result == 0 { 314 if m.Result == 0 {
316 return nil 315 return nil
317 } 316 }
318 return fmt.Errorf("Failed with rc=%d", m.Result) 317 return fmt.Errorf("failed with rc=%d", m.Result)
319 default: 318 default:
320 logger.Printf(logger.ERROR, "[gns] Got invalid response type (%d)\n", m.Header().MsgType) 319 logger.Printf(logger.ERROR, "[gns] Got invalid response type (%d)\n", m.Header().MsgType)
321 err = ErrInvalidResponseType 320 err = ErrInvalidResponseType
@@ -324,9 +323,11 @@ func (s *GNSService) StoreNamecache(ctx *service.SessionContext, block *message.
324} 323}
325 324
326//====================================================================== 325//======================================================================
326// DHT-related methods
327//======================================================================
327 328
328// LookupDHT 329// LookupDHT gets a GNS block from the DHT for the given query key.
329func (s *GNSService) LookupDHT(ctx *service.SessionContext, query *Query) (block *message.GNSBlock, err error) { 330func (s *Service) LookupDHT(ctx *service.SessionContext, query *Query) (block *message.Block, err error) {
330 logger.Printf(logger.DBG, "[gns] LookupDHT(%s)...\n", hex.EncodeToString(query.Key.Bits)) 331 logger.Printf(logger.DBG, "[gns] LookupDHT(%s)...\n", hex.EncodeToString(query.Key.Bits))
331 block = nil 332 block = nil
332 333
@@ -360,7 +361,7 @@ func (s *GNSService) LookupDHT(ctx *service.SessionContext, query *Query) (block
360 361
361 // send DHT GET request and wait for response 362 // send DHT GET request and wait for response
362 reqGet := message.NewDHTClientGetMsg(query.Key) 363 reqGet := message.NewDHTClientGetMsg(query.Key)
363 reqGet.Id = uint64(util.NextID()) 364 reqGet.ID = uint64(util.NextID())
364 reqGet.ReplLevel = uint32(enums.DHT_GNS_REPLICATION_LEVEL) 365 reqGet.ReplLevel = uint32(enums.DHT_GNS_REPLICATION_LEVEL)
365 reqGet.Type = uint32(enums.BLOCK_TYPE_GNS_NAMERECORD) 366 reqGet.Type = uint32(enums.BLOCK_TYPE_GNS_NAMERECORD)
366 reqGet.Options = uint32(enums.DHT_RO_DEMULTIPLEX_EVERYWHERE) 367 reqGet.Options = uint32(enums.DHT_RO_DEMULTIPLEX_EVERYWHERE)
@@ -372,7 +373,7 @@ func (s *GNSService) LookupDHT(ctx *service.SessionContext, query *Query) (block
372 373
373 // send DHT GET_STOP request and terminate 374 // send DHT GET_STOP request and terminate
374 reqStop := message.NewDHTClientGetStopMsg(query.Key) 375 reqStop := message.NewDHTClientGetStopMsg(query.Key)
375 reqStop.Id = reqGet.Id 376 reqStop.ID = reqGet.ID
376 if err = interact(reqStop, false); err != nil { 377 if err = interact(reqStop, false); err != nil {
377 logger.Printf(logger.ERROR, "[gns] remote Lookup abort failed: %s\n", err.Error()) 378 logger.Printf(logger.ERROR, "[gns] remote Lookup abort failed: %s\n", err.Error())
378 } 379 }
@@ -385,7 +386,7 @@ func (s *GNSService) LookupDHT(ctx *service.SessionContext, query *Query) (block
385 switch m := resp.(type) { 386 switch m := resp.(type) {
386 case *message.DHTClientResultMsg: 387 case *message.DHTClientResultMsg:
387 // check for matching IDs 388 // check for matching IDs
388 if m.Id != reqGet.Id { 389 if m.ID != reqGet.ID {
389 logger.Println(logger.ERROR, "[gns] Got response for unknown ID") 390 logger.Println(logger.ERROR, "[gns] Got response for unknown ID")
390 break 391 break
391 } 392 }
@@ -406,7 +407,7 @@ func (s *GNSService) LookupDHT(ctx *service.SessionContext, query *Query) (block
406 } 407 }
407 408
408 // get GNSBlock from message 409 // get GNSBlock from message
409 block = message.NewGNSBlock() 410 block = message.NewBlock()
410 if err = data.Unmarshal(block, m.Data); err != nil { 411 if err = data.Unmarshal(block, m.Data); err != nil {
411 logger.Printf(logger.ERROR, "[gns] can't read GNS block: %s\n", err.Error()) 412 logger.Printf(logger.ERROR, "[gns] can't read GNS block: %s\n", err.Error())
412 break 413 break
diff --git a/src/gnunet/service/namecache/module.go b/src/gnunet/service/namecache/module.go
index a205444..d5aa014 100644
--- a/src/gnunet/service/namecache/module.go
+++ b/src/gnunet/service/namecache/module.go
@@ -36,10 +36,10 @@ import (
36type NamecacheModule struct { 36type NamecacheModule struct {
37} 37}
38 38
39func (nc *NamecacheModule) Get(ctx *service.SessionContext, query *gns.Query) (*message.GNSBlock, error) { 39func (nc *NamecacheModule) Get(ctx *service.SessionContext, query *gns.Query) (*message.Block, error) {
40 return nil, nil 40 return nil, nil
41} 41}
42 42
43func (nc *NamecacheModule) Put(ctx *service.SessionContext, block *message.GNSBlock) error { 43func (nc *NamecacheModule) Put(ctx *service.SessionContext, block *message.Block) error {
44 return nil 44 return nil
45} 45}
diff --git a/src/gnunet/service/revocation/module.go b/src/gnunet/service/revocation/module.go
index 908cc2e..d13c069 100644
--- a/src/gnunet/service/revocation/module.go
+++ b/src/gnunet/service/revocation/module.go
@@ -20,10 +20,11 @@ package revocation
20 20
21import ( 21import (
22 "gnunet/config" 22 "gnunet/config"
23 "gnunet/crypto"
23 "gnunet/service" 24 "gnunet/service"
24 "gnunet/util" 25 "gnunet/util"
26 "net/http"
25 27
26 "github.com/bfix/gospel/crypto/ed25519"
27 "github.com/bfix/gospel/data" 28 "github.com/bfix/gospel/data"
28 "github.com/bfix/gospel/logger" 29 "github.com/bfix/gospel/logger"
29) 30)
@@ -32,14 +33,14 @@ import (
32// "GNUnet Revocation" implementation 33// "GNUnet Revocation" implementation
33//====================================================================== 34//======================================================================
34 35
35// RevocationModule handles the revocation-related calls to other modules. 36// Module handles the revocation-related calls to other modules.
36type RevocationModule struct { 37type Module struct {
37 bloomf *data.BloomFilter // bloomfilter for fast revocation check 38 bloomf *data.BloomFilter // bloomfilter for fast revocation check
38 kvs util.KeyValueStore // storage for known revocations 39 kvs util.KeyValueStore // storage for known revocations
39} 40}
40 41
41// Init a revocation module 42// Init a revocation module
42func (m *RevocationModule) Init() error { 43func (m *Module) Init() error {
43 // Initialize access to revocation data storage 44 // Initialize access to revocation data storage
44 var err error 45 var err error
45 if m.kvs, err = util.OpenKVStore(config.Cfg.Revocation.Storage); err != nil { 46 if m.kvs, err = util.OpenKVStore(config.Cfg.Revocation.Storage); err != nil {
@@ -61,9 +62,9 @@ func (m *RevocationModule) Init() error {
61 return nil 62 return nil
62} 63}
63 64
64// NewRevocationModule returns an initialized revocation module 65// NewModule returns an initialized revocation module
65func NewRevocationModule() *RevocationModule { 66func NewModule() *Module {
66 m := new(RevocationModule) 67 m := new(Module)
67 if err := m.Init(); err != nil { 68 if err := m.Init(); err != nil {
68 logger.Printf(logger.ERROR, "[revocation] Failed to initialize module: %s\n", err.Error()) 69 logger.Printf(logger.ERROR, "[revocation] Failed to initialize module: %s\n", err.Error())
69 return nil 70 return nil
@@ -71,18 +72,25 @@ func NewRevocationModule() *RevocationModule {
71 return m 72 return m
72} 73}
73 74
75// RPC returns the route and handler function for a JSON-RPC request
76func (m *Module) RPC() (string, func(http.ResponseWriter, *http.Request)) {
77 return "/revocation/", func(wrt http.ResponseWriter, req *http.Request) {
78 wrt.Write([]byte(`{"msg": "This is REVOCATION" }`))
79 }
80}
81
74// Query return true if the pkey is valid (not revoked) and false 82// Query return true if the pkey is valid (not revoked) and false
75// if the pkey has been revoked. 83// if the pkey has been revoked.
76func (s *RevocationModule) Query(ctx *service.SessionContext, pkey *ed25519.PublicKey) (valid bool, err error) { 84func (m *Module) Query(ctx *service.SessionContext, zkey *crypto.ZoneKey) (valid bool, err error) {
77 // fast check first: is the key in the bloomfilter? 85 // fast check first: is the key in the bloomfilter?
78 data := pkey.Bytes() 86 data := zkey.Bytes()
79 if !s.bloomf.Contains(data) { 87 if !m.bloomf.Contains(data) {
80 // no: it is valid (not revoked) 88 // no: it is valid (not revoked)
81 return true, nil 89 return true, nil
82 } 90 }
83 // check in store to detect false-positives 91 // check in store to detect false-positives
84 key := util.EncodeBinaryToString(data) 92 key := util.EncodeBinaryToString(data)
85 if _, err = s.kvs.Get(key); err != nil { 93 if _, err = m.kvs.Get(key); err != nil {
86 logger.Printf(logger.ERROR, "[revocation] Failed to locate key '%s' in store: %s\n", key, err.Error()) 94 logger.Printf(logger.ERROR, "[revocation] Failed to locate key '%s' in store: %s\n", key, err.Error())
87 // assume not revoked... 95 // assume not revoked...
88 return true, err 96 return true, err
@@ -91,8 +99,8 @@ func (s *RevocationModule) Query(ctx *service.SessionContext, pkey *ed25519.Publ
91 return false, nil 99 return false, nil
92} 100}
93 101
94// Revoke 102// Revoke a key with given revocation data
95func (s *RevocationModule) Revoke(ctx *service.SessionContext, rd *RevData) (success bool, err error) { 103func (m *Module) Revoke(ctx *service.SessionContext, rd *RevData) (success bool, err error) {
96 // verify the revocation data 104 // verify the revocation data
97 rc := rd.Verify(true) 105 rc := rd.Verify(true)
98 switch { 106 switch {
@@ -111,14 +119,13 @@ func (s *RevocationModule) Revoke(ctx *service.SessionContext, rd *RevData) (suc
111 } 119 }
112 // store the revocation data 120 // store the revocation data
113 // (1) add it to the bloomfilter 121 // (1) add it to the bloomfilter
114 s.bloomf.Add(rd.ZoneKey) 122 m.bloomf.Add(rd.ZoneKeySig.KeyData)
115 // (2) add it to the store 123 // (2) add it to the store
116 var buf []byte 124 var buf []byte
117 key := util.EncodeBinaryToString(rd.ZoneKey)
118 if buf, err = data.Marshal(rd); err != nil { 125 if buf, err = data.Marshal(rd); err != nil {
119 return false, err 126 return false, err
120 } 127 }
121 value := util.EncodeBinaryToString(buf) 128 value := util.EncodeBinaryToString(buf)
122 err = s.kvs.Put(key, value) 129 err = m.kvs.Put(rd.ZoneKeySig.ID(), value)
123 return true, err 130 return true, err
124} 131}
diff --git a/src/gnunet/service/revocation/pow.go b/src/gnunet/service/revocation/pow.go
index dd702b4..04bbb13 100644
--- a/src/gnunet/service/revocation/pow.go
+++ b/src/gnunet/service/revocation/pow.go
@@ -31,7 +31,6 @@ import (
31 "gnunet/message" 31 "gnunet/message"
32 "gnunet/util" 32 "gnunet/util"
33 33
34 "github.com/bfix/gospel/crypto/ed25519"
35 "github.com/bfix/gospel/data" 34 "github.com/bfix/gospel/data"
36 "github.com/bfix/gospel/math" 35 "github.com/bfix/gospel/math"
37 "golang.org/x/crypto/argon2" 36 "golang.org/x/crypto/argon2"
@@ -44,15 +43,15 @@ import (
44// PoWData is the proof-of-work data 43// PoWData is the proof-of-work data
45type PoWData struct { 44type PoWData struct {
46 PoW uint64 `order:"big"` // start with this PoW value 45 PoW uint64 `order:"big"` // start with this PoW value
47 Timestamp util.AbsoluteTime // Timestamp of creation 46 Timestamp util.AbsoluteTime `` // Timestamp of creation
48 ZoneKey []byte `size:"32"` // public zone key to be revoked 47 ZoneKey *crypto.ZoneKey `` // public zone key to be revoked
49 48
50 // transient attributes (not serialized) 49 // transient attributes (not serialized)
51 blob []byte // binary representation of serialized data 50 blob []byte // binary representation of serialized data
52} 51}
53 52
54// NewPoWData creates a PoWData instance for the given arguments. 53// NewPoWData creates a PoWData instance for the given arguments.
55func NewPoWData(pow uint64, ts util.AbsoluteTime, zoneKey []byte) *PoWData { 54func NewPoWData(pow uint64, ts util.AbsoluteTime, zoneKey *crypto.ZoneKey) *PoWData {
56 rd := &PoWData{ 55 rd := &PoWData{
57 PoW: 0, 56 PoW: 0,
58 Timestamp: ts, 57 Timestamp: ts,
@@ -69,7 +68,7 @@ func (p *PoWData) SetPoW(pow uint64) error {
69 p.PoW = pow 68 p.PoW = pow
70 p.blob = p.Blob() 69 p.blob = p.Blob()
71 if p.blob == nil { 70 if p.blob == nil {
72 return fmt.Errorf("Invalid PoW work unit") 71 return fmt.Errorf("invalid PoW work unit")
73 } 72 }
74 return nil 73 return nil
75} 74}
@@ -119,26 +118,24 @@ func (p *PoWData) Blob() []byte {
119 118
120// RevData is the revocation data (wire format) 119// RevData is the revocation data (wire format)
121type RevData struct { 120type RevData struct {
122 Timestamp util.AbsoluteTime // Timestamp of creation 121 Timestamp util.AbsoluteTime `` // Timestamp of creation
123 TTL util.RelativeTime // TTL of revocation 122 TTL util.RelativeTime `` // TTL of revocation
124 PoWs []uint64 `size:"32" order:"big"` // (Sorted) list of PoW values 123 PoWs []uint64 `size:"32" order:"big"` // (Sorted) list of PoW values
125 Signature []byte `size:"64"` // Signature (Proof-of-ownership). 124 ZoneKeySig *crypto.ZoneSignature `` // public zone key to be revoked
126 ZoneKey []byte `size:"32"` // public zone key to be revoked
127} 125}
128 126
129// SignedRevData is the block of data signed for a RevData instance. 127// SignedRevData is the block of data signed for a RevData instance.
130type SignedRevData struct { 128type SignedRevData struct {
131 Purpose *crypto.SignaturePurpose 129 Purpose *crypto.SignaturePurpose // signature purpose
132 ZoneKey []byte `size:"32"` // public zone key to be revoked 130 Timestamp util.AbsoluteTime // Timestamp of creation
133 Timestamp util.AbsoluteTime // Timestamp of creation 131 ZoneKey *crypto.ZoneKey // public zone key to be revoked
134} 132}
135 133
136// NewRevDataFromMsg initializes a new RevData instance from a GNUnet message 134// NewRevDataFromMsg initializes a new RevData instance from a GNUnet message
137func NewRevDataFromMsg(m *message.RevocationRevokeMsg) *RevData { 135func NewRevDataFromMsg(m *message.RevocationRevokeMsg) *RevData {
138 rd := &RevData{ 136 rd := &RevData{
139 Timestamp: m.Timestamp, 137 Timestamp: m.Timestamp,
140 Signature: util.Clone(m.Signature), 138 ZoneKeySig: m.ZoneKeySig,
141 ZoneKey: util.Clone(m.ZoneKey),
142 } 139 }
143 for i, pow := range m.PoWs { 140 for i, pow := range m.PoWs {
144 rd.PoWs[i] = pow 141 rd.PoWs[i] = pow
@@ -147,25 +144,20 @@ func NewRevDataFromMsg(m *message.RevocationRevokeMsg) *RevData {
147} 144}
148 145
149// Sign the revocation data 146// Sign the revocation data
150func (rd *RevData) Sign(skey *ed25519.PrivateKey) error { 147func (rd *RevData) Sign(skey *crypto.ZonePrivate) (err error) {
151 sigBlock := &SignedRevData{ 148 sigBlock := &SignedRevData{
152 Purpose: &crypto.SignaturePurpose{ 149 Purpose: &crypto.SignaturePurpose{
153 Size: 48, 150 Size: uint32(20 + rd.ZoneKeySig.KeySize()),
154 Purpose: enums.SIG_REVOCATION, 151 Purpose: enums.SIG_REVOCATION,
155 }, 152 },
156 ZoneKey: util.Clone(rd.ZoneKey),
157 Timestamp: rd.Timestamp, 153 Timestamp: rd.Timestamp,
154 ZoneKey: &rd.ZoneKeySig.ZoneKey,
158 } 155 }
159 sigData, err := data.Marshal(sigBlock) 156 sigData, err := data.Marshal(sigBlock)
160 if err != nil { 157 if err == nil {
161 return err 158 rd.ZoneKeySig, err = skey.Sign(sigData)
162 }
163 sig, err := skey.EcSign(sigData)
164 if err != nil {
165 return err
166 } 159 }
167 copy(rd.Signature, sig.Bytes()) 160 return
168 return nil
169} 161}
170 162
171// Verify a revocation object: returns the (smallest) number of leading 163// Verify a revocation object: returns the (smallest) number of leading
@@ -179,22 +171,17 @@ func (rd *RevData) Verify(withSig bool) int {
179 if withSig { 171 if withSig {
180 sigBlock := &SignedRevData{ 172 sigBlock := &SignedRevData{
181 Purpose: &crypto.SignaturePurpose{ 173 Purpose: &crypto.SignaturePurpose{
182 Size: 48, 174 Size: uint32(20 + rd.ZoneKeySig.KeySize()),
183 Purpose: enums.SIG_REVOCATION, 175 Purpose: enums.SIG_REVOCATION,
184 }, 176 },
185 ZoneKey: util.Clone(rd.ZoneKey),
186 Timestamp: rd.Timestamp, 177 Timestamp: rd.Timestamp,
178 ZoneKey: &rd.ZoneKeySig.ZoneKey,
187 } 179 }
188 sigData, err := data.Marshal(sigBlock) 180 sigData, err := data.Marshal(sigBlock)
189 if err != nil { 181 if err != nil {
190 return -1 182 return -1
191 } 183 }
192 pkey := ed25519.NewPublicKeyFromBytes(rd.ZoneKey) 184 valid, err := rd.ZoneKeySig.Verify(sigData)
193 sig, err := ed25519.NewEcSignatureFromBytes(rd.Signature)
194 if err != nil {
195 return -1
196 }
197 valid, err := pkey.EcVerify(sigData, sig)
198 if err != nil || !valid { 185 if err != nil || !valid {
199 return -1 186 return -1
200 } 187 }
@@ -212,7 +199,7 @@ func (rd *RevData) Verify(withSig bool) int {
212 } 199 }
213 last = pow 200 last = pow
214 // compute number of leading zero-bits 201 // compute number of leading zero-bits
215 work := NewPoWData(pow, rd.Timestamp, rd.ZoneKey) 202 work := NewPoWData(pow, rd.Timestamp, &rd.ZoneKeySig.ZoneKey)
216 zbits += float64(512 - work.Compute().BitLen()) 203 zbits += float64(512 - work.Compute().BitLen())
217 } 204 }
218 zbits /= 32.0 205 zbits /= 32.0
@@ -240,18 +227,16 @@ type RevDataCalc struct {
240} 227}
241 228
242// NewRevDataCalc initializes a new RevDataCalc instance 229// NewRevDataCalc initializes a new RevDataCalc instance
243func NewRevDataCalc(pkey []byte) *RevDataCalc { 230func NewRevDataCalc(zkey *crypto.ZoneKey) *RevDataCalc {
244 rd := &RevDataCalc{ 231 rd := &RevDataCalc{
245 RevData: RevData{ 232 RevData: RevData{
246 Timestamp: util.AbsoluteTimeNow(), 233 Timestamp: util.AbsoluteTimeNow(),
247 PoWs: make([]uint64, 32), 234 PoWs: make([]uint64, 32),
248 Signature: make([]byte, 64), 235 ZoneKeySig: nil,
249 ZoneKey: make([]byte, 32),
250 }, 236 },
251 Bits: make([]uint16, 32), 237 Bits: make([]uint16, 32),
252 SmallestIdx: 0, 238 SmallestIdx: 0,
253 } 239 }
254 copy(rd.ZoneKey, pkey)
255 return rd 240 return rd
256} 241}
257 242
@@ -294,7 +279,7 @@ func (rdc *RevDataCalc) sortBits() {
294// complete if the average above is greater or equal to 'bits'. 279// complete if the average above is greater or equal to 'bits'.
295func (rdc *RevDataCalc) Compute(ctx context.Context, bits int, last uint64, cb func(float64, uint64)) (float64, uint64) { 280func (rdc *RevDataCalc) Compute(ctx context.Context, bits int, last uint64, cb func(float64, uint64)) (float64, uint64) {
296 // find the largest PoW value in current work unit 281 // find the largest PoW value in current work unit
297 work := NewPoWData(0, rdc.Timestamp, rdc.ZoneKey) 282 work := NewPoWData(0, rdc.Timestamp, &rdc.ZoneKeySig.ZoneKey)
298 var max uint64 = 0 283 var max uint64 = 0
299 for i, pow := range rdc.PoWs { 284 for i, pow := range rdc.PoWs {
300 if pow == 0 { 285 if pow == 0 {
diff --git a/src/gnunet/service/revocation/pow_test.go b/src/gnunet/service/revocation/pow_test.go
index 6e7a355..8280402 100644
--- a/src/gnunet/service/revocation/pow_test.go
+++ b/src/gnunet/service/revocation/pow_test.go
@@ -3,130 +3,147 @@ package revocation
3import ( 3import (
4 "bytes" 4 "bytes"
5 "encoding/hex" 5 "encoding/hex"
6 "fmt" 6 "gnunet/crypto"
7 "gnunet/enums"
7 "testing" 8 "testing"
8 9
9 "gnunet/util"
10
11 "github.com/bfix/gospel/crypto/ed25519"
12 "github.com/bfix/gospel/data" 10 "github.com/bfix/gospel/data"
13 "github.com/bfix/gospel/math"
14) 11)
15 12
16type testData struct { 13// Test revocation with test vector defined in the RFC draft.
17 skey string 14func TestRevocationRFC(t *testing.T) {
18 pkey string
19 revdata string
20}
21 15
22var ( 16 var (
23 test_data = []testData{ 17 D = "6fea32c05af58bfa979553d188605fd57d8bf9cc263b78d5f7478c07b998ed70"
24 { 18 ZKEY = "000100002ca223e879ecc4bbdeb5da17319281d63b2e3b6955f1c3775c804a98d5f8ddaa"
19 DIFF = 7
20 PROOF = "" +
21 "0005d66da3598127" +
22 "0000395d1827c000" +
23 "3ab877d07570f2b8" +
24 "3ab877d07570f332" +
25 "3ab877d07570f4f5" +
26 "3ab877d07570f50f" +
27 "3ab877d07570f537" +
28 "3ab877d07570f599" +
29 "3ab877d07570f5cd" +
30 "3ab877d07570f5d9" +
31 "3ab877d07570f66a" +
32 "3ab877d07570f69b" +
33 "3ab877d07570f72f" +
34 "3ab877d07570f7c3" +
35 "3ab877d07570f843" +
36 "3ab877d07570f8d8" +
37 "3ab877d07570f91b" +
38 "3ab877d07570f93a" +
39 "3ab877d07570f944" +
40 "3ab877d07570f98a" +
41 "3ab877d07570f9a7" +
42 "3ab877d07570f9b0" +
43 "3ab877d07570f9df" +
44 "3ab877d07570fa05" +
45 "3ab877d07570fa3e" +
46 "3ab877d07570fa63" +
47 "3ab877d07570fa84" +
48 "3ab877d07570fa8f" +
49 "3ab877d07570fa91" +
50 "3ab877d07570fad6" +
51 "3ab877d07570fb0a" +
52 "3ab877d07570fc0f" +
53 "3ab877d07570fc43" +
54 "3ab877d07570fca5" +
55 "00010000" +
56 "2ca223e879ecc4bbdeb5da17319281d63b2e3b6955f1c3775c804a98d5f8ddaa" +
57 "053b0259700039187d1da4613531502bc4a4eeccc69900d24f8aac5430f28fc5092701331f178e290fe06e82ce2498ce7b23a34058e3d6a2f247e92bc9d7b9ab"
58 )
25 59
26 "90ea2a95cb9ef482b45817dc45b805cae00f387022a065a3674f41ad15173c63", // private scalar D 60 // construct private/public key pair from test data
27 "4ac1e51d9a585a9ad9fb0dfac2be100aee83f0cc79c4c5ea8f3eb8afd9092fa5", // public key 61 d, err := hex.DecodeString(D)
28 "" + 62 if err != nil {
29 "0005a5fd368978f4" + // private scalar D 63 t.Fatal(err)
30 "0000395d1827c000" + // public key Ed25519
31 "e23f657bc47ec853" + // PoW_0
32 "e23f657bc47ec9d8" +
33 "e23f657bc47ecaec" +
34 "e23f657bc47ecb29" +
35 "e23f657bc47ecc00" +
36 "e23f657bc47ecc79" +
37 "e23f657bc47ece83" +
38 "e23f657bc47ecfc6" +
39 "e23f657bc47ecfc8" +
40 "e23f657bc47ecfd5" +
41 "e23f657bc47ed02b" +
42 "e23f657bc47ed03b" +
43 "e23f657bc47ed0ff" +
44 "e23f657bc47ed241" +
45 "e23f657bc47ed264" +
46 "e23f657bc47ed2e5" +
47 "e23f657bc47ed343" +
48 "e23f657bc47ed348" +
49 "e23f657bc47ed45e" +
50 "e23f657bc47ed480" +
51 "e23f657bc47ed49a" +
52 "e23f657bc47ed564" +
53 "e23f657bc47ed565" +
54 "e23f657bc47ed5b6" +
55 "e23f657bc47ed5de" +
56 "e23f657bc47ed5e0" +
57 "e23f657bc47ed77f" +
58 "e23f657bc47ed800" +
59 "e23f657bc47ed80c" +
60 "e23f657bc47ed817" +
61 "e23f657bc47ed82c" +
62 "e23f657bc47ed8a6" + // PoW_31
63 "0396020c831a5405cee6c38842209191c8db799dbe81e0dcf6dbd4f91c257ae2" + // Sig.R
64 "0079e7fd1cd31cc24cd9a52831d5ec30f10e22e5a6dd906518746cfce2095610" + // Sig.S
65 "4ac1e51d9a585a9ad9fb0dfac2be100aee83f0cc79c4c5ea8f3eb8afd9092fa5", // PKEY
66 },
67 } 64 }
68) 65 prv, err := crypto.NewZonePrivate(crypto.ZONE_PKEY, d)
66 if err != nil {
67 t.Fatal(err)
68 }
69 zk := prv.Public()
69 70
70func TestRevocationRFC(t *testing.T) { 71 // check
72 zkey, err := hex.DecodeString(ZKEY)
73 if err != nil {
74 t.Fatal(err)
75 }
76 if !bytes.Equal(zk.Bytes(), zkey) {
77 t.Logf("zkey = %s\n", hex.EncodeToString(zk.Bytes()))
78 t.Logf("ZKEY = %s\n", hex.EncodeToString(zkey))
79 t.Fatal("Private/Public key mismatch")
80 }
71 81
72 for i, td := range test_data { 82 // assemble revocation data object
73 if testing.Verbose() { 83 revD, err := hex.DecodeString(PROOF)
74 fmt.Println("---------------------------------") 84 if err != nil {
75 fmt.Printf("Test case #%d\n", i+1) 85 t.Fatal(err)
76 fmt.Println("---------------------------------") 86 }
77 } 87 revData := new(RevData)
88 if err = data.Unmarshal(revData, revD); err != nil {
89 t.Fatal(err)
90 }
91 if !bytes.Equal(revData.ZoneKeySig.Bytes(), zkey) {
92 t.Logf("zkey = %s\n", hex.EncodeToString(revData.ZoneKeySig.Bytes()))
93 t.Logf("ZKEY = %s\n", hex.EncodeToString(zkey))
94 t.Fatal("Wrong zone key in test revocation")
95 }
78 96
79 // construct private/public key pair from test data 97 // show revdata content
80 skey_d, err := hex.DecodeString(td.skey) 98 if testing.Verbose() {
81 if err != nil { 99 t.Log("REVDATA:")
82 t.Fatal(err) 100 t.Logf(" Timestamp: %s\n", revData.Timestamp.String())
83 } 101 t.Logf(" TTL: %s\n", revData.TTL.String())
84 d := math.NewIntFromBytes(util.Reverse(skey_d))
85 skey := ed25519.NewPrivateKeyFromD(d)
86 pkey_d, err := hex.DecodeString(td.pkey)
87 if err != nil {
88 t.Fatal(err)
89 }
90 if bytes.Compare(skey.Public().Bytes(), pkey_d) != 0 {
91 t.Fatal("Private/Public key mismatch")
92 }
93 102
94 // assemble revocation data object 103 work := NewPoWData(0, revData.Timestamp, &revData.ZoneKeySig.ZoneKey)
95 rev_d, err := hex.DecodeString(td.revdata) 104 for i, pow := range revData.PoWs {
96 if err != nil { 105 t.Logf(" PoW #%d: %d\n", i, pow)
97 t.Fatal(err) 106 work.SetPoW(pow)
98 } 107 buf := work.Blob()
99 revData := new(RevData) 108 t.Logf(" P: %s\n", hex.EncodeToString(buf))
100 if err = data.Unmarshal(revData, rev_d); err != nil { 109 v := work.Compute()
101 t.Fatal(err) 110 t.Logf(" H: %s\n", hex.EncodeToString(v.Bytes()))
102 } 111 num := 512 - v.BitLen()
103 if bytes.Compare(revData.ZoneKey, pkey_d) != 0 { 112 t.Logf(" --> %d leading zeros\n", num)
104 t.Fatal("Wrong zone key in test revocation")
105 } 113 }
114 t.Logf(" ZoneKey: %s\n", hex.EncodeToString(revData.ZoneKeySig.KeyData))
115 t.Logf(" Signature: %s\n", hex.EncodeToString(revData.ZoneKeySig.Signature))
116 }
106 117
107 // show revdata content 118 // assemble data for signature
108 if testing.Verbose() { 119 sigBlock := &SignedRevData{
109 fmt.Println("REVDATA:") 120 Purpose: &crypto.SignaturePurpose{
110 fmt.Printf(" Timestamp: %s\n", revData.Timestamp.String()) 121 Size: uint32(20 + revData.ZoneKeySig.KeySize()),
111 fmt.Printf(" TTL: %s\n", revData.TTL.String()) 122 Purpose: enums.SIG_REVOCATION,
123 },
124 Timestamp: revData.Timestamp,
125 ZoneKey: &revData.ZoneKeySig.ZoneKey,
126 }
127 sigData, err := data.Marshal(sigBlock)
128 if err != nil {
129 t.Fatal(err)
130 }
131 if testing.Verbose() {
132 t.Logf("SigData = %s\n", hex.EncodeToString(sigData))
133 }
112 134
113 work := NewPoWData(0, revData.Timestamp, revData.ZoneKey) 135 sigOut, err := prv.Sign(sigData)
114 for i, pow := range revData.PoWs { 136 if err != nil {
115 fmt.Printf(" PoW #%d: %d\n", i, pow) 137 t.Fatal(err)
116 work.SetPoW(pow) 138 }
117 buf := work.Blob() 139 if testing.Verbose() {
118 fmt.Printf(" P: %s\n", hex.EncodeToString(buf)) 140 t.Logf("Signature = %s\n", hex.EncodeToString(sigOut.Signature))
119 v := work.Compute() 141 t.Logf(" ?= %s\n", hex.EncodeToString(revData.ZoneKeySig.Signature))
120 fmt.Printf(" H: %s\n", hex.EncodeToString(v.Bytes())) 142 }
121 num := 512 - v.BitLen()
122 fmt.Printf(" --> %d leading zeros\n", num)
123 }
124 fmt.Printf(" Signature: %s\n", hex.EncodeToString(revData.Signature))
125 fmt.Printf(" ZoneKey: %s\n", hex.EncodeToString(revData.ZoneKey))
126 }
127 143
128 // verify revocation data object 144 // verify revocation data object
129 rc := revData.Verify(true) 145 rc := revData.Verify(true)
130 fmt.Printf("REV_Verify (pkey): %d\n", rc) 146 if rc != DIFF {
147 t.Fatalf("REV_Verify (pkey): %d\n", rc)
131 } 148 }
132} 149}
diff --git a/src/gnunet/service/revocation/service.go b/src/gnunet/service/revocation/service.go
index f2a6ec3..a82e582 100644
--- a/src/gnunet/service/revocation/service.go
+++ b/src/gnunet/service/revocation/service.go
@@ -25,7 +25,6 @@ import (
25 "gnunet/service" 25 "gnunet/service"
26 "gnunet/transport" 26 "gnunet/transport"
27 27
28 "github.com/bfix/gospel/crypto/ed25519"
29 "github.com/bfix/gospel/logger" 28 "github.com/bfix/gospel/logger"
30) 29)
31 30
@@ -33,49 +32,48 @@ import (
33// "GNUnet Revocation" service implementation 32// "GNUnet Revocation" service implementation
34//---------------------------------------------------------------------- 33//----------------------------------------------------------------------
35 34
36// RevocationService 35// Service implements a revocation service
37type RevocationService struct { 36type Service struct {
38 RevocationModule 37 Module
39} 38}
40 39
41// NewRevocationService 40// NewService creates a new revocation service instance
42func NewRevocationService() service.Service { 41func NewService() service.Service {
43 // instantiate service and assemble a new Revocation handler. 42 // instantiate service and assemble a new Revocation handler.
44 inst := new(RevocationService) 43 inst := new(Service)
45 return inst 44 return inst
46} 45}
47 46
48// Start the Revocation service 47// Start the Revocation service
49func (s *RevocationService) Start(spec string) error { 48func (s *Service) Start(spec string) error {
50 return nil 49 return nil
51} 50}
52 51
53// Stop the Revocation service 52// Stop the Revocation service
54func (s *RevocationService) Stop() error { 53func (s *Service) Stop() error {
55 return nil 54 return nil
56} 55}
57 56
58// Serve a client channel. 57// ServeClient processes a client channel.
59func (s *RevocationService) ServeClient(ctx *service.SessionContext, mc *transport.MsgChannel) { 58func (s *Service) ServeClient(ctx *service.SessionContext, mc *transport.MsgChannel) {
60 59 reqID := 0
61 reqId := 0
62loop: 60loop:
63 for { 61 for {
64 // receive next message from client 62 // receive next message from client
65 reqId++ 63 reqID++
66 logger.Printf(logger.DBG, "[revocation:%d:%d] Waiting for client request...\n", ctx.Id, reqId) 64 logger.Printf(logger.DBG, "[revocation:%d:%d] Waiting for client request...\n", ctx.ID, reqID)
67 msg, err := mc.Receive(ctx.Signaller()) 65 msg, err := mc.Receive(ctx.Signaller())
68 if err != nil { 66 if err != nil {
69 if err == io.EOF { 67 if err == io.EOF {
70 logger.Printf(logger.INFO, "[revocation:%d:%d] Client channel closed.\n", ctx.Id, reqId) 68 logger.Printf(logger.INFO, "[revocation:%d:%d] Client channel closed.\n", ctx.ID, reqID)
71 } else if err == transport.ErrChannelInterrupted { 69 } else if err == transport.ErrChannelInterrupted {
72 logger.Printf(logger.INFO, "[revocation:%d:%d] Service operation interrupted.\n", ctx.Id, reqId) 70 logger.Printf(logger.INFO, "[revocation:%d:%d] Service operation interrupted.\n", ctx.ID, reqID)
73 } else { 71 } else {
74 logger.Printf(logger.ERROR, "[revocation:%d:%d] Message-receive failed: %s\n", ctx.Id, reqId, err.Error()) 72 logger.Printf(logger.ERROR, "[revocation:%d:%d] Message-receive failed: %s\n", ctx.ID, reqID, err.Error())
75 } 73 }
76 break loop 74 break loop
77 } 75 }
78 logger.Printf(logger.INFO, "[revocation:%d:%d] Received request: %v\n", ctx.Id, reqId, msg) 76 logger.Printf(logger.INFO, "[revocation:%d:%d] Received request: %v\n", ctx.ID, reqID, msg)
79 77
80 // handle request 78 // handle request
81 switch m := msg.(type) { 79 switch m := msg.(type) {
@@ -84,70 +82,69 @@ loop:
84 // REVOCATION_QUERY 82 // REVOCATION_QUERY
85 //---------------------------------------------------------- 83 //----------------------------------------------------------
86 go func(id int, m *message.RevocationQueryMsg) { 84 go func(id int, m *message.RevocationQueryMsg) {
87 logger.Printf(logger.INFO, "[revocation:%d:%d] Query request received.\n", ctx.Id, id) 85 logger.Printf(logger.INFO, "[revocation:%d:%d] Query request received.\n", ctx.ID, id)
88 var resp *message.RevocationQueryResponseMsg 86 var resp *message.RevocationQueryResponseMsg
89 ctx.Add() 87 ctx.Add()
90 defer func() { 88 defer func() {
91 // send response 89 // send response
92 if resp != nil { 90 if resp != nil {
93 if err := mc.Send(resp, ctx.Signaller()); err != nil { 91 if err := mc.Send(resp, ctx.Signaller()); err != nil {
94 logger.Printf(logger.ERROR, "[revocation:%d:%d] Failed to send response: %s\n", ctx.Id, id, err.Error()) 92 logger.Printf(logger.ERROR, "[revocation:%d:%d] Failed to send response: %s\n", ctx.ID, id, err.Error())
95 } 93 }
96 } 94 }
97 // go-routine finished 95 // go-routine finished
98 logger.Printf(logger.DBG, "[revocation:%d:%d] Query request finished.\n", ctx.Id, id) 96 logger.Printf(logger.DBG, "[revocation:%d:%d] Query request finished.\n", ctx.ID, id)
99 ctx.Remove() 97 ctx.Remove()
100 }() 98 }()
101 99
102 pkey := ed25519.NewPublicKeyFromBytes(m.Zone) 100 valid, err := s.Query(ctx, m.Zone)
103 valid, err := s.Query(ctx, pkey)
104 if err != nil { 101 if err != nil {
105 logger.Printf(logger.ERROR, "[revocation:%d:%d] Failed to query revocation status: %s\n", ctx.Id, id, err.Error()) 102 logger.Printf(logger.ERROR, "[revocation:%d:%d] Failed to query revocation status: %s\n", ctx.ID, id, err.Error())
106 if err == transport.ErrChannelInterrupted { 103 if err == transport.ErrChannelInterrupted {
107 resp = nil 104 resp = nil
108 } 105 }
109 return 106 return
110 } 107 }
111 resp = message.NewRevocationQueryResponseMsg(valid) 108 resp = message.NewRevocationQueryResponseMsg(valid)
112 }(reqId, m) 109 }(reqID, m)
113 110
114 case *message.RevocationRevokeMsg: 111 case *message.RevocationRevokeMsg:
115 //---------------------------------------------------------- 112 //----------------------------------------------------------
116 // REVOCATION_REVOKE 113 // REVOCATION_REVOKE
117 //---------------------------------------------------------- 114 //----------------------------------------------------------
118 go func(id int, m *message.RevocationRevokeMsg) { 115 go func(id int, m *message.RevocationRevokeMsg) {
119 logger.Printf(logger.INFO, "[revocation:%d:%d] Revoke request received.\n", ctx.Id, id) 116 logger.Printf(logger.INFO, "[revocation:%d:%d] Revoke request received.\n", ctx.ID, id)
120 var resp *message.RevocationRevokeResponseMsg 117 var resp *message.RevocationRevokeResponseMsg
121 ctx.Add() 118 ctx.Add()
122 defer func() { 119 defer func() {
123 // send response 120 // send response
124 if resp != nil { 121 if resp != nil {
125 if err := mc.Send(resp, ctx.Signaller()); err != nil { 122 if err := mc.Send(resp, ctx.Signaller()); err != nil {
126 logger.Printf(logger.ERROR, "[revocation:%d:%d] Failed to send response: %s\n", ctx.Id, id, err.Error()) 123 logger.Printf(logger.ERROR, "[revocation:%d:%d] Failed to send response: %s\n", ctx.ID, id, err.Error())
127 } 124 }
128 } 125 }
129 // go-routine finished 126 // go-routine finished
130 logger.Printf(logger.DBG, "[revocation:%d:%d] Revoke request finished.\n", ctx.Id, id) 127 logger.Printf(logger.DBG, "[revocation:%d:%d] Revoke request finished.\n", ctx.ID, id)
131 ctx.Remove() 128 ctx.Remove()
132 }() 129 }()
133 130
134 rd := NewRevDataFromMsg(m) 131 rd := NewRevDataFromMsg(m)
135 valid, err := s.Revoke(ctx, rd) 132 valid, err := s.Revoke(ctx, rd)
136 if err != nil { 133 if err != nil {
137 logger.Printf(logger.ERROR, "[revocation:%d:%d] Failed to revoke key: %s\n", ctx.Id, id, err.Error()) 134 logger.Printf(logger.ERROR, "[revocation:%d:%d] Failed to revoke key: %s\n", ctx.ID, id, err.Error())
138 if err == transport.ErrChannelInterrupted { 135 if err == transport.ErrChannelInterrupted {
139 resp = nil 136 resp = nil
140 } 137 }
141 return 138 return
142 } 139 }
143 resp = message.NewRevocationRevokeResponseMsg(valid) 140 resp = message.NewRevocationRevokeResponseMsg(valid)
144 }(reqId, m) 141 }(reqID, m)
145 142
146 default: 143 default:
147 //---------------------------------------------------------- 144 //----------------------------------------------------------
148 // UNKNOWN message type received 145 // UNKNOWN message type received
149 //---------------------------------------------------------- 146 //----------------------------------------------------------
150 logger.Printf(logger.ERROR, "[revocation:%d:%d] Unhandled message of type (%d)\n", ctx.Id, reqId, msg.Header().MsgType) 147 logger.Printf(logger.ERROR, "[revocation:%d:%d] Unhandled message of type (%d)\n", ctx.ID, reqID, msg.Header().MsgType)
151 break loop 148 break loop
152 } 149 }
153 } 150 }
@@ -155,6 +152,6 @@ loop:
155 mc.Close() 152 mc.Close()
156 153
157 // cancel all tasks running for this session/connection 154 // cancel all tasks running for this session/connection
158 logger.Printf(logger.INFO, "[revocation:%d] Start closing session... [%d]\n", ctx.Id, ctx.Waiting()) 155 logger.Printf(logger.INFO, "[revocation:%d] Start closing session... [%d]\n", ctx.ID, ctx.Waiting())
159 ctx.Cancel() 156 ctx.Cancel()
160} 157}
diff --git a/src/gnunet/service/service.go b/src/gnunet/service/service.go
index 1017e0b..c996e0c 100644
--- a/src/gnunet/service/service.go
+++ b/src/gnunet/service/service.go
@@ -20,6 +20,7 @@ package service
20 20
21import ( 21import (
22 "fmt" 22 "fmt"
23 "net/http"
23 "sync" 24 "sync"
24 25
25 "gnunet/transport" 26 "gnunet/transport"
@@ -27,18 +28,28 @@ import (
27 "github.com/bfix/gospel/logger" 28 "github.com/bfix/gospel/logger"
28) 29)
29 30
31// Module is an interface for GNUnet service modules (workers).
32type Module interface {
33 // RPC returns the route and handler for JSON-RPC requests
34 RPC() (string, func(http.ResponseWriter, *http.Request))
35}
36
30// Service is an interface for GNUnet services. Every service has one channel 37// Service is an interface for GNUnet services. Every service has one channel
31// end-point it listens to for incoming channel requests (network-based 38// end-point it listens to for incoming channel requests (network-based
32// channels established by service clients). The end-point is specified in 39// channels established by service clients). The end-point is specified in
33// Channel semantics in the specification string. 40// Channel semantics in the specification string.
34type Service interface { 41type Service interface {
42 Module
43 // Start a service on the given endpoint
35 Start(spec string) error 44 Start(spec string) error
45 // Serve a client session
36 ServeClient(ctx *SessionContext, ch *transport.MsgChannel) 46 ServeClient(ctx *SessionContext, ch *transport.MsgChannel)
47 // Stop the service
37 Stop() error 48 Stop() error
38} 49}
39 50
40// ServiceImpl is an implementation of generic service functionality. 51// Impl is an implementation of generic service functionality.
41type ServiceImpl struct { 52type Impl struct {
42 impl Service // Specific service implementation 53 impl Service // Specific service implementation
43 hdlr chan transport.Channel // Channel from listener 54 hdlr chan transport.Channel // Channel from listener
44 ctrl chan bool // Control channel 55 ctrl chan bool // Control channel
@@ -51,8 +62,8 @@ type ServiceImpl struct {
51} 62}
52 63
53// NewServiceImpl instantiates a new ServiceImpl object. 64// NewServiceImpl instantiates a new ServiceImpl object.
54func NewServiceImpl(name string, srv Service) *ServiceImpl { 65func NewServiceImpl(name string, srv Service) *Impl {
55 return &ServiceImpl{ 66 return &Impl{
56 impl: srv, 67 impl: srv,
57 hdlr: make(chan transport.Channel), 68 hdlr: make(chan transport.Channel),
58 ctrl: make(chan bool), 69 ctrl: make(chan bool),
@@ -66,7 +77,7 @@ func NewServiceImpl(name string, srv Service) *ServiceImpl {
66} 77}
67 78
68// Start a service 79// Start a service
69func (si *ServiceImpl) Start(spec string) (err error) { 80func (si *Impl) Start(spec string) (err error) {
70 // check if we are already running 81 // check if we are already running
71 if si.running { 82 if si.running {
72 logger.Printf(logger.ERROR, "Service '%s' already running.\n", si.name) 83 logger.Printf(logger.ERROR, "Service '%s' already running.\n", si.name)
@@ -98,22 +109,22 @@ func (si *ServiceImpl) Start(spec string) (err error) {
98 case transport.Channel: 109 case transport.Channel:
99 // run a new session with context 110 // run a new session with context
100 ctx := NewSessionContext() 111 ctx := NewSessionContext()
101 sessId := ctx.Id 112 sessID := ctx.ID
102 si.pending[sessId] = ctx 113 si.pending[sessID] = ctx
103 logger.Printf(logger.INFO, "[%s] Session '%d' started.\n", si.name, sessId) 114 logger.Printf(logger.INFO, "[%s] Session '%d' started.\n", si.name, sessID)
104 115
105 go func() { 116 go func() {
106 // serve client on the message channel 117 // serve client on the message channel
107 si.impl.ServeClient(ctx, transport.NewMsgChannel(ch)) 118 si.impl.ServeClient(ctx, transport.NewMsgChannel(ch))
108 // session is done now. 119 // session is done now.
109 logger.Printf(logger.INFO, "[%s] Session with client '%d' ended.\n", si.name, sessId) 120 logger.Printf(logger.INFO, "[%s] Session with client '%d' ended.\n", si.name, sessID)
110 si.drop <- sessId 121 si.drop <- sessID
111 }() 122 }()
112 } 123 }
113 124
114 // handle session removal 125 // handle session removal
115 case sessId := <-si.drop: 126 case sessID := <-si.drop:
116 delete(si.pending, sessId) 127 delete(si.pending, sessID)
117 128
118 // handle cancelation signal on listener. 129 // handle cancelation signal on listener.
119 case <-si.ctrl: 130 case <-si.ctrl:
@@ -123,7 +134,7 @@ func (si *ServiceImpl) Start(spec string) (err error) {
123 134
124 // terminate pending sessions 135 // terminate pending sessions
125 for _, ctx := range si.pending { 136 for _, ctx := range si.pending {
126 logger.Printf(logger.DBG, "[%s] Session '%d' closing...\n", si.name, ctx.Id) 137 logger.Printf(logger.DBG, "[%s] Session '%d' closing...\n", si.name, ctx.ID)
127 ctx.Cancel() 138 ctx.Cancel()
128 } 139 }
129 140
@@ -137,7 +148,7 @@ func (si *ServiceImpl) Start(spec string) (err error) {
137} 148}
138 149
139// Stop a service 150// Stop a service
140func (si *ServiceImpl) Stop() error { 151func (si *Impl) Stop() error {
141 if !si.running { 152 if !si.running {
142 logger.Printf(logger.WARN, "Service '%s' not running.\n", si.name) 153 logger.Printf(logger.WARN, "Service '%s' not running.\n", si.name)
143 return fmt.Errorf("service not running") 154 return fmt.Errorf("service not running")
diff --git a/src/gnunet/transport/channel.go b/src/gnunet/transport/channel.go
index 458a063..1632aab 100644
--- a/src/gnunet/transport/channel.go
+++ b/src/gnunet/transport/channel.go
@@ -35,9 +35,9 @@ import (
35 35
36// Error codes 36// Error codes
37var ( 37var (
38 ErrChannelNotImplemented = fmt.Errorf("Protocol not implemented") 38 ErrChannelNotImplemented = fmt.Errorf("protocol not implemented")
39 ErrChannelNotOpened = fmt.Errorf("Channel not opened") 39 ErrChannelNotOpened = fmt.Errorf("channel not opened")
40 ErrChannelInterrupted = fmt.Errorf("Channel interrupted") 40 ErrChannelInterrupted = fmt.Errorf("channel interrupted")
41) 41)
42 42
43//////////////////////////////////////////////////////////////////////// 43////////////////////////////////////////////////////////////////////////
@@ -102,7 +102,7 @@ var channelServerImpl = map[string]ChannelServerFactory{
102 "udp": NewUDPChannelServer, 102 "udp": NewUDPChannelServer,
103} 103}
104 104
105// NewChannelServer 105// NewChannelServer creates a new channel server instance
106func NewChannelServer(spec string, hdlr chan<- Channel) (cs ChannelServer, err error) { 106func NewChannelServer(spec string, hdlr chan<- Channel) (cs ChannelServer, err error) {
107 parts := strings.Split(spec, "+") 107 parts := strings.Split(spec, "+")
108 108
@@ -158,7 +158,7 @@ func (c *MsgChannel) Send(msg message.Message, sig *concurrent.Signaller) error
158 return err 158 return err
159 } 159 }
160 if len(data) != int(mh.MsgSize) { 160 if len(data) != int(mh.MsgSize) {
161 return errors.New("Send: message size mismatch") 161 return errors.New("send: message size mismatch")
162 } 162 }
163 163
164 // send packet 164 // send packet
@@ -167,7 +167,7 @@ func (c *MsgChannel) Send(msg message.Message, sig *concurrent.Signaller) error
167 return err 167 return err
168 } 168 }
169 if n != len(data) { 169 if n != len(data) {
170 return errors.New("Incomplete send") 170 return errors.New("incomplete send")
171 } 171 }
172 return nil 172 return nil
173} 173}
@@ -202,7 +202,7 @@ func (c *MsgChannel) Receive(sig *concurrent.Signaller) (message.Message, error)
202 return nil, err 202 return nil, err
203 } 203 }
204 if msg == nil { 204 if msg == nil {
205 return nil, fmt.Errorf("Message{%d} is nil!\n", mh.MsgType) 205 return nil, fmt.Errorf("message{%d} is nil", mh.MsgType)
206 } 206 }
207 if err = data.Unmarshal(msg, c.buf[:mh.MsgSize]); err != nil { 207 if err = data.Unmarshal(msg, c.buf[:mh.MsgSize]); err != nil {
208 return nil, err 208 return nil, err
diff --git a/src/gnunet/transport/channel_netw.go b/src/gnunet/transport/channel_netw.go
index b70faa4..c0de978 100644
--- a/src/gnunet/transport/channel_netw.go
+++ b/src/gnunet/transport/channel_netw.go
@@ -42,7 +42,7 @@ func NewChannelResult(n int, err error) *ChannelResult {
42 } 42 }
43} 43}
44 44
45// Values() returns the attributes of a result instance (for passing up the 45// Values returns the attributes of a result instance (for passing up the
46// call stack). 46// call stack).
47func (cr *ChannelResult) Values() (int, error) { 47func (cr *ChannelResult) Values() (int, error) {
48 return cr.count, cr.err 48 return cr.count, cr.err
@@ -51,7 +51,7 @@ func (cr *ChannelResult) Values() (int, error) {
51//////////////////////////////////////////////////////////////////////// 51////////////////////////////////////////////////////////////////////////
52// Generic network-based Channel 52// Generic network-based Channel
53 53
54// NetworkChannel 54// NetworkChannel represents a network-based channel
55type NetworkChannel struct { 55type NetworkChannel struct {
56 network string // network protocol identifier ("tcp", "unix", ...) 56 network string // network protocol identifier ("tcp", "unix", ...)
57 conn net.Conn // associated connection 57 conn net.Conn // associated connection
@@ -167,13 +167,13 @@ func (c *NetworkChannel) Write(buf []byte, sig *concurrent.Signaller) (int, erro
167//////////////////////////////////////////////////////////////////////// 167////////////////////////////////////////////////////////////////////////
168// Generic network-based ChannelServer 168// Generic network-based ChannelServer
169 169
170// NetworkChannelServer 170// NetworkChannelServer represents a network-based channel server
171type NetworkChannelServer struct { 171type NetworkChannelServer struct {
172 network string // network protocol to listen on 172 network string // network protocol to listen on
173 listener net.Listener // reference to listener object 173 listener net.Listener // reference to listener object
174} 174}
175 175
176// NewNetworkChannelServer 176// NewNetworkChannelServer creates a new network-based channel server
177func NewNetworkChannelServer(netw string) ChannelServer { 177func NewNetworkChannelServer(netw string) ChannelServer {
178 return &NetworkChannelServer{ 178 return &NetworkChannelServer{
179 network: netw, 179 network: netw,
@@ -254,32 +254,32 @@ func (s *NetworkChannelServer) Close() error {
254// helper functions to instantiate network channels and servers for 254// helper functions to instantiate network channels and servers for
255// common network protocols 255// common network protocols
256 256
257// NewSocketChannel: Unix Domain Socket connection 257// NewSocketChannel implements a Unix Domain Socket connection
258func NewSocketChannel() Channel { 258func NewSocketChannel() Channel {
259 return NewNetworkChannel("unix") 259 return NewNetworkChannel("unix")
260} 260}
261 261
262// NewTCPChannel: TCP connection 262// NewTCPChannel implements a: TCP connection
263func NewTCPChannel() Channel { 263func NewTCPChannel() Channel {
264 return NewNetworkChannel("tcp") 264 return NewNetworkChannel("tcp")
265} 265}
266 266
267// NewUDPChannel: UDP connection 267// NewUDPChannel implements an UDP connection
268func NewUDPChannel() Channel { 268func NewUDPChannel() Channel {
269 return NewNetworkChannel("udp") 269 return NewNetworkChannel("udp")
270} 270}
271 271
272// NewSocketChannelServer: Unix Domain Socket listener 272// NewSocketChannelServer implements an Unix Domain Socket listener
273func NewSocketChannelServer() ChannelServer { 273func NewSocketChannelServer() ChannelServer {
274 return NewNetworkChannelServer("unix") 274 return NewNetworkChannelServer("unix")
275} 275}
276 276
277// NewTCPChannelServer: TCP listener 277// NewTCPChannelServer implements a TCP listener
278func NewTCPChannelServer() ChannelServer { 278func NewTCPChannelServer() ChannelServer {
279 return NewNetworkChannelServer("tcp") 279 return NewNetworkChannelServer("tcp")
280} 280}
281 281
282// NewUDPChannelServer: UDP listener 282// NewUDPChannelServer implements an UDP listener
283func NewUDPChannelServer() ChannelServer { 283func NewUDPChannelServer() ChannelServer {
284 return NewNetworkChannelServer("udp") 284 return NewNetworkChannelServer("udp")
285} 285}
diff --git a/src/gnunet/transport/channel_test.go b/src/gnunet/transport/channel_test.go
index 41831b3..f028171 100644
--- a/src/gnunet/transport/channel_test.go
+++ b/src/gnunet/transport/channel_test.go
@@ -23,12 +23,17 @@ import (
23 "fmt" 23 "fmt"
24 "testing" 24 "testing"
25 "time" 25 "time"
26
27 "github.com/bfix/gospel/concurrent"
26) 28)
27 29
30// TODO: These test cases fail from time to time for no obvious reason.
31// This needs to be investigated.
32
28const ( 33const (
29 SOCK_ADDR = "/tmp/gnunet-go-test.sock" 34 SockAddr = "/tmp/gnunet-go-test.sock"
30 TCP_ADDR_CLIENT = "gnunet.org:80" 35 TCPAddrClient = "gnunet.org:80"
31 TCP_ADDR_SERVER = "127.0.0.1:12086" 36 TCPAddrServer = "127.0.0.1:9876"
32) 37)
33 38
34type TestChannelServer struct { 39type TestChannelServer struct {
@@ -45,14 +50,14 @@ func NewTestChannelServer() *TestChannelServer {
45 } 50 }
46} 51}
47 52
48func (s *TestChannelServer) handle(ch Channel) { 53func (s *TestChannelServer) handle(ch Channel, sig *concurrent.Signaller) {
49 buf := make([]byte, 4096) 54 buf := make([]byte, 4096)
50 for { 55 for {
51 n, err := ch.Read(buf) 56 n, err := ch.Read(buf, sig)
52 if err != nil { 57 if err != nil {
53 break 58 break
54 } 59 }
55 _, err = ch.Write(buf[:n]) 60 _, err = ch.Write(buf[:n], sig)
56 if err != nil { 61 if err != nil {
57 break 62 break
58 } 63 }
@@ -73,17 +78,16 @@ func (s *TestChannelServer) Start(spec string) (err error) {
73 s.running = true 78 s.running = true
74 79
75 // handle clients 80 // handle clients
81 sig := concurrent.NewSignaller()
76 go func() { 82 go func() {
77 for s.running { 83 for s.running {
78 select { 84 in := <-s.hdlr
79 case in := <-s.hdlr: 85 if in == nil {
80 if in == nil { 86 break
81 break 87 }
82 } 88 switch x := in.(type) {
83 switch x := in.(type) { 89 case Channel:
84 case Channel: 90 go s.handle(x, sig)
85 go s.handle(x)
86 }
87 } 91 }
88 } 92 }
89 s.srvc.Close() 93 s.srvc.Close()
@@ -99,33 +103,41 @@ func (s *TestChannelServer) Stop() {
99func TestChannelServerTCPSingle(t *testing.T) { 103func TestChannelServerTCPSingle(t *testing.T) {
100 time.Sleep(time.Second) 104 time.Sleep(time.Second)
101 s := NewTestChannelServer() 105 s := NewTestChannelServer()
102 if err := s.Start("tcp+" + TCP_ADDR_SERVER); err != nil { 106 err := s.Start("tcp+" + TCPAddrServer)
107 defer s.Stop()
108 if err != nil {
103 t.Fatal(err) 109 t.Fatal(err)
104 } 110 }
105 s.Stop()
106} 111}
107 112
108func TestChannelServerTCPTwice(t *testing.T) { 113func TestChannelServerTCPTwice(t *testing.T) {
109 time.Sleep(time.Second) 114 time.Sleep(time.Second)
110 s1 := NewTestChannelServer() 115 s1 := NewTestChannelServer()
111 if err := s1.Start("tcp+" + TCP_ADDR_SERVER); err != nil { 116 err := s1.Start("tcp+" + TCPAddrServer)
117 defer s1.Stop()
118 if err != nil {
112 t.Fatal(err) 119 t.Fatal(err)
113 } 120 }
121 time.Sleep(time.Second)
114 s2 := NewTestChannelServer() 122 s2 := NewTestChannelServer()
115 if err := s2.Start("tcp+" + TCP_ADDR_SERVER); err == nil { 123 err = s2.Start("tcp+" + TCPAddrServer)
124 defer s2.Stop()
125 if err == nil {
116 t.Fatal("SocketServer started twice!!") 126 t.Fatal("SocketServer started twice!!")
117 } 127 }
118 s1.Stop()
119} 128}
120 129
121func TestChannelClientTCP(t *testing.T) { 130func TestChannelClientTCP(t *testing.T) {
122 time.Sleep(time.Second) 131 time.Sleep(time.Second)
123 ch, err := NewChannel("tcp+" + TCP_ADDR_CLIENT) 132 ch, err := NewChannel("tcp+" + TCPAddrClient)
124 if err != nil { 133 if err != nil {
125 t.Fatal(err) 134 t.Fatal(err)
126 } 135 }
136 defer ch.Close()
137
138 sig := concurrent.NewSignaller()
127 msg := []byte("GET /\n\n") 139 msg := []byte("GET /\n\n")
128 n, err := ch.Write(msg) 140 n, err := ch.Write(msg, sig)
129 if err != nil { 141 if err != nil {
130 t.Fatal(err) 142 t.Fatal(err)
131 } 143 }
@@ -136,29 +148,29 @@ func TestChannelClientTCP(t *testing.T) {
136 n = 0 148 n = 0
137 start := time.Now().Unix() 149 start := time.Now().Unix()
138 for n == 0 && (time.Now().Unix()-start) < 3 { 150 for n == 0 && (time.Now().Unix()-start) < 3 {
139 if n, err = ch.Read(buf); err != nil { 151 if n, err = ch.Read(buf, sig); err != nil {
140 t.Fatal(err) 152 t.Fatal(err)
141 } 153 }
142 } 154 }
143 if err = ch.Close(); err != nil {
144 t.Fatal(err)
145 }
146 t.Logf("'%s' [%d]\n", string(buf[:n]), n) 155 t.Logf("'%s' [%d]\n", string(buf[:n]), n)
147} 156}
148 157
149func TestChannelClientServerTCP(t *testing.T) { 158func TestChannelClientServerTCP(t *testing.T) {
150 time.Sleep(time.Second) 159 time.Sleep(time.Second)
151 s := NewTestChannelServer() 160 s := NewTestChannelServer()
152 if err := s.Start("tcp+" + TCP_ADDR_SERVER); err != nil { 161 err := s.Start("tcp+" + TCPAddrServer)
162 defer s.Stop()
163 if err != nil {
153 t.Fatal(err) 164 t.Fatal(err)
154 } 165 }
155 166
156 ch, err := NewChannel("tcp+" + TCP_ADDR_SERVER) 167 ch, err := NewChannel("tcp+" + TCPAddrServer)
157 if err != nil { 168 if err != nil {
158 t.Fatal(err) 169 t.Fatal(err)
159 } 170 }
171 sig := concurrent.NewSignaller()
160 msg := []byte("GET /\n\n") 172 msg := []byte("GET /\n\n")
161 n, err := ch.Write(msg) 173 n, err := ch.Write(msg, sig)
162 if err != nil { 174 if err != nil {
163 t.Fatal(err) 175 t.Fatal(err)
164 } 176 }
@@ -169,33 +181,32 @@ func TestChannelClientServerTCP(t *testing.T) {
169 n = 0 181 n = 0
170 start := time.Now().Unix() 182 start := time.Now().Unix()
171 for n == 0 && (time.Now().Unix()-start) < 3 { 183 for n == 0 && (time.Now().Unix()-start) < 3 {
172 if n, err = ch.Read(buf); err != nil { 184 if n, err = ch.Read(buf, sig); err != nil {
173 t.Fatal(err) 185 t.Fatal(err)
174 } 186 }
175 } 187 }
176 if err = ch.Close(); err != nil { 188 if err = ch.Close(); err != nil {
177 t.Fatal(err) 189 t.Fatal(err)
178 } 190 }
179 if bytes.Compare(buf[:n], msg) != 0 { 191 if !bytes.Equal(buf[:n], msg) {
180 t.Fatal("message send/receive mismatch") 192 t.Fatal("message send/receive mismatch")
181 } 193 }
182
183 s.Stop()
184} 194}
185 195
186func TestChannelClientServerSock(t *testing.T) { 196func TestChannelClientServerSock(t *testing.T) {
187 time.Sleep(time.Second) 197 time.Sleep(time.Second)
188 s := NewTestChannelServer() 198 s := NewTestChannelServer()
189 if err := s.Start("unix+" + SOCK_ADDR); err != nil { 199 if err := s.Start("unix+" + SockAddr); err != nil {
190 t.Fatal(err) 200 t.Fatal(err)
191 } 201 }
192 202
193 ch, err := NewChannel("unix+" + SOCK_ADDR) 203 ch, err := NewChannel("unix+" + SockAddr)
194 if err != nil { 204 if err != nil {
195 t.Fatal(err) 205 t.Fatal(err)
196 } 206 }
207 sig := concurrent.NewSignaller()
197 msg := []byte("This is just a test -- please ignore...") 208 msg := []byte("This is just a test -- please ignore...")
198 n, err := ch.Write(msg) 209 n, err := ch.Write(msg, sig)
199 if err != nil { 210 if err != nil {
200 t.Fatal(err) 211 t.Fatal(err)
201 } 212 }
@@ -206,14 +217,14 @@ func TestChannelClientServerSock(t *testing.T) {
206 n = 0 217 n = 0
207 start := time.Now().Unix() 218 start := time.Now().Unix()
208 for n == 0 && (time.Now().Unix()-start) < 3 { 219 for n == 0 && (time.Now().Unix()-start) < 3 {
209 if n, err = ch.Read(buf); err != nil { 220 if n, err = ch.Read(buf, sig); err != nil {
210 t.Fatal(err) 221 t.Fatal(err)
211 } 222 }
212 } 223 }
213 if err = ch.Close(); err != nil { 224 if err = ch.Close(); err != nil {
214 t.Fatal(err) 225 t.Fatal(err)
215 } 226 }
216 if bytes.Compare(buf[:n], msg) != 0 { 227 if !bytes.Equal(buf[:n], msg) {
217 t.Fatal("message send/receive mismatch") 228 t.Fatal("message send/receive mismatch")
218 } 229 }
219 230
diff --git a/src/gnunet/transport/connection.go b/src/gnunet/transport/connection.go
index 03549fc..cc2c909 100644
--- a/src/gnunet/transport/connection.go
+++ b/src/gnunet/transport/connection.go
@@ -29,9 +29,7 @@ import (
29type Connection struct { 29type Connection struct {
30 from, to *core.Peer 30 from, to *core.Peer
31 ch *MsgChannel 31 ch *MsgChannel
32 buf []byte
33 bandwidth uint32 32 bandwidth uint32
34 init bool
35 state int 33 state int
36 shared []byte 34 shared []byte
37} 35}
diff --git a/src/gnunet/transport/session.go b/src/gnunet/transport/session.go
index f6a320e..f5a0787 100644
--- a/src/gnunet/transport/session.go
+++ b/src/gnunet/transport/session.go
@@ -20,10 +20,10 @@ package transport
20 20
21// Session states 21// Session states
22const ( 22const (
23 KX_STATE_DOWN = iota // No handshake yet. 23 KxStateDown = iota // No handshake yet.
24 KX_STATE_KEY_SENT // We've sent our session key. 24 KxStateKeySent // We've sent our session key.
25 KX_STATE_KEY_RECEIVED // We've received the other peers session key. 25 KxStateKeyReceived // We've received the other peers session key.
26 KX_STATE_UP // Key exchange is done. 26 KxStateUp // Key exchange is done.
27 KX_STATE_REKEY_SENT // We're rekeying (or had a timeout). 27 KxStateRekeySent // We're rekeying (or had a timeout).
28 KX_PEER_DISCONNECT // Last state of a KX (when it is being terminated). 28 KxPeerDisconnect // Last state of a KX (when it is being terminated).
29) 29)
diff --git a/src/gnunet/util/address.go b/src/gnunet/util/address.go
index 2d3e3ac..d272742 100644
--- a/src/gnunet/util/address.go
+++ b/src/gnunet/util/address.go
@@ -61,7 +61,7 @@ func AddressString(transport string, addr []byte) string {
61 61
62//---------------------------------------------------------------------- 62//----------------------------------------------------------------------
63 63
64// IP address (can be IPv4 or IPv6 or a DNS name) 64// IPAddress (can be IPv4 or IPv6 or a DNS name)
65type IPAddress struct { 65type IPAddress struct {
66 Host []byte `size:"*-2"` 66 Host []byte `size:"*-2"`
67 Port uint16 `order:"big"` 67 Port uint16 `order:"big"`
diff --git a/src/gnunet/util/array.go b/src/gnunet/util/array.go
index be25ef9..254610b 100644
--- a/src/gnunet/util/array.go
+++ b/src/gnunet/util/array.go
@@ -87,7 +87,7 @@ func Fill(b []byte, val byte) {
87// String list helpers 87// String list helpers
88//---------------------------------------------------------------------- 88//----------------------------------------------------------------------
89 89
90// Reverse StringList reverse an array of strings 90// ReverseStringList reverse an array of strings
91func ReverseStringList(s []string) []string { 91func ReverseStringList(s []string) []string {
92 sl := len(s) 92 sl := len(s)
93 r := make([]string, sl) 93 r := make([]string, sl)
@@ -97,9 +97,9 @@ func ReverseStringList(s []string) []string {
97 return r 97 return r
98} 98}
99 99
100// Convert a binary representation of a string list. Each string is '\0'- 100// StringList converts a binary representation of a string list. Each string
101// terminated. The whole byte array is parsed; if the final string is not 101// is '\0'-terminated. The whole byte array is parsed; if the final string is
102// terminated, it is skipped. 102// not terminated, it is skipped.
103func StringList(b []byte) []string { 103func StringList(b []byte) []string {
104 res := make([]string, 0) 104 res := make([]string, 0)
105 str := "" 105 str := ""
diff --git a/src/gnunet/util/database.go b/src/gnunet/util/database.go
index 48da749..5805a8f 100644
--- a/src/gnunet/util/database.go
+++ b/src/gnunet/util/database.go
@@ -24,17 +24,17 @@ import (
24 "os" 24 "os"
25 "strings" 25 "strings"
26 26
27 _ "github.com/go-sql-driver/mysql" 27 _ "github.com/go-sql-driver/mysql" // init MySQL driver
28 _ "github.com/mattn/go-sqlite3" 28 _ "github.com/mattn/go-sqlite3" // init SQLite3 driver
29) 29)
30 30
31// Error messages related to databases 31// Error messages related to databases
32var ( 32var (
33 ErrSqlInvalidDatabaseSpec = fmt.Errorf("Invalid database specification") 33 ErrSQLInvalidDatabaseSpec = fmt.Errorf("Invalid database specification")
34 ErrSqlNoDatabase = fmt.Errorf("Database not found") 34 ErrSQLNoDatabase = fmt.Errorf("Database not found")
35) 35)
36 36
37// ConnectSqlDatabase connects to an SQL database (various types and flavors): 37// ConnectSQLDatabase connects to an SQL database (various types and flavors):
38// The 'spec' option defines the arguments required to connect to a database; 38// The 'spec' option defines the arguments required to connect to a database;
39// the meaning and format of the arguments depends on the specific SQL database. 39// the meaning and format of the arguments depends on the specific SQL database.
40// The arguments are seperated by the '+' character; the first (and mandatory) 40// The arguments are seperated by the '+' character; the first (and mandatory)
@@ -46,21 +46,21 @@ var (
46// * 'mysql': A MySQL-compatible database; the second argument specifies the 46// * 'mysql': A MySQL-compatible database; the second argument specifies the
47// information required to log into the database (e.g. 47// information required to log into the database (e.g.
48// "[user[:passwd]@][proto[(addr)]]/dbname[?param1=value1&...]"). 48// "[user[:passwd]@][proto[(addr)]]/dbname[?param1=value1&...]").
49func ConnectSqlDatabase(spec string) (db *sql.DB, err error) { 49func ConnectSQLDatabase(spec string) (db *sql.DB, err error) {
50 // split spec string into segments 50 // split spec string into segments
51 specs := strings.Split(spec, ":") 51 specs := strings.Split(spec, ":")
52 if len(specs) < 2 { 52 if len(specs) < 2 {
53 return nil, ErrSqlInvalidDatabaseSpec 53 return nil, ErrSQLInvalidDatabaseSpec
54 } 54 }
55 switch specs[0] { 55 switch specs[0] {
56 case "sqlite3": 56 case "sqlite3":
57 // check if the database file exists 57 // check if the database file exists
58 var fi os.FileInfo 58 var fi os.FileInfo
59 if fi, err = os.Stat(specs[1]); err != nil { 59 if fi, err = os.Stat(specs[1]); err != nil {
60 return nil, ErrSqlNoDatabase 60 return nil, ErrSQLNoDatabase
61 } 61 }
62 if fi.IsDir() { 62 if fi.IsDir() {
63 return nil, ErrSqlNoDatabase 63 return nil, ErrSQLNoDatabase
64 } 64 }
65 // open the database file 65 // open the database file
66 return sql.Open("sqlite3", specs[1]) 66 return sql.Open("sqlite3", specs[1])
@@ -68,5 +68,5 @@ func ConnectSqlDatabase(spec string) (db *sql.DB, err error) {
68 // just connect to the database 68 // just connect to the database
69 return sql.Open("mysql", specs[1]) 69 return sql.Open("mysql", specs[1])
70 } 70 }
71 return nil, ErrSqlInvalidDatabaseSpec 71 return nil, ErrSQLInvalidDatabaseSpec
72} 72}
diff --git a/src/gnunet/util/id.go b/src/gnunet/util/id.go
index 14333bf..f2fb4f0 100644
--- a/src/gnunet/util/id.go
+++ b/src/gnunet/util/id.go
@@ -22,7 +22,8 @@ var (
22 _id = 0 22 _id = 0
23) 23)
24 24
25// generate next unique identifier (unique in the running process/application) 25// NextID generates the next unique identifier (unique in the running
26// process/application)
26func NextID() int { 27func NextID() int {
27 _id++ 28 _id++
28 return _id 29 return _id
diff --git a/src/gnunet/util/key_value_store.go b/src/gnunet/util/key_value_store.go
index d87b747..0658218 100644
--- a/src/gnunet/util/key_value_store.go
+++ b/src/gnunet/util/key_value_store.go
@@ -25,7 +25,7 @@ import (
25 "strconv" 25 "strconv"
26 "strings" 26 "strings"
27 27
28 "github.com/go-redis/redis" 28 redis "github.com/go-redis/redis/v8"
29) 29)
30 30
31// Error messages related to the key/value-store implementations 31// Error messages related to the key/value-store implementations
@@ -88,11 +88,11 @@ func OpenKVStore(spec string) (KeyValueStore, error) {
88 //-------------------------------------------------------------- 88 //--------------------------------------------------------------
89 // SQL-based persistance 89 // SQL-based persistance
90 //-------------------------------------------------------------- 90 //--------------------------------------------------------------
91 kvs := new(KvsSql) 91 kvs := new(KvsSQL)
92 var err error 92 var err error
93 93
94 // connect to SQL database 94 // connect to SQL database
95 kvs.db, err = ConnectSqlDatabase(spec) 95 kvs.db, err = ConnectSQLDatabase(spec)
96 if err != nil { 96 if err != nil {
97 return nil, err 97 return nil, err
98 } 98 }
@@ -111,7 +111,7 @@ func OpenKVStore(spec string) (KeyValueStore, error) {
111// NoSQL-based key-value-stores 111// NoSQL-based key-value-stores
112//====================================================================== 112//======================================================================
113 113
114// Redis-based key/value store 114// KvsRedis represents a redis-based key/value store
115type KvsRedis struct { 115type KvsRedis struct {
116 client *redis.Client // client connection 116 client *redis.Client // client connection
117 db int // index to database 117 db int // index to database
@@ -127,7 +127,7 @@ func (kvs *KvsRedis) Get(key string) (value string, err error) {
127 return kvs.client.Get(context.TODO(), key).Result() 127 return kvs.client.Get(context.TODO(), key).Result()
128} 128}
129 129
130// Get a list of all keys in store 130// List all keys in store
131func (kvs *KvsRedis) List() (keys []string, err error) { 131func (kvs *KvsRedis) List() (keys []string, err error) {
132 var ( 132 var (
133 crs uint64 133 crs uint64
@@ -151,26 +151,26 @@ func (kvs *KvsRedis) List() (keys []string, err error) {
151// SQL-based key-value-store 151// SQL-based key-value-store
152//====================================================================== 152//======================================================================
153 153
154// SQL-based key/value store 154// KvsSQL represents a SQL-based key/value store
155type KvsSql struct { 155type KvsSQL struct {
156 db *sql.DB 156 db *sql.DB
157} 157}
158 158
159// Put a key/value pair into the store 159// Put a key/value pair into the store
160func (kvs *KvsSql) Put(key string, value string) error { 160func (kvs *KvsSQL) Put(key string, value string) error {
161 _, err := kvs.db.Exec("insert into store(key,value) values(?,?)", key, value) 161 _, err := kvs.db.Exec("insert into store(key,value) values(?,?)", key, value)
162 return err 162 return err
163} 163}
164 164
165// Get a value for a given key from store 165// Get a value for a given key from store
166func (kvs *KvsSql) Get(key string) (value string, err error) { 166func (kvs *KvsSQL) Get(key string) (value string, err error) {
167 row := kvs.db.QueryRow("select value from store where key=?", key) 167 row := kvs.db.QueryRow("select value from store where key=?", key)
168 err = row.Scan(&value) 168 err = row.Scan(&value)
169 return 169 return
170} 170}
171 171
172// Get a list of all keys in store 172// List all keys in store
173func (kvs *KvsSql) List() (keys []string, err error) { 173func (kvs *KvsSQL) List() (keys []string, err error) {
174 var ( 174 var (
175 rows *sql.Rows 175 rows *sql.Rows
176 key string 176 key string
diff --git a/src/gnunet/util/misc.go b/src/gnunet/util/misc.go
index 80f5c84..66744bd 100644
--- a/src/gnunet/util/misc.go
+++ b/src/gnunet/util/misc.go
@@ -22,9 +22,10 @@ import (
22 "strings" 22 "strings"
23) 23)
24 24
25// CounterMap 25// CounterMap is a metric with single key
26type CounterMap map[interface{}]int 26type CounterMap map[interface{}]int
27 27
28// Add one to themetric for a given key and return current value
28func (cm CounterMap) Add(i interface{}) int { 29func (cm CounterMap) Add(i interface{}) int {
29 count, ok := cm[i] 30 count, ok := cm[i]
30 if !ok { 31 if !ok {
@@ -36,6 +37,7 @@ func (cm CounterMap) Add(i interface{}) int {
36 return count 37 return count
37} 38}
38 39
40// Num returns the metric for a given key
39func (cm CounterMap) Num(i interface{}) int { 41func (cm CounterMap) Num(i interface{}) int {
40 count, ok := cm[i] 42 count, ok := cm[i]
41 if !ok { 43 if !ok {
@@ -44,6 +46,8 @@ func (cm CounterMap) Num(i interface{}) int {
44 return count 46 return count
45} 47}
46 48
49// StripPathRight returns a dot-separated path without
50// its last (right-most) element.
47func StripPathRight(s string) string { 51func StripPathRight(s string) string {
48 if idx := strings.LastIndex(s, "."); idx != -1 { 52 if idx := strings.LastIndex(s, "."); idx != -1 {
49 return s[:idx] 53 return s[:idx]
diff --git a/src/gnunet/util/time.go b/src/gnunet/util/time.go
index bf2a1c2..e70635c 100644
--- a/src/gnunet/util/time.go
+++ b/src/gnunet/util/time.go
@@ -113,7 +113,7 @@ func (t AbsoluteTime) Compare(t2 AbsoluteTime) int {
113// Relative time 113// Relative time
114//---------------------------------------------------------------------- 114//----------------------------------------------------------------------
115 115
116// Relative time is a timestamp defined relative to the current time. 116// RelativeTime is a timestamp defined relative to the current time.
117// It actually is more like a duration than a time... 117// It actually is more like a duration than a time...
118type RelativeTime struct { 118type RelativeTime struct {
119 Val uint64 `order:"big"` 119 Val uint64 `order:"big"`
diff --git a/src/gnunet/util/time_test.go b/src/gnunet/util/time_test.go
new file mode 100644
index 0000000..d753d89
--- /dev/null
+++ b/src/gnunet/util/time_test.go
@@ -0,0 +1,44 @@
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 util
20
21import (
22 "testing"
23 "time"
24)
25
26func TestTimeCompare(t *testing.T) {
27 t1 := AbsoluteTimeNow()
28 t2 := t1.Add(time.Hour)
29 t3 := t1.Add(24 * time.Hour)
30 tNever := AbsoluteTimeNever()
31
32 if t1.Compare(t2) != -1 {
33 t.Fatal("(1)")
34 }
35 if t1.Compare(t3) != -1 {
36 t.Fatal("(2)")
37 }
38 if t2.Compare(t3) != -1 {
39 t.Fatal("(3)")
40 }
41 if tNever.Compare(t1) != 1 {
42 t.Fatal("(4)")
43 }
44}