diff options
author | Bernd Fix <brf@hoi-polloi.org> | 2022-02-02 15:14:12 +0100 |
---|---|---|
committer | Bernd Fix <brf@hoi-polloi.org> | 2022-02-02 15:14:12 +0100 |
commit | 205cad60026bf0af1cd2712a8faa4bce08eafb1d (patch) | |
tree | 9a2f361e5b2227b3e213fc5093d07641c18cedb4 /src | |
parent | d9dc142fe6d634066c8e33b48106cd6e5c588baf (diff) | |
download | gnunet-go-205cad60026bf0af1cd2712a8faa4bce08eafb1d.tar.gz gnunet-go-205cad60026bf0af1cd2712a8faa4bce08eafb1d.zip |
Refactored GNS zone crypto implementation.v0.1.23
Diffstat (limited to 'src')
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 @@ | |||
19 | package main | 19 | package main |
20 | 20 | ||
21 | import ( | 21 | import ( |
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 | ||
34 | func main() { | 38 | func 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 @@ | |||
19 | package main | 19 | package main |
20 | 20 | ||
21 | import ( | 21 | import ( |
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 | ||
34 | func main() { | 38 | func 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 | ||
35 | type 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 |
35 | type GNSConfig struct { | 43 | type 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) |
45 | type DHTConfig struct { | 53 | type 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 |
53 | type NamecacheConfig struct { | 61 | type 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 |
61 | type RevocationConfig struct { | 69 | type 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 |
69 | type Environ map[string]string | 77 | type Environment map[string]string |
70 | 78 | ||
71 | // Config is the aggregated configuration for GNUnet. | 79 | // Config is the aggregated configuration for GNUnet. |
72 | type Config struct { | 80 | type 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. | ||
86 | func ParseConfig(fileName string) (err error) { | 96 | func 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 @@ | |||
19 | package crypto | 19 | package crypto |
20 | 20 | ||
21 | import ( | 21 | import ( |
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 | //====================================================================== |
30 | func 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. |
48 | func 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 | ||
93 | type 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. | ||
102 | type 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. | ||
123 | type 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. | ||
138 | type ZoneSigImpl interface { | ||
139 | ZoneAbstractImpl | ||
140 | } | ||
141 | |||
142 | //---------------------------------------------------------------------- | ||
143 | // Zone types | ||
144 | //---------------------------------------------------------------------- | ||
145 | var ( | ||
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) | ||
156 | type 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 | ||
166 | var ( | ||
167 | zoneImpl = make(map[uint32]*ZoneImplementation) | ||
168 | ) | ||
169 | |||
170 | // Error codes | ||
171 | var ( | ||
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. | ||
177 | func 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,...) | ||
193 | type ZonePrivate struct { | ||
194 | ZoneKey | ||
195 | |||
196 | impl ZonePrivateImpl // reference to implementation | ||
197 | } | ||
198 | |||
199 | // NewZonePrivate returns a new initialized ZonePrivate instance | ||
200 | func 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). | ||
225 | func (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) | ||
233 | func (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 | ||
258 | func (zp *ZonePrivate) Sign(data []byte) (sig *ZoneSignature, err error) { | ||
259 | return zp.impl.Sign(data) | ||
260 | } | ||
261 | |||
262 | // Public returns the associated public key | ||
263 | func (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,...) | ||
272 | type 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 | ||
280 | func 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). | ||
298 | func (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) | ||
306 | func (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 | ||
318 | func (zk *ZoneKey) BlockKey(label string, expires util.AbsoluteTime) (skey []byte) { | ||
319 | return zk.impl.BlockKey(label, expires) | ||
320 | } | ||
321 | |||
322 | // Encrypt data | ||
323 | func (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 | ||
328 | func (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 | ||
333 | func (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. | ||
339 | func (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 | ||
347 | func (zk *ZoneKey) Bytes() []byte { | ||
348 | data, _ := data.Marshal(zk) | ||
349 | return data | ||
350 | } | ||
351 | |||
352 | // Equal checks if two zone keys are equal | ||
353 | func (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 | ||
358 | func (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 | |||
370 | type 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 | ||
378 | func 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). | ||
404 | func (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 | ||
412 | func (zs *ZoneSignature) Key() *ZoneKey { | ||
413 | return &zs.ZoneKey | ||
414 | } | ||
415 | |||
416 | // Verify a signature | ||
417 | func (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. | ||
426 | func 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 | |||
19 | package crypto | ||
20 | |||
21 | import ( | ||
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 | ||
42 | func 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. | ||
58 | type 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. | ||
65 | func (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()'. | ||
73 | func (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. | ||
79 | func (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 | ||
91 | func (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 | ||
105 | func (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 | ||
124 | func (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. | ||
134 | func (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. | ||
163 | type 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. | ||
171 | func (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()'. | ||
180 | func (pk *EDKEYPrivateImpl) Bytes() []byte { | ||
181 | return pk.prv.Bytes() | ||
182 | } | ||
183 | |||
184 | // Public returns the associate public key implementation. | ||
185 | func (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. | ||
191 | func (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 | ||
206 | func (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. | ||
230 | type 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. | ||
236 | func (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()'. | ||
243 | func (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 | |||
19 | package crypto | ||
20 | |||
21 | import ( | ||
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 | ||
42 | func 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. | ||
58 | type 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. | ||
65 | func (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()'. | ||
73 | func (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. | ||
79 | func (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 | ||
91 | func (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 | ||
96 | func (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 | ||
101 | func (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. | ||
111 | func (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). | ||
138 | func (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. | ||
158 | type 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. | ||
166 | func (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()'. | ||
176 | func (pk *PKEYPrivateImpl) Bytes() []byte { | ||
177 | return pk.prv.Bytes() | ||
178 | } | ||
179 | |||
180 | // Public returns the associate public key implementation. | ||
181 | func (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. | ||
187 | func (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 | ||
202 | func (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. | ||
226 | type 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. | ||
232 | func (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()'. | ||
239 | func (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 | ||
21 | import ( | 21 | import ( |
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 | |||
29 | var ( | ||
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 | ||
39 | func TestDeriveBlockKey(t *testing.T) { | 33 | func 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 | ||
86 | func TestDecryptBlock(t *testing.T) { | 74 | func 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 | |||
199 | func 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 | |||
299 | func 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 | |||
345 | func 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 | |||
19 | package crypto | ||
20 | |||
21 | import ( | ||
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 | ||
31 | var ( | ||
32 | ED25519_N = ed25519.GetCurve().N | ||
33 | ) | ||
34 | |||
35 | // DeriveH derives an integer 'h' from the arguments. | ||
36 | func 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. | ||
47 | func 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 | |||
19 | package crypto | ||
20 | |||
21 | import ( | ||
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 | |||
34 | func 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 | |||
129 | func 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 | |||
175 | func 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 | ||
62 | func calcSharedSecret() bool { | 64 | func 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 | ||
73 | func TestDHE(t *testing.T) { | 75 | func 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 | ||
96 | func TestDHERandom(t *testing.T) { | 97 | func 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 | |||
19 | package crypto | ||
20 | |||
21 | import ( | ||
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. | ||
34 | type 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. | ||
40 | func 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. | ||
52 | type 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. | ||
58 | func 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. | ||
69 | func 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. | ||
90 | func 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 @@ | |||
1 | module gnunet | 1 | module gnunet |
2 | 2 | ||
3 | go 1.12 | 3 | go 1.17 |
4 | 4 | ||
5 | require ( | 5 | require ( |
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 | |||
15 | require ( | ||
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 @@ | |||
1 | github.com/bfix/gospel v0.0.0-20190922182041-6fcd6d4fd449 h1:oIq3s14sMh1sq791v9VpR+GJvhVGbvuOWlfTjruRTDQ= | 1 | github.com/bfix/gospel v1.2.10 h1:a8l/sET2y+FVKIO5M1l5hdTlqLxstvkhp+b6FpAkxOU= |
2 | github.com/bfix/gospel v0.0.0-20190922182041-6fcd6d4fd449/go.mod h1:RQYETFV9SP+VriIsHVqCntRpSbbRvCBnNTtbUl9NAKA= | 2 | github.com/bfix/gospel v1.2.10/go.mod h1:cdu63bA9ZdfeDoqZ+vnWOcbY9Puwdzmf5DMxMGMznRI= |
3 | github.com/bfix/gospel v0.0.0-20200326093412-d1b2381f0c46 h1:5aNd1/ISbO1ltgmyUGza7kdaN4fD/Qal6uKZk9goMhw= | 3 | github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= |
4 | github.com/bfix/gospel v0.0.0-20200326093412-d1b2381f0c46/go.mod h1:RQYETFV9SP+VriIsHVqCntRpSbbRvCBnNTtbUl9NAKA= | 4 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= |
5 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | ||
6 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
7 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= | ||
8 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= | ||
9 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= | ||
10 | github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= | ||
11 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= | ||
12 | github.com/go-redis/redis/v8 v8.5.0 h1:L3r1Q3I5WOUdXZGCP6g44EruKh0u3n6co5Hl5xWkdGA= | ||
13 | github.com/go-redis/redis/v8 v8.5.0/go.mod h1:YmEcgBDttjnkbMzDAhDtQxY9yVA7jMN6PCR5HeMvqFE= | ||
14 | github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= | ||
15 | github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= | ||
16 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||
17 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= | ||
18 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= | ||
19 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= | ||
20 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= | ||
21 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= | ||
22 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | ||
23 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | ||
24 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | ||
25 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||
26 | github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= | ||
27 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||
28 | github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= | ||
29 | github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= | ||
30 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= | ||
31 | github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= | ||
32 | github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= | ||
33 | github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= | ||
34 | github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= | ||
5 | github.com/miekg/dns v1.1.26 h1:gPxPSwALAeHJSjarOs00QjVdV9QoBvc1D2ujQUr5BzU= | 35 | github.com/miekg/dns v1.1.26 h1:gPxPSwALAeHJSjarOs00QjVdV9QoBvc1D2ujQUr5BzU= |
6 | github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= | 36 | github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= |
37 | github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= | ||
38 | github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | ||
39 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||
40 | github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= | ||
41 | github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4= | ||
42 | github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= | ||
43 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= | ||
44 | github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= | ||
45 | github.com/onsi/gomega v1.10.5 h1:7n6FEkpFmfCoo2t+YYqXH0evK+a9ICQz0xcAy9dYcaQ= | ||
46 | github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= | ||
47 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
48 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
49 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
50 | github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= | ||
51 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
52 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||
53 | go.opentelemetry.io/otel v0.16.0 h1:uIWEbdeb4vpKPGITLsRVUS44L5oDbDUCZxn8lkxhmgw= | ||
54 | go.opentelemetry.io/otel v0.16.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA= | ||
7 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | 55 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= |
8 | golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM= | ||
9 | golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||
10 | golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M= | ||
11 | golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= | 56 | golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= |
12 | golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= | 57 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= |
13 | golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | 58 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= |
59 | golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= | ||
60 | golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed h1:YoWVYYAfvQ4ddHv3OKmIvX7NCAhFGTj62VP2l2kfBbA= | ||
61 | golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= | ||
62 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||
63 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||
64 | golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||
14 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | 65 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= |
15 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | 66 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= |
16 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= | ||
17 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | 67 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= |
18 | golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= | 68 | golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= |
69 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | ||
70 | golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | ||
71 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= | ||
72 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||
73 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
19 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | 74 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
75 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= | ||
76 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
77 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
20 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | 78 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
21 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | 79 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
80 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
22 | golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | 81 | golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
23 | golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M= | ||
24 | golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | 82 | golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
83 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
84 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
85 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
86 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
87 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
88 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
89 | golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
90 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
91 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= | ||
92 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
93 | golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= | ||
94 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||
25 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | 95 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= |
26 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= | ||
27 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | 96 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= |
97 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
98 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
99 | golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= | ||
100 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
28 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | 101 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
29 | golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | 102 | golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= |
103 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||
104 | golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | ||
30 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | 105 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
106 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
107 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
108 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
109 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= | ||
110 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= | ||
111 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= | ||
112 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= | ||
113 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= | ||
114 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | ||
115 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
116 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | ||
117 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= | ||
118 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= | ||
119 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||
120 | gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= | ||
121 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||
122 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | ||
123 | gopkg.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 @@ | |||
19 | package message | 19 | package message |
20 | 20 | ||
21 | import ( | 21 | import ( |
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. |
33 | type Message interface { | 33 | type 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). |
39 | type MessageHeader struct { | 39 | type 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) |
45 | func (mh *MessageHeader) Size() uint16 { | 45 | func (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) |
50 | func (mh *MessageHeader) Type() uint16 { | 50 | func (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). |
56 | func GetMsgHeader(b []byte) (mh *MessageHeader, err error) { | 56 | func 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. |
83 | func (msg *EphemeralKeyMsg) Header() *MessageHeader { | 83 | func (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. |
108 | func NewEphemeralKey(peerId []byte, ltPrv *ed25519.PrivateKey) (*ed25519.PrivateKey, *EphemeralKeyMsg, error) { | 108 | func 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 |
35 | type DHTClientGetMsg struct { | 35 | type 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. |
64 | func (m *DHTClientGetMsg) SetXQuery(xq []byte) []byte { | 64 | func (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. |
73 | func (m *DHTClientGetMsg) String() string { | 73 | func (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. |
79 | func (msg *DHTClientGetMsg) Header() *MessageHeader { | 79 | func (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 |
88 | type DHTClientResultMsg struct { | 88 | type 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. |
121 | func (m *DHTClientResultMsg) String() string { | 121 | func (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. |
126 | func (msg *DHTClientResultMsg) Header() *MessageHeader { | 126 | func (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 |
135 | type DHTClientGetStopMsg struct { | 135 | type 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. |
158 | func (m *DHTClientGetStopMsg) String() string { | 158 | func (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. |
163 | func (msg *DHTClientGetStopMsg) Header() *MessageHeader { | 163 | func (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 | ||
33 | var ( | 33 | var ( |
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 |
42 | type GNSLookupMsg struct { | 42 | type 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. |
54 | func NewGNSLookupMsg() *GNSLookupMsg { | 54 | func 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 |
68 | func (m *GNSLookupMsg) SetName(name string) { | 68 | func (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 |
74 | func (m *GNSLookupMsg) GetName() string { | 74 | func (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. |
85 | func (m *GNSLookupMsg) String() string { | 85 | func (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. |
93 | func (msg *GNSLookupMsg) Header() *MessageHeader { | 92 | func (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. |
104 | type GNSRecordSet struct { | 103 | type 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. |
111 | func NewGNSRecordSet() *GNSRecordSet { | 110 | func 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. |
120 | func (rs *GNSRecordSet) AddRecord(rec *GNSResourceRecord) { | 119 | func (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 | 125 | func (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. | ||
138 | func (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 | ||
127 | type SignedBlockData struct { | 152 | type 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. |
139 | type GNSBlock struct { | 164 | type 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 |
151 | func (b *GNSBlock) String() string { | 175 | func (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. |
157 | func (b *GNSBlock) Records() ([]*GNSResourceRecord, error) { | 181 | func (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. |
171 | func (b *GNSBlock) Verify(zoneKey *ed25519.PublicKey, label string) (err error) { | 195 | func (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. |
201 | func (b *GNSBlock) Decrypt(zoneKey *ed25519.PublicKey, label string) (err error) { | 215 | func (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 |
209 | func NewGNSBlock() *GNSBlock { | 223 | func 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). |
227 | type GNSResourceRecord struct { | 240 | type 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. |
236 | func (r *GNSResourceRecord) String() string { | 249 | func (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 |
242 | type GNSLookupResultMsg struct { | 255 | type 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 |
251 | func NewGNSLookupResultMsg(id uint32) *GNSLookupResultMsg { | 264 | func 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. |
262 | func (m *GNSLookupResultMsg) AddRecord(rec *GNSResourceRecord) error { | 275 | func (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. |
274 | func (m *GNSLookupResultMsg) String() string { | 287 | func (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. |
279 | func (msg *GNSLookupResultMsg) Header() *MessageHeader { | 292 | func (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 | |||
19 | package message | ||
20 | |||
21 | import ( | ||
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") | ||
34 | func 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") | ||
194 | func 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 |
34 | type NamecacheLookupMsg struct { | 34 | type 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. |
55 | func (m *NamecacheLookupMsg) String() string { | 55 | func (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. |
61 | func (msg *NamecacheLookupMsg) Header() *MessageHeader { | 61 | func (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. |
70 | type NamecacheLookupResultMsg struct { | 70 | type 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. |
81 | func NewNamecacheLookupResultMsg() *NamecacheLookupResultMsg { | 80 | func 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. |
94 | func (m *NamecacheLookupResultMsg) String() string { | 92 | func (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. |
100 | func (msg *NamecacheLookupResultMsg) Header() *MessageHeader { | 98 | func (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. |
109 | type NamecacheCacheMsg struct { | 107 | type 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. |
120 | func NewNamecacheCacheMsg(block *GNSBlock) *NamecacheCacheMsg { | 117 | func 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. |
143 | func (m *NamecacheCacheMsg) String() string { | 138 | func (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. |
149 | func (msg *NamecacheCacheMsg) Header() *MessageHeader { | 144 | func (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 |
158 | type NamecacheCacheResponseMsg struct { | 153 | type 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. |
176 | func (m *NamecacheCacheResponseMsg) String() string { | 171 | func (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. |
182 | func (msg *NamecacheCacheResponseMsg) Header() *MessageHeader { | 177 | func (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 | |||
21 | import ( | 21 | import ( |
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 |
34 | type RevocationQueryMsg struct { | 33 | type 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. |
42 | func NewRevocationQueryMsg(zone *ed25519.PublicKey) *RevocationQueryMsg { | 41 | func 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. |
56 | func (m *RevocationQueryMsg) String() string { | 51 | func (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. |
61 | func (msg *RevocationQueryMsg) Header() *MessageHeader { | 56 | func (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. |
70 | type RevocationQueryResponseMsg struct { | 65 | type 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. |
95 | func (msg *RevocationQueryResponseMsg) Header() *MessageHeader { | 90 | func (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 |
104 | type RevocationRevokeMsg struct { | 99 | type 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. |
115 | func NewRevocationRevokeMsg(zoneKey *ed25519.PublicKey, sig *ed25519.EcSignature) *RevocationRevokeMsg { | 109 | func 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. |
135 | func (m *RevocationRevokeMsg) String() string { | 121 | func (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. |
140 | func (msg *RevocationRevokeMsg) Header() *MessageHeader { | 126 | func (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 |
149 | type RevocationRevokeResponseMsg struct { | 135 | type 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. |
174 | func (msg *RevocationRevokeResponseMsg) Header() *MessageHeader { | 160 | func (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. |
38 | type TransportTcpWelcomeMsg struct { | 38 | type 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. |
45 | func NewTransportTcpWelcomeMsg(peerid *util.PeerID) *TransportTcpWelcomeMsg { | 45 | func 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. |
57 | func (m *TransportTcpWelcomeMsg) String() string { | 57 | func (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. |
62 | func (msg *TransportTcpWelcomeMsg) Header() *MessageHeader { | 62 | func (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 |
76 | type TransportPingMsg struct { | 76 | type 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. |
86 | func NewTransportPingMsg(target *util.PeerID, a *util.Address) *TransportPingMsg { | 86 | func 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. |
115 | func (msg *TransportPingMsg) Header() *MessageHeader { | 115 | func (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 |
159 | type TransportPongMsg struct { | 159 | type 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. |
196 | func (msg *TransportPongMsg) Header() *MessageHeader { | 196 | func (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 |
242 | type HelloAddress struct { | 242 | type 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 |
250 | func NewAddress(a *util.Address) *HelloAddress { | 250 | func 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 |
268 | type HelloMsg struct { | 268 | type 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. |
303 | func (msg *HelloMsg) Header() *MessageHeader { | 303 | func (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 |
312 | type SessionAckMsg struct { | 312 | type 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. |
331 | func (msg *SessionAckMsg) Header() *MessageHeader { | 331 | func (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 |
340 | type SessionSynMsg struct { | 340 | type 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. |
363 | func (msg *SessionSynMsg) Header() *MessageHeader { | 363 | func (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 |
372 | type SessionSynAckMsg struct { | 372 | type 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. |
395 | func (msg *SessionSynAckMsg) Header() *MessageHeader { | 395 | func (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 |
404 | type SessionQuotaMsg struct { | 404 | type 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. |
427 | func (msg *SessionQuotaMsg) Header() *MessageHeader { | 427 | func (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. |
436 | type SessionKeepAliveMsg struct { | 436 | type 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. |
458 | func (msg *SessionKeepAliveMsg) Header() *MessageHeader { | 458 | func (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. |
467 | type SessionKeepAliveRespMsg struct { | 467 | type 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. |
489 | func (msg *SessionKeepAliveRespMsg) Header() *MessageHeader { | 489 | func (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 |
39 | type Instances struct { | 40 | type 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 | ||
48 | func (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 | |||
19 | package rpc | ||
20 | |||
21 | import ( | ||
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 | ||
33 | var Router = mux.NewRouter() | ||
34 | var srv *http.Server | ||
35 | |||
36 | // Start the JSON-RPC server. It can be terminated by context | ||
37 | func 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 | ||
63 | func 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. |
64 | func ServiceRequestResponse( | 64 | func 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. |
32 | type SessionContext struct { | 32 | type 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. |
42 | func NewSessionContext() *SessionContext { | 42 | func 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. |
36 | type DHTModule struct { | 36 | type Module struct { |
37 | } | 37 | } |
38 | 38 | ||
39 | func (nc *DHTModule) Get(ctx *service.SessionContext, query *gns.Query) (*message.GNSBlock, error) { | 39 | // Get a GNS block from the DHT |
40 | func (nc *Module) Get(ctx *service.SessionContext, query *gns.Query) (*message.Block, error) { | ||
40 | return nil, nil | 41 | return nil, nil |
41 | } | 42 | } |
42 | 43 | ||
43 | func (nc *DHTModule) Put(ctx *service.SessionContext, block *message.GNSBlock) error { | 44 | // Put a GNS block into the DHT |
45 | func (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. |
34 | type HdlrInst func(*message.GNSResourceRecord, []string) (BlockHandler, error) | 34 | type HdlrInst func(*message.ResourceRecord, []string) (BlockHandler, error) |
35 | 35 | ||
36 | // Error codes | 36 | // Error codes |
37 | var ( | 37 | var ( |
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 |
48 | var ( | 48 | var ( |
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). |
110 | func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string) (*BlockHandlerList, []*message.GNSResourceRecord, error) { | 111 | func 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. |
196 | func (hl *BlockHandlerList) GetHandler(t int) BlockHandler { | 197 | func (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 |
205 | func (hl *BlockHandlerList) FinalizeRecord(rec *message.GNSResourceRecord) *message.GNSResourceRecord { | 208 | func (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 |
215 | type PkeyHandler struct { | 218 | type 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 |
221 | func NewPkeyHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) { | 225 | func 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. |
235 | func (h *PkeyHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error { | 243 | func (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) |
255 | func (h *PkeyHandler) Coexist(cm util.CounterMap) bool { | 263 | func (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 |
261 | func (h *PkeyHandler) Records(kind RRTypeList) *message.GNSRecordSet { | 269 | func (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. |
270 | func (h *PkeyHandler) Name() string { | 278 | func (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 |
279 | type Gns2DnsHandler struct { | 287 | type 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 |
286 | func NewGns2DnsHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) { | 294 | func 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. |
302 | func (h *Gns2DnsHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error { | 310 | func (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 |
336 | func (h *Gns2DnsHandler) Records(kind RRTypeList) *message.GNSRecordSet { | 344 | func (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 |
361 | func NewBoxHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) { | 369 | func 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. |
375 | func (h *BoxHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error { | 383 | func (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 |
406 | func (h *BoxHandler) Records(kind RRTypeList) *message.GNSRecordSet { | 414 | func (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 |
433 | type LehoHandler struct { | 441 | type 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 |
439 | func NewLehoHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) { | 447 | func 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. |
453 | func (h *LehoHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error { | 461 | func (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 |
470 | func (h *LehoHandler) Records(kind RRTypeList) *message.GNSRecordSet { | 478 | func (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 |
488 | type CnameHandler struct { | 496 | type 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 |
494 | func NewCnameHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) { | 502 | func 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. |
508 | func (h *CnameHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error { | 516 | func (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 |
528 | func (h *CnameHandler) Records(kind RRTypeList) *message.GNSRecordSet { | 536 | func (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 |
546 | type VpnHandler struct { | 554 | type 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 |
551 | func NewVpnHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) { | 559 | func 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. |
563 | func (h *VpnHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error { | 571 | func (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 |
582 | func (h *VpnHandler) Records(kind RRTypeList) *message.GNSRecordSet { | 590 | func (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. |
45 | func NewBox(rec *message.GNSResourceRecord) *Box { | 45 | func 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 |
38 | var ( | 38 | var ( |
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. |
49 | type RRTypeList []int | 49 | type 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 |
52 | func NewRRTypeList(args ...int) (res RRTypeList) { | 52 | func 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 | ||
118 | func 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. |
119 | func 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. |
206 | func (gns *GNSModule) ResolveDNS( | 207 | func (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 | ||
21 | import ( | 21 | import ( |
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 |
42 | var ( | 42 | var ( |
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. |
53 | type Query struct { | 53 | type 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. |
61 | func NewQuery(pkey *ed25519.PublicKey, label string) *Query { | 61 | func 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. |
113 | type GNSModule struct { | 114 | type 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 | ||
124 | func (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". |
124 | func (gns *GNSModule) Resolve( | 132 | func (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 |
150 | func (gns *GNSModule) ResolveAbsolute( | 158 | // (with multiple labels). |
159 | func (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 |
176 | func (gns *GNSModule) ResolveRelative( | 185 | // GNS record types |
186 | func (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. |
351 | func (gns *GNSModule) ResolveUnknown( | 363 | func (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. |
387 | func (gns *GNSModule) GetZoneKey(path string) *ed25519.PublicKey { | 399 | func (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. |
400 | func (gns *GNSModule) Lookup( | 412 | func (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. |
436 | func (gns *GNSModule) newLEHORecord(name string, expires util.AbsoluteTime) *message.GNSResourceRecord { | 448 | func (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 |
41 | var ( | 40 | var ( |
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 |
52 | type GNSService struct { | 51 | type Service struct { |
53 | GNSModule | 52 | Module |
54 | } | 53 | } |
55 | 54 | ||
56 | // NewGNSService | 55 | // NewService creates a new GNS service instance |
57 | func NewGNSService() service.Service { | 56 | func 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 |
69 | func (s *GNSService) Start(spec string) error { | 68 | func (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 |
74 | func (s *GNSService) Stop() error { | 73 | func (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. |
79 | func (s *GNSService) ServeClient(ctx *service.SessionContext, mc *transport.MsgChannel) { | 78 | func (s *Service) ServeClient(ctx *service.SessionContext, mc *transport.MsgChannel) { |
80 | 79 | reqID := 0 | |
81 | reqId := 0 | ||
82 | loop: | 80 | loop: |
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 |
176 | func (s *GNSService) QueryKeyRevocation(ctx *service.SessionContext, pkey *ed25519.PublicKey) (valid bool, err error) { | 175 | func (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 |
199 | func (s *GNSService) RevokeKey(ctx *service.SessionContext, rd *revocation.RevData) (success bool, err error) { | 198 | func (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) |
228 | func (s *GNSService) LookupNamecache(ctx *service.SessionContext, query *Query) (block *message.GNSBlock, err error) { | 228 | func (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. |
291 | func (s *GNSService) StoreNamecache(ctx *service.SessionContext, block *message.GNSBlock) (err error) { | 290 | func (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. |
329 | func (s *GNSService) LookupDHT(ctx *service.SessionContext, query *Query) (block *message.GNSBlock, err error) { | 330 | func (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 ( | |||
36 | type NamecacheModule struct { | 36 | type NamecacheModule struct { |
37 | } | 37 | } |
38 | 38 | ||
39 | func (nc *NamecacheModule) Get(ctx *service.SessionContext, query *gns.Query) (*message.GNSBlock, error) { | 39 | func (nc *NamecacheModule) Get(ctx *service.SessionContext, query *gns.Query) (*message.Block, error) { |
40 | return nil, nil | 40 | return nil, nil |
41 | } | 41 | } |
42 | 42 | ||
43 | func (nc *NamecacheModule) Put(ctx *service.SessionContext, block *message.GNSBlock) error { | 43 | func (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 | ||
21 | import ( | 21 | import ( |
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. |
36 | type RevocationModule struct { | 37 | type 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 |
42 | func (m *RevocationModule) Init() error { | 43 | func (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 |
65 | func NewRevocationModule() *RevocationModule { | 66 | func 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 | ||
76 | func (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. |
76 | func (s *RevocationModule) Query(ctx *service.SessionContext, pkey *ed25519.PublicKey) (valid bool, err error) { | 84 | func (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 |
95 | func (s *RevocationModule) Revoke(ctx *service.SessionContext, rd *RevData) (success bool, err error) { | 103 | func (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 |
45 | type PoWData struct { | 44 | type 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. |
55 | func NewPoWData(pow uint64, ts util.AbsoluteTime, zoneKey []byte) *PoWData { | 54 | func 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) |
121 | type RevData struct { | 120 | type 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. |
130 | type SignedRevData struct { | 128 | type 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 |
137 | func NewRevDataFromMsg(m *message.RevocationRevokeMsg) *RevData { | 135 | func 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 |
150 | func (rd *RevData) Sign(skey *ed25519.PrivateKey) error { | 147 | func (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 |
243 | func NewRevDataCalc(pkey []byte) *RevDataCalc { | 230 | func 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'. |
295 | func (rdc *RevDataCalc) Compute(ctx context.Context, bits int, last uint64, cb func(float64, uint64)) (float64, uint64) { | 280 | func (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 | |||
3 | import ( | 3 | import ( |
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 | ||
16 | type testData struct { | 13 | // Test revocation with test vector defined in the RFC draft. |
17 | skey string | 14 | func TestRevocationRFC(t *testing.T) { |
18 | pkey string | ||
19 | revdata string | ||
20 | } | ||
21 | 15 | ||
22 | var ( | 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 | ||
70 | func 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 |
37 | type RevocationService struct { | 36 | type Service struct { |
38 | RevocationModule | 37 | Module |
39 | } | 38 | } |
40 | 39 | ||
41 | // NewRevocationService | 40 | // NewService creates a new revocation service instance |
42 | func NewRevocationService() service.Service { | 41 | func 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 |
49 | func (s *RevocationService) Start(spec string) error { | 48 | func (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 |
54 | func (s *RevocationService) Stop() error { | 53 | func (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. |
59 | func (s *RevocationService) ServeClient(ctx *service.SessionContext, mc *transport.MsgChannel) { | 58 | func (s *Service) ServeClient(ctx *service.SessionContext, mc *transport.MsgChannel) { |
60 | 59 | reqID := 0 | |
61 | reqId := 0 | ||
62 | loop: | 60 | loop: |
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 | ||
21 | import ( | 21 | import ( |
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). | ||
32 | type 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. |
34 | type Service interface { | 41 | type 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. |
41 | type ServiceImpl struct { | 52 | type 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. |
54 | func NewServiceImpl(name string, srv Service) *ServiceImpl { | 65 | func 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 |
69 | func (si *ServiceImpl) Start(spec string) (err error) { | 80 | func (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 |
140 | func (si *ServiceImpl) Stop() error { | 151 | func (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 |
37 | var ( | 37 | var ( |
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 |
106 | func NewChannelServer(spec string, hdlr chan<- Channel) (cs ChannelServer, err error) { | 106 | func 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). |
47 | func (cr *ChannelResult) Values() (int, error) { | 47 | func (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 |
55 | type NetworkChannel struct { | 55 | type 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 |
171 | type NetworkChannelServer struct { | 171 | type 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 |
177 | func NewNetworkChannelServer(netw string) ChannelServer { | 177 | func 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 |
258 | func NewSocketChannel() Channel { | 258 | func NewSocketChannel() Channel { |
259 | return NewNetworkChannel("unix") | 259 | return NewNetworkChannel("unix") |
260 | } | 260 | } |
261 | 261 | ||
262 | // NewTCPChannel: TCP connection | 262 | // NewTCPChannel implements a: TCP connection |
263 | func NewTCPChannel() Channel { | 263 | func NewTCPChannel() Channel { |
264 | return NewNetworkChannel("tcp") | 264 | return NewNetworkChannel("tcp") |
265 | } | 265 | } |
266 | 266 | ||
267 | // NewUDPChannel: UDP connection | 267 | // NewUDPChannel implements an UDP connection |
268 | func NewUDPChannel() Channel { | 268 | func 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 |
273 | func NewSocketChannelServer() ChannelServer { | 273 | func NewSocketChannelServer() ChannelServer { |
274 | return NewNetworkChannelServer("unix") | 274 | return NewNetworkChannelServer("unix") |
275 | } | 275 | } |
276 | 276 | ||
277 | // NewTCPChannelServer: TCP listener | 277 | // NewTCPChannelServer implements a TCP listener |
278 | func NewTCPChannelServer() ChannelServer { | 278 | func NewTCPChannelServer() ChannelServer { |
279 | return NewNetworkChannelServer("tcp") | 279 | return NewNetworkChannelServer("tcp") |
280 | } | 280 | } |
281 | 281 | ||
282 | // NewUDPChannelServer: UDP listener | 282 | // NewUDPChannelServer implements an UDP listener |
283 | func NewUDPChannelServer() ChannelServer { | 283 | func 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 | |||
28 | const ( | 33 | const ( |
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 | ||
34 | type TestChannelServer struct { | 39 | type TestChannelServer struct { |
@@ -45,14 +50,14 @@ func NewTestChannelServer() *TestChannelServer { | |||
45 | } | 50 | } |
46 | } | 51 | } |
47 | 52 | ||
48 | func (s *TestChannelServer) handle(ch Channel) { | 53 | func (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() { | |||
99 | func TestChannelServerTCPSingle(t *testing.T) { | 103 | func 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 | ||
108 | func TestChannelServerTCPTwice(t *testing.T) { | 113 | func 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 | ||
121 | func TestChannelClientTCP(t *testing.T) { | 130 | func 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 | ||
149 | func TestChannelClientServerTCP(t *testing.T) { | 158 | func 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 | ||
186 | func TestChannelClientServerSock(t *testing.T) { | 196 | func 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 ( | |||
29 | type Connection struct { | 29 | type 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 |
22 | const ( | 22 | const ( |
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) |
65 | type IPAddress struct { | 65 | type 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 |
91 | func ReverseStringList(s []string) []string { | 91 | func 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. |
103 | func StringList(b []byte) []string { | 103 | func 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 |
32 | var ( | 32 | var ( |
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&...]"). |
49 | func ConnectSqlDatabase(spec string) (db *sql.DB, err error) { | 49 | func 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) | ||
26 | func NextID() int { | 27 | func 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 |
115 | type KvsRedis struct { | 115 | type 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 |
131 | func (kvs *KvsRedis) List() (keys []string, err error) { | 131 | func (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 |
155 | type KvsSql struct { | 155 | type 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 |
160 | func (kvs *KvsSql) Put(key string, value string) error { | 160 | func (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 |
166 | func (kvs *KvsSql) Get(key string) (value string, err error) { | 166 | func (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 |
173 | func (kvs *KvsSql) List() (keys []string, err error) { | 173 | func (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 |
26 | type CounterMap map[interface{}]int | 26 | type CounterMap map[interface{}]int |
27 | 27 | ||
28 | // Add one to themetric for a given key and return current value | ||
28 | func (cm CounterMap) Add(i interface{}) int { | 29 | func (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 | ||
39 | func (cm CounterMap) Num(i interface{}) int { | 41 | func (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. | ||
47 | func StripPathRight(s string) string { | 51 | func 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... |
118 | type RelativeTime struct { | 118 | type 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 | |||
19 | package util | ||
20 | |||
21 | import ( | ||
22 | "testing" | ||
23 | "time" | ||
24 | ) | ||
25 | |||
26 | func 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 | } | ||