aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBernd Fix <brf@hoi-polloi.org>2019-09-18 17:39:29 +0200
committerBernd Fix <brf@hoi-polloi.org>2019-09-18 17:39:29 +0200
commita048e9c08195a3ed11e7f864e270d372668b129e (patch)
treee64bdf4bd0675d0ad8a5cf58f5d6891f62bbb1d9 /src
downloadgnunet-go-a048e9c08195a3ed11e7f864e270d372668b129e.tar.gz
gnunet-go-a048e9c08195a3ed11e7f864e270d372668b129e.zip
Initial revision.
Diffstat (limited to 'src')
-rw-r--r--src/cmd/.gitignore1
-rw-r--r--src/cmd/gnunet-service-gns-go/main.go83
-rw-r--r--src/cmd/peer_mockup/main.go68
-rw-r--r--src/cmd/peer_mockup/peers.go46
-rw-r--r--src/cmd/peer_mockup/process.go118
-rw-r--r--src/cmd/vanityid/main.go46
-rw-r--r--src/gnunet/config/config.go141
-rw-r--r--src/gnunet/config/config_test.go22
-rw-r--r--src/gnunet/config/gnunet-config.json16
-rw-r--r--src/gnunet/core/peer.go93
-rw-r--r--src/gnunet/crypto/hash.go24
-rw-r--r--src/gnunet/crypto/key_derivation.go31
-rw-r--r--src/gnunet/crypto/key_derivation_test.go215
-rw-r--r--src/gnunet/crypto/key_exchange.go12
-rw-r--r--src/gnunet/crypto/key_exchange_test.go104
-rw-r--r--src/gnunet/crypto/keys_test.go69
-rw-r--r--src/gnunet/crypto/signature.go6
-rw-r--r--src/gnunet/crypto/symmetric.go59
-rw-r--r--src/gnunet/enums/block.go22
-rw-r--r--src/gnunet/enums/dht.go12
-rw-r--r--src/gnunet/enums/gns.go287
-rw-r--r--src/gnunet/enums/signature.go34
-rw-r--r--src/gnunet/go.mod5
-rw-r--r--src/gnunet/go.sum10
-rw-r--r--src/gnunet/message/const.go37
-rw-r--r--src/gnunet/message/factory.go64
-rw-r--r--src/gnunet/message/message.go37
-rw-r--r--src/gnunet/message/msg_core.go95
-rw-r--r--src/gnunet/message/msg_dht.go106
-rw-r--r--src/gnunet/message/msg_gns.go128
-rw-r--r--src/gnunet/message/msg_namecache.go86
-rw-r--r--src/gnunet/message/msg_transport.go440
-rw-r--r--src/gnunet/message/types.go817
-rw-r--r--src/gnunet/service/client.go59
-rw-r--r--src/gnunet/service/gns/crypto.go41
-rw-r--r--src/gnunet/service/gns/crypto_test.go150
-rw-r--r--src/gnunet/service/gns/gns.go248
-rw-r--r--src/gnunet/service/gns/record.go111
-rw-r--r--src/gnunet/service/service.go91
-rw-r--r--src/gnunet/transport/channel.go180
-rw-r--r--src/gnunet/transport/channel_netw.go173
-rw-r--r--src/gnunet/transport/channel_test.go203
-rw-r--r--src/gnunet/transport/connection.go52
-rw-r--r--src/gnunet/transport/session.go12
-rw-r--r--src/gnunet/util/address.go39
-rw-r--r--src/gnunet/util/array.go48
-rw-r--r--src/gnunet/util/base32.go109
-rw-r--r--src/gnunet/util/base32_test.go86
-rw-r--r--src/gnunet/util/format.go36
-rw-r--r--src/gnunet/util/id.go10
-rw-r--r--src/gnunet/util/msg_queue.go3
-rw-r--r--src/gnunet/util/rnd.go46
-rw-r--r--src/gnunet/util/time.go19
53 files changed, 5050 insertions, 0 deletions
diff --git a/src/cmd/.gitignore b/src/cmd/.gitignore
new file mode 100644
index 0000000..1933786
--- /dev/null
+++ b/src/cmd/.gitignore
@@ -0,0 +1 @@
/test/
diff --git a/src/cmd/gnunet-service-gns-go/main.go b/src/cmd/gnunet-service-gns-go/main.go
new file mode 100644
index 0000000..ccfb5d3
--- /dev/null
+++ b/src/cmd/gnunet-service-gns-go/main.go
@@ -0,0 +1,83 @@
1package main
2
3import (
4 "flag"
5 "os"
6 "os/signal"
7 "syscall"
8 "time"
9
10 "github.com/bfix/gospel/logger"
11 "gnunet/config"
12 "gnunet/service"
13 "gnunet/service/gns"
14)
15
16func main() {
17 logger.Println(logger.INFO, "[gns] Starting service...")
18 var (
19 cfgFile string
20 srvEndp string
21 err error
22 logLevel int
23 )
24 // handle command line arguments
25 flag.StringVar(&cfgFile, "c", "gnunet-config.json", "GNUnet configuration file")
26 flag.StringVar(&srvEndp, "s", "", "GNS service end-point")
27 flag.IntVar(&logLevel, "L", logger.INFO, "GNS log level (default: INFO)")
28 flag.Parse()
29
30 // read configuration file and set missing arguments.
31 if err = config.ParseConfig(cfgFile); err != nil {
32 logger.Printf(logger.ERROR, "[gns] Invalid configuration file: %s\n", err.Error())
33 return
34 }
35
36 // apply configuration
37 logger.SetLogLevel(logLevel)
38 if len(srvEndp) == 0 {
39 srvEndp = config.Cfg.GNS.Endpoint
40 }
41
42 // start a new GNS service
43 gns := gns.NewGNSService()
44 srv := service.NewServiceImpl("gns", gns)
45 if err = srv.Start(srvEndp); err != nil {
46 logger.Printf(logger.ERROR, "[gns] Error: '%s'\n", err.Error())
47 return
48 }
49
50 // handle OS signals
51 sigCh := make(chan os.Signal, 5)
52 signal.Notify(sigCh)
53
54 // heart beat
55 tick := time.NewTicker(5 * time.Minute)
56
57loop:
58 for {
59 select {
60 // handle OS signals
61 case sig := <-sigCh:
62 switch sig {
63 case syscall.SIGKILL:
64 case syscall.SIGINT:
65 case syscall.SIGTERM:
66 logger.Println(logger.INFO, "[gns] Terminating service (on signal)")
67 break loop
68 case syscall.SIGHUP:
69 logger.Println(logger.INFO, "[gns] SIGHUP")
70 default:
71 logger.Println(logger.INFO, "[gns] Unhandled signal: "+sig.String())
72 }
73 // handle heart beat
74 case now := <-tick.C:
75 logger.Println(logger.INFO, "[gns] Heart beat at "+now.String())
76 }
77 }
78
79 // terminating service
80 srv.Stop()
81 // wait for logger to flush last messages
82 time.Sleep(5 * time.Second)
83}
diff --git a/src/cmd/peer_mockup/main.go b/src/cmd/peer_mockup/main.go
new file mode 100644
index 0000000..59bc002
--- /dev/null
+++ b/src/cmd/peer_mockup/main.go
@@ -0,0 +1,68 @@
1package main
2
3import (
4 "encoding/hex"
5 "flag"
6 "fmt"
7
8 "github.com/bfix/gospel/logger"
9 "gnunet/core"
10 "gnunet/transport"
11)
12
13var (
14 p *core.Peer // local peer (with private key)
15 t *core.Peer // remote peer
16)
17
18func main() {
19 // handle command line arguments
20 var (
21 asServer bool
22 err error
23 ch transport.Channel
24 )
25 flag.BoolVar(&asServer, "s", false, "accept incoming connections")
26 flag.Parse()
27
28 // setup peer instances from static data
29 if err = setupPeers(false); err != nil {
30 fmt.Println(err.Error())
31 return
32 }
33
34 fmt.Println("======================================================================")
35 fmt.Println("GNUnet peer mock-up (EXPERIMENTAL) (c) 2018,2019 by Bernd Fix, >Y<")
36 fmt.Printf(" Identity '%s'\n", p.GetIDString())
37 fmt.Printf(" [%s]\n", hex.EncodeToString(p.GetID()))
38 fmt.Println("======================================================================")
39
40 if asServer {
41 // run as server
42 fmt.Println("Waiting for connections...")
43 hdlr := make(chan transport.Channel)
44 go func() {
45 for {
46 select {
47 case ch = <-hdlr:
48 mc := transport.NewMsgChannel(ch)
49 if err = process(mc, t, p); err != nil {
50 logger.Println(logger.ERROR, err.Error())
51 }
52 }
53 }
54 }()
55 _, err = transport.NewChannelServer("tcp+0.0.0.0:2086", hdlr)
56 } else {
57 // connect to peer
58 fmt.Println("Connecting to target peer")
59 if ch, err = transport.NewChannel("tcp+172.17.0.5:2086"); err != nil {
60 logger.Println(logger.ERROR, err.Error())
61 }
62 mc := transport.NewMsgChannel(ch)
63 err = process(mc, p, t)
64 }
65 if err != nil {
66 fmt.Println(err)
67 }
68}
diff --git a/src/cmd/peer_mockup/peers.go b/src/cmd/peer_mockup/peers.go
new file mode 100644
index 0000000..16d3c87
--- /dev/null
+++ b/src/cmd/peer_mockup/peers.go
@@ -0,0 +1,46 @@
1package main
2
3import (
4 "github.com/bfix/gospel/data"
5 "gnunet/core"
6 "gnunet/util"
7)
8
9func setupPeers(rnd bool) (err error) {
10
11 //------------------------------------------------------------------
12 // create local peer
13 //------------------------------------------------------------------
14 secret := []byte{
15 0x78, 0xde, 0xcf, 0xc0, 0x26, 0x9e, 0x62, 0x3d,
16 0x17, 0x24, 0xe6, 0x1b, 0x98, 0x25, 0xec, 0x2f,
17 0x40, 0x6b, 0x1e, 0x39, 0xa5, 0x19, 0xac, 0x9b,
18 0xb2, 0xdd, 0xf4, 0x6c, 0x12, 0x83, 0xdb, 0x86,
19 }
20 if rnd {
21 util.RndArray(secret)
22 }
23 p, err = core.NewPeer(secret, true)
24 if err != nil {
25 return
26 }
27 addr, _ := data.Marshal(util.NewIPAddress([]byte{172, 17, 0, 6}, 2086))
28 p.AddAddress(util.NewAddress("tcp", addr))
29
30 //------------------------------------------------------------------
31 // create remote peer
32 //------------------------------------------------------------------
33 id := []byte{
34 0x92, 0xdc, 0xbf, 0x39, 0x40, 0x2d, 0xc6, 0x3c,
35 0x97, 0xa6, 0x81, 0xe0, 0xfc, 0xd8, 0x7c, 0x74,
36 0x17, 0xd3, 0xa3, 0x8c, 0x52, 0xfd, 0xe0, 0x49,
37 0xbc, 0xd0, 0x1c, 0x0a, 0x0b, 0x8c, 0x02, 0x51,
38 }
39 t, err = core.NewPeer(id, false)
40 if err != nil {
41 return
42 }
43 addr, _ = data.Marshal(util.NewIPAddress([]byte{172, 17, 0, 5}, 2086))
44 t.AddAddress(util.NewAddress("tcp", addr))
45 return
46}
diff --git a/src/cmd/peer_mockup/process.go b/src/cmd/peer_mockup/process.go
new file mode 100644
index 0000000..51d4805
--- /dev/null
+++ b/src/cmd/peer_mockup/process.go
@@ -0,0 +1,118 @@
1package main
2
3import (
4 "errors"
5 "fmt"
6
7 "gnunet/core"
8 "gnunet/crypto"
9 "gnunet/message"
10 "gnunet/transport"
11 "gnunet/util"
12)
13
14func process(ch *transport.MsgChannel, from, to *core.Peer) (err error) {
15 // create a new connection instance
16 c := transport.NewConnection(ch, from, to)
17 defer c.Close()
18
19 // read and push next message
20 in := make(chan message.Message)
21 go func() {
22 for {
23 msg, err := c.Receive()
24 if err != nil {
25 fmt.Printf("Receive: %s\n", err.Error())
26 return
27 }
28 in <- msg
29 }
30 }()
31
32 // are we initiating the connection?
33 init := (from == p)
34 if init {
35 c.Send(message.NewTransportTcpWelcomeMsg(p.GetID()))
36 }
37
38 // remember peer addresses (only ONE!)
39 pAddr := p.GetAddressList()[0]
40 tAddr := t.GetAddressList()[0]
41
42 send := make(map[uint16]bool)
43 //received := make(map[uint16]bool)
44 pending := make(map[uint16]message.Message)
45
46 // process loop
47 for {
48 select {
49 case m := <-in:
50 switch msg := m.(type) {
51
52 case *message.TransportTcpWelcomeMsg:
53 if init {
54 c.Send(message.NewHelloMsg(p.GetID()))
55 c.Send(message.NewTransportPingMsg(t.GetID(), tAddr))
56 } else {
57 c.Send(message.NewTransportTcpWelcomeMsg(p.GetID()))
58 }
59
60 case *message.HelloMsg:
61
62 case *message.TransportPingMsg:
63 mOut := message.NewTransportPongMsg(msg.Challenge, pAddr)
64 if err := mOut.Sign(p.PrvKey()); err != nil {
65 return err
66 }
67 c.Send(mOut)
68
69 case *message.TransportPongMsg:
70 rc, err := msg.Verify(t.PubKey())
71 if err != nil {
72 return err
73 }
74 if !rc {
75 return errors.New("PONG verification failed")
76 }
77 send[message.TRANSPORT_PONG] = true
78 if mOut, ok := pending[message.TRANSPORT_SESSION_SYN]; ok {
79 c.Send(mOut)
80 }
81
82 case *message.SessionSynMsg:
83 mOut := message.NewSessionSynAckMsg(msg.Timestamp)
84 if send[message.TRANSPORT_PONG] {
85 c.Send(mOut)
86 } else {
87 pending[message.TRANSPORT_SESSION_SYN] = mOut
88 }
89
90 case *message.SessionQuotaMsg:
91 c.SetBandwidth(msg.Quota)
92
93 case *message.SessionAckMsg:
94
95 case *message.SessionKeepAliveMsg:
96 c.Send(message.NewSessionKeepAliveRespMsg(msg.Nonce))
97
98 case *message.EphemeralKeyMsg:
99 rc, err := msg.Verify(t.PubKey())
100 if err != nil {
101 return err
102 }
103 if !rc {
104 return errors.New("EPHKEY verification failed")
105 }
106 t.SetEphKeyMsg(msg)
107 c.Send(p.EphKeyMsg())
108 secret := crypto.SharedSecret(p.EphPrvKey(), t.EphKeyMsg().Public())
109 c.SharedSecret(util.Clone(secret.Bits[:]))
110
111 default:
112 fmt.Printf("!!! %v\n", msg)
113 }
114 default:
115 }
116 }
117 return nil
118}
diff --git a/src/cmd/vanityid/main.go b/src/cmd/vanityid/main.go
new file mode 100644
index 0000000..0b9fb18
--- /dev/null
+++ b/src/cmd/vanityid/main.go
@@ -0,0 +1,46 @@
1package main
2
3import (
4 "crypto/rand"
5 "encoding/hex"
6 "flag"
7 "fmt"
8 "regexp"
9
10 "github.com/bfix/gospel/crypto/ed25519"
11 "gnunet/util"
12)
13
14func main() {
15 // get arguments
16 flag.Parse()
17 prefixes := flag.Args()
18 num := len(prefixes)
19 if num == 0 {
20 fmt.Println("No prefixes specified -- done.")
21 return
22 }
23
24 // pre-compile regexp
25 reg := make([]*regexp.Regexp, num)
26 for i, p := range prefixes {
27 reg[i] = regexp.MustCompile(p)
28 }
29
30 // generate new keys in a loop
31 seed := make([]byte, 32)
32 for {
33 n, err := rand.Read(seed)
34 if err != nil || n != 32 {
35 panic(err)
36 }
37 prv := ed25519.NewPrivateKeyFromSeed(seed)
38 pub := prv.Public().Bytes()
39 id := util.EncodeBinaryToString(pub)
40 for _, r := range reg {
41 if r.MatchString(id) {
42 fmt.Printf("%s [%s]\n", id, hex.EncodeToString(seed))
43 }
44 }
45 }
46}
diff --git a/src/gnunet/config/config.go b/src/gnunet/config/config.go
new file mode 100644
index 0000000..74732ab
--- /dev/null
+++ b/src/gnunet/config/config.go
@@ -0,0 +1,141 @@
1package config
2
3import (
4 "encoding/json"
5 "io/ioutil"
6 "reflect"
7 "regexp"
8 "strings"
9
10 "github.com/bfix/gospel/logger"
11)
12
13///////////////////////////////////////////////////////////////////////
14// GNS configuration
15
16// GNSConfig
17type GNSConfig struct {
18 Endpoint string `json:"endpoint"` // end-point of GNS service
19 DHTReplLevel int `json:"dhtReplLevel"` // DHT replication level
20}
21
22///////////////////////////////////////////////////////////////////////
23// DHT configuration
24
25// DHTConfig
26type DHTConfig struct {
27 Endpoint string `json:"endpoint"` // end-point of DHT service
28}
29
30///////////////////////////////////////////////////////////////////////
31// Namecache configuration
32
33// NamecacheConfig
34type NamecacheConfig struct {
35 Endpoint string `json:"endpoint"` // end-point of Namecache service
36}
37
38///////////////////////////////////////////////////////////////////////
39
40// Environment settings
41type Environ map[string]string
42
43// Config is the aggregated configuration for GNUnet.
44type Config struct {
45 Env Environ `json:"environ"`
46 DHT *DHTConfig `json:"dht"`
47 GNS *GNSConfig `json:"gns"`
48 Namecache *NamecacheConfig `json:"namecache"`
49}
50
51var (
52 Cfg *Config
53)
54
55// Parse a JSON-encoded configuration file map it to the Config data structure.
56func ParseConfig(fileName string) (err error) {
57 // parse configuration file
58 file, err := ioutil.ReadFile(fileName)
59 if err != nil {
60 return
61 }
62 // unmarshal to Config data structure
63 Cfg = new(Config)
64 if err = json.Unmarshal(file, Cfg); err == nil {
65 // process all string-based config settings and apply
66 // string substitutions.
67 applySubstitutions(Cfg, Cfg.Env)
68 }
69 return
70}
71
72var (
73 rx = regexp.MustCompile("\\$\\{([^\\}]*)\\}")
74)
75
76func substString(s string, env map[string]string) string {
77 matches := rx.FindAllStringSubmatch(s, -1)
78 for _, m := range matches {
79 if len(m[1]) != 0 {
80 subst, ok := env[m[1]]
81 if !ok {
82 continue
83 }
84 s = strings.Replace(s, "${"+m[1]+"}", subst, -1)
85 }
86 }
87 return s
88}
89
90// applySubstitutions
91func applySubstitutions(x interface{}, env map[string]string) {
92
93 var process func(v reflect.Value)
94 process = func(v reflect.Value) {
95 for i := 0; i < v.NumField(); i++ {
96 fld := v.Field(i)
97 if fld.CanSet() {
98 switch fld.Kind() {
99 case reflect.String:
100 // check for substitution
101 s := fld.Interface().(string)
102 for {
103 s1 := substString(s, env)
104 if s1 == s {
105 break
106 }
107 logger.Printf(logger.DBG, "[config] %s --> %s\n", s, s1)
108 fld.SetString(s1)
109 s = s1
110 }
111
112 case reflect.Struct:
113 // handle nested struct
114 process(fld)
115
116 case reflect.Ptr:
117 // handle pointer
118 e := fld.Elem()
119 if e.IsValid() {
120 process(fld.Elem())
121 } else {
122 logger.Printf(logger.ERROR, "[config] 'nil' pointer encountered")
123 }
124 }
125 }
126 }
127 }
128
129 v := reflect.ValueOf(x)
130 switch v.Kind() {
131 case reflect.Ptr:
132 e := v.Elem()
133 if e.IsValid() {
134 process(e)
135 } else {
136 logger.Printf(logger.ERROR, "[config] 'nil' pointer encountered")
137 }
138 case reflect.Struct:
139 process(v)
140 }
141}
diff --git a/src/gnunet/config/config_test.go b/src/gnunet/config/config_test.go
new file mode 100644
index 0000000..ec35d08
--- /dev/null
+++ b/src/gnunet/config/config_test.go
@@ -0,0 +1,22 @@
1package config
2
3import (
4 "encoding/json"
5 "testing"
6
7 "github.com/bfix/gospel/logger"
8)
9
10func TestConfigRead(t *testing.T) {
11 logger.SetLogLevel(logger.WARN)
12 if err := ParseConfig("./gnunet-config.json"); err != nil {
13 t.Fatal(err)
14 }
15 if testing.Verbose() {
16 data, err := json.Marshal(Cfg)
17 if err != nil {
18 t.Fatal(err)
19 }
20 t.Log("cfg=" + string(data))
21 }
22}
diff --git a/src/gnunet/config/gnunet-config.json b/src/gnunet/config/gnunet-config.json
new file mode 100644
index 0000000..7ea854c
--- /dev/null
+++ b/src/gnunet/config/gnunet-config.json
@@ -0,0 +1,16 @@
1{
2 "environ": {
3 "TMP": "/tmp",
4 "RT_SYS": "${TMP}/gnunet-system-runtime"
5 },
6 "dht": {
7 "endpoint": "unix+${RT_SYS}/gnunet-service-dht.sock"
8 },
9 "gns": {
10 "endpoint": "unix+${RT_SYS}/gnunet-service-gns-go.sock+perm=0770",
11 "dhtReplLevel": 10
12 },
13 "namecache": {
14 "endpoint": "unix+${RT_SYS}/gnunet-service-namecache.sock"
15 }
16}
diff --git a/src/gnunet/core/peer.go b/src/gnunet/core/peer.go
new file mode 100644
index 0000000..ac2d980
--- /dev/null
+++ b/src/gnunet/core/peer.go
@@ -0,0 +1,93 @@
1package core
2
3import (
4 "fmt"
5
6 "github.com/bfix/gospel/crypto/ed25519"
7 "gnunet/message"
8 "gnunet/util"
9)
10
11/*
12type Peer interface {
13 GetID() []byte
14 GetIDString() string
15 GetAddressList() []*util.Address
16 Sign(msg []byte) ([]byte, error)
17 Verify(msg, sig []byte) bool
18}
19*/
20
21type Peer struct {
22 pub *ed25519.PublicKey
23 idString string
24 addrList []*util.Address
25 prv *ed25519.PrivateKey // long-term signing key
26 ephPrv *ed25519.PrivateKey // ephemeral signing key
27 ephMsg *message.EphemeralKeyMsg // ephemeral signing key message
28}
29
30func NewPeer(data []byte, local bool) (p *Peer, err error) {
31 p = new(Peer)
32 if local {
33 p.prv = ed25519.NewPrivateKeyFromSeed(data)
34 p.pub = p.prv.Public()
35 p.ephPrv, p.ephMsg, err = message.NewEphemeralKey(p.pub.Bytes(), p.prv)
36 if err != nil {
37 return
38 }
39 } else {
40 p.prv = nil
41 p.pub = ed25519.NewPublicKeyFromBytes(data)
42 }
43 p.idString = util.EncodeBinaryToString(p.pub.Bytes())
44 p.addrList = make([]*util.Address, 0)
45 return
46}
47
48func (p *Peer) EphKeyMsg() *message.EphemeralKeyMsg {
49 return p.ephMsg
50}
51
52func (p *Peer) SetEphKeyMsg(msg *message.EphemeralKeyMsg) {
53 p.ephMsg = msg
54}
55
56func (p *Peer) EphPrvKey() *ed25519.PrivateKey {
57 return p.ephPrv
58}
59
60func (p *Peer) PrvKey() *ed25519.PrivateKey {
61 return p.prv
62}
63
64func (p *Peer) PubKey() *ed25519.PublicKey {
65 return p.pub
66}
67
68func (p *Peer) GetID() []byte {
69 return p.pub.Bytes()
70}
71
72func (p *Peer) GetIDString() string {
73 return p.idString
74}
75
76func (p *Peer) GetAddressList() []*util.Address {
77 return p.addrList
78}
79
80func (p *Peer) AddAddress(a *util.Address) {
81 p.addrList = append(p.addrList, a)
82}
83
84func (p *Peer) Sign(msg []byte) (*ed25519.EdSignature, error) {
85 if p.prv == nil {
86 return nil, fmt.Errorf("No private key")
87 }
88 return p.prv.EdSign(msg)
89}
90
91func (p *Peer) Verify(msg []byte, sig *ed25519.EdSignature) (bool, error) {
92 return p.pub.EdVerify(msg, sig)
93}
diff --git a/src/gnunet/crypto/hash.go b/src/gnunet/crypto/hash.go
new file mode 100644
index 0000000..87e3941
--- /dev/null
+++ b/src/gnunet/crypto/hash.go
@@ -0,0 +1,24 @@
1package crypto
2
3import (
4 "crypto/sha512"
5
6 "gnunet/util"
7)
8
9type HashCode struct {
10 Bits []byte `size:"64"`
11}
12
13func NewHashCode() *HashCode {
14 return &HashCode{
15 Bits: make([]byte, 64),
16 }
17}
18
19func Hash(data []byte) *HashCode {
20 val := sha512.Sum512(data)
21 return &HashCode{
22 Bits: util.Clone(val[:]),
23 }
24}
diff --git a/src/gnunet/crypto/key_derivation.go b/src/gnunet/crypto/key_derivation.go
new file mode 100644
index 0000000..575f511
--- /dev/null
+++ b/src/gnunet/crypto/key_derivation.go
@@ -0,0 +1,31 @@
1package crypto
2
3import (
4 "crypto/sha256"
5 "crypto/sha512"
6
7 "github.com/bfix/gospel/crypto/ed25519"
8 "github.com/bfix/gospel/math"
9 "golang.org/x/crypto/hkdf"
10)
11
12var (
13 ED25519_N = ed25519.GetCurve().N
14)
15
16// DeriveH derives an integer 'h' from the arguments.
17func DeriveH(pub *ed25519.PublicKey, label, context string) *math.Int {
18 prk := hkdf.Extract(sha512.New, pub.Bytes(), []byte("key-derivation"))
19 data := append([]byte(label), []byte(context)...)
20 rdr := hkdf.Expand(sha256.New, prk, data)
21 b := make([]byte, 64)
22 rdr.Read(b)
23 return math.NewIntFromBytes(b).Mod(ED25519_N)
24}
25
26// DerivePublicKey "shifts" a public key 'Q' to a new point 'P' where
27// P = h*Q with 'h' being a factor derived from the arguments.
28func DerivePublicKey(pub *ed25519.PublicKey, label string, context string) *ed25519.PublicKey {
29 h := DeriveH(pub, label, context)
30 return pub.Mult(h)
31}
diff --git a/src/gnunet/crypto/key_derivation_test.go b/src/gnunet/crypto/key_derivation_test.go
new file mode 100644
index 0000000..8b927d2
--- /dev/null
+++ b/src/gnunet/crypto/key_derivation_test.go
@@ -0,0 +1,215 @@
1package crypto
2
3import (
4 "bytes"
5 "crypto/sha256"
6 "crypto/sha512"
7 "encoding/hex"
8 "testing"
9
10 "github.com/bfix/gospel/crypto/ed25519"
11 "github.com/bfix/gospel/math"
12 "gnunet/util"
13 "golang.org/x/crypto/hkdf"
14)
15
16func TestDeriveH(t *testing.T) {
17 var (
18 D = []byte{
19 0x40, 0x00, 0xd4, 0xe6, 0x85, 0xa3, 0x40, 0xe2,
20 0xa5, 0xab, 0x0f, 0xe0, 0x56, 0xbd, 0x5b, 0x93,
21 0x6b, 0x86, 0xcd, 0x2d, 0xd2, 0xa0, 0x71, 0x4c,
22 0x1e, 0x2b, 0x16, 0x08, 0x83, 0xaa, 0x7f, 0x88,
23 }
24 PUB = []byte{
25 0x93, 0x34, 0x71, 0xF6, 0x99, 0x19, 0x0C, 0x62,
26 0x85, 0xC7, 0x9B, 0x83, 0x9D, 0xCA, 0x83, 0x91,
27 0x38, 0xFA, 0x87, 0xFB, 0xB8, 0xD4, 0xF6, 0xF0,
28 0xF0, 0x4B, 0x7F, 0x0A, 0x48, 0xBF, 0x95, 0xF7,
29 }
30
31 ID = "JCT73XMS346651E7KE1SVJM3J4WFN1ZVQ3AFDW7G9DZGMJ5ZJQVG"
32 LABEL = "home"
33 CONTEXT = "gns"
34
35 H = []byte{
36 0x0d, 0x4a, 0x75, 0x30, 0xfd, 0x07, 0xe1, 0x88,
37 0xfc, 0xa0, 0xf4, 0x29, 0x52, 0x66, 0x24, 0x0f,
38 0x1e, 0x08, 0x91, 0xb0, 0x61, 0x39, 0x46, 0xca,
39 0xfb, 0x4c, 0xe3, 0xa8, 0x54, 0xca, 0x47, 0x7a,
40 }
41 Q = []byte{
42 0x26, 0x84, 0x1b, 0x24, 0x35, 0xa4, 0x63, 0xe9,
43 0xf0, 0x48, 0xae, 0x3e, 0xf7, 0xe8, 0x1b, 0xca,
44 0x55, 0x9f, 0x4c, 0x1e, 0x16, 0x18, 0xa6, 0xd3,
45 0x5b, 0x91, 0x0d, 0x54, 0x31, 0x6e, 0xbf, 0x97,
46 }
47
48 QUERY = []byte{
49 0x13, 0xab, 0x16, 0x69, 0x72, 0xf5, 0x8a, 0xcf,
50 0x21, 0x96, 0xc8, 0x19, 0x9c, 0x92, 0x46, 0x6f,
51 0x15, 0xa2, 0x45, 0x19, 0x0a, 0x18, 0xd2, 0x3b,
52 0x7b, 0x83, 0x21, 0x4e, 0x9d, 0x03, 0x3b, 0x81,
53 0x7d, 0xc2, 0x23, 0xf3, 0x26, 0xe4, 0x7b, 0x43,
54 0x52, 0xa1, 0x03, 0x59, 0x00, 0xd7, 0x2e, 0x3f,
55 0x17, 0x0f, 0xc3, 0xb5, 0xf5, 0xcf, 0x3a, 0xdd,
56 0xea, 0x8a, 0xc6, 0xbd, 0x2b, 0xfd, 0x50, 0x54,
57 }
58 )
59
60 // compute keypair from seed
61 prv := ed25519.NewPrivateKeyFromD(math.NewIntFromBytes(D))
62 pub := prv.Public()
63 if bytes.Compare(pub.Bytes(), PUB) != 0 {
64 t.Fatal("Wrong public key")
65 }
66 if ID != util.EncodeBinaryToString(pub.Bytes()) {
67 t.Fatal("Wrong ego ID")
68 }
69
70 hBuf := make([]byte, 32)
71 hFull := DeriveH(pub, LABEL, CONTEXT)
72 h := hFull.Mod(ED25519_N)
73 util.CopyBlock(hBuf, h.Bytes())
74 if bytes.Compare(hBuf, H) != 0 {
75 if testing.Verbose() {
76 t.Logf("H(computed) = %s\n", hex.EncodeToString(hBuf))
77 t.Logf("H(expected) = %s\n", hex.EncodeToString(H))
78 }
79 t.Fatal("H mismatch")
80 }
81
82 dpub := pub.Mult(h)
83 dpub2 := DerivePublicKey(pub, LABEL, CONTEXT)
84 if !dpub.Q.Equals(dpub2.Q) {
85 t.Fatal("Q mismatch")
86 }
87
88 q := dpub.Q.Bytes()
89 if bytes.Compare(q, Q) != 0 {
90 if testing.Verbose() {
91 t.Logf("derived_x(computed) = %s\n", hex.EncodeToString(q))
92 t.Logf("derived_x(expected) = %s\n", hex.EncodeToString(Q))
93 }
94 t.Fatal("x-coordinate mismatch")
95 }
96 pk1 := dpub.Bytes()
97 pk2 := DerivePublicKey(pub, LABEL, CONTEXT).Bytes()
98 if bytes.Compare(pk1, pk2) != 0 {
99 if testing.Verbose() {
100 t.Logf("derived(1) = %s\n", hex.EncodeToString(pk1))
101 t.Logf("derived(2) = %s\n", hex.EncodeToString(pk2))
102 }
103 t.Fatal("Derived key mismatch")
104 }
105
106 out := sha512.Sum512(pk1)
107 if bytes.Compare(out[:], QUERY) != 0 {
108 if testing.Verbose() {
109 t.Log("query(expected) = " + hex.EncodeToString(QUERY))
110 t.Log("query(computed) = " + hex.EncodeToString(out[:]))
111 }
112 t.Fatal("Query mismatch")
113 }
114}
115
116func TestHKDF_gnunet(t *testing.T) {
117
118 var (
119 // SALT as defined in GNUnet
120 salt = []byte("key-derivation")
121 // expected PRK (as dumped in GNUnet)
122 PRK = []byte{
123 0xEB, 0xFE, 0x63, 0xBA, 0x68, 0x2D, 0xA5, 0x5C,
124 0xF8, 0x37, 0xCE, 0x8F, 0x94, 0x3B, 0x01, 0x44,
125 0x1B, 0xF9, 0x67, 0x3D, 0xFC, 0x91, 0xED, 0x61,
126 0x79, 0x94, 0xE8, 0x2A, 0x62, 0x0A, 0xE8, 0x6E,
127 0x59, 0xDB, 0x56, 0x63, 0x80, 0x94, 0x63, 0xAC,
128 0x8D, 0x35, 0xE2, 0xEA, 0xBA, 0xE6, 0xF3, 0xE8,
129 0xC1, 0x4B, 0xC9, 0x4F, 0xBD, 0xE3, 0xE6, 0x61,
130 0x01, 0xB3, 0xB2, 0x1C, 0x6F, 0x19, 0x73, 0x8B,
131 }
132 info = []byte("master-homegns")
133 // expected result (as dumped in GNUnet)
134 OKM = []byte{
135 0x30, 0x86, 0x34, 0x7F, 0x2E, 0x12, 0xD7, 0x65,
136 0x35, 0x70, 0x44, 0xE2, 0xF6, 0x9B, 0x84, 0x59,
137 0x6E, 0xE1, 0x7F, 0x62, 0x93, 0xAD, 0xAE, 0x56,
138 0x50, 0x6A, 0xA6, 0xD6, 0x8D, 0x39, 0x39, 0x95,
139 }
140 )
141 prk := hkdf.Extract(sha512.New, pub.Bytes(), salt)
142 if testing.Verbose() {
143 t.Log("PRK(computed) = " + hex.EncodeToString(prk))
144 }
145 if bytes.Compare(prk, PRK) != 0 {
146 t.Log("PRK(expected) = " + hex.EncodeToString(PRK))
147 t.Fatal("PRK mismatch")
148 }
149
150 rdr := hkdf.Expand(sha256.New, prk, info)
151 okm := make([]byte, len(OKM))
152 rdr.Read(okm)
153 if testing.Verbose() {
154 t.Log("OKM(computed) = " + hex.EncodeToString(okm))
155 }
156 if bytes.Compare(okm, OKM) != 0 {
157 t.Log("OKM(expected) = " + hex.EncodeToString(OKM))
158 t.Fatal("OKM mismatch")
159 }
160}
161
162func TestHDKF(t *testing.T) {
163 var (
164 ikm = []byte{
165 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
166 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
167 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
168 }
169 salt = []byte{
170 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
171 0x08, 0x09, 0x0a, 0x0b, 0x0c,
172 }
173 PRK = []byte{
174 0x66, 0x57, 0x99, 0x82, 0x37, 0x37, 0xde, 0xd0,
175 0x4a, 0x88, 0xe4, 0x7e, 0x54, 0xa5, 0x89, 0x0b,
176 0xb2, 0xc3, 0xd2, 0x47, 0xc7, 0xa4, 0x25, 0x4a,
177 0x8e, 0x61, 0x35, 0x07, 0x23, 0x59, 0x0a, 0x26,
178 0xc3, 0x62, 0x38, 0x12, 0x7d, 0x86, 0x61, 0xb8,
179 0x8c, 0xf8, 0x0e, 0xf8, 0x02, 0xd5, 0x7e, 0x2f,
180 0x7c, 0xeb, 0xcf, 0x1e, 0x00, 0xe0, 0x83, 0x84,
181 0x8b, 0xe1, 0x99, 0x29, 0xc6, 0x1b, 0x42, 0x37,
182 }
183 info = []byte{
184 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
185 }
186 OKM = []byte{
187 0x83, 0x23, 0x90, 0x08, 0x6c, 0xda, 0x71, 0xfb,
188 0x47, 0x62, 0x5b, 0xb5, 0xce, 0xb1, 0x68, 0xe4,
189 0xc8, 0xe2, 0x6a, 0x1a, 0x16, 0xed, 0x34, 0xd9,
190 0xfc, 0x7f, 0xe9, 0x2c, 0x14, 0x81, 0x57, 0x93,
191 0x38, 0xda, 0x36, 0x2c, 0xb8, 0xd9, 0xf9, 0x25,
192 0xd7, 0xcb,
193 }
194 )
195
196 prk := hkdf.Extract(sha512.New, ikm, salt)
197 if testing.Verbose() {
198 t.Log("PRK(computed) = " + hex.EncodeToString(prk))
199 }
200 if bytes.Compare(prk, PRK) != 0 {
201 t.Log("PRK(expected) = " + hex.EncodeToString(PRK))
202 t.Fatal("PRK mismatch")
203 }
204
205 rdr := hkdf.Expand(sha512.New, prk, info)
206 okm := make([]byte, len(OKM))
207 rdr.Read(okm)
208 if testing.Verbose() {
209 t.Log("OKM(computed) = " + hex.EncodeToString(okm))
210 }
211 if bytes.Compare(okm, OKM) != 0 {
212 t.Log("OKM(expected) = " + hex.EncodeToString(OKM))
213 t.Fatal("OKM mismatch")
214 }
215}
diff --git a/src/gnunet/crypto/key_exchange.go b/src/gnunet/crypto/key_exchange.go
new file mode 100644
index 0000000..0efa441
--- /dev/null
+++ b/src/gnunet/crypto/key_exchange.go
@@ -0,0 +1,12 @@
1package crypto
2
3import (
4 "github.com/bfix/gospel/crypto/ed25519"
5)
6
7// SharedSecret computes a 64 byte shared secret
8// between (prvA,pubB) and (prvB,pubA).
9func SharedSecret(prv *ed25519.PrivateKey, pub *ed25519.PublicKey) *HashCode {
10 ss := pub.Mult(prv.D).Q.X().Bytes()
11 return Hash(ss)
12}
diff --git a/src/gnunet/crypto/key_exchange_test.go b/src/gnunet/crypto/key_exchange_test.go
new file mode 100644
index 0000000..93e95a2
--- /dev/null
+++ b/src/gnunet/crypto/key_exchange_test.go
@@ -0,0 +1,104 @@
1package crypto
2
3import (
4 "bytes"
5 "crypto/sha512"
6 "encoding/hex"
7 "testing"
8
9 "github.com/bfix/gospel/crypto/ed25519"
10 "github.com/bfix/gospel/math"
11)
12
13var (
14 d_1 = []byte{
15 0x7F, 0xDE, 0x7A, 0xAA, 0xEA, 0x0D, 0xA1, 0x7A,
16 0x7B, 0xCB, 0x4F, 0x57, 0x49, 0xCC, 0xA9, 0xBE,
17 0xA7, 0xFB, 0x2B, 0x85, 0x77, 0xAD, 0xC9, 0x55,
18 0xDA, 0xB2, 0x68, 0xB2, 0xB4, 0xCC, 0x24, 0x78,
19 }
20
21 d_2 = []byte{
22 0x20, 0x3f, 0x2f, 0x8c, 0x54, 0xf4, 0x1a, 0xd3,
23 0x01, 0x9a, 0x56, 0x92, 0x19, 0xda, 0xee, 0x4f,
24 0xd2, 0x53, 0x55, 0xa6, 0x3c, 0xfc, 0x57, 0x40,
25 0x8a, 0xb0, 0x86, 0x88, 0xf6, 0x86, 0xf4, 0x9c,
26 }
27
28 ss = []byte{
29 0x0a, 0x49, 0x6e, 0x6b, 0x83, 0xca, 0x14, 0xeb,
30 0xa5, 0x0f, 0x45, 0x49, 0x1d, 0x90, 0x7e, 0x0c,
31 0x07, 0x56, 0x90, 0x16, 0xb2, 0x43, 0x7a, 0x0e,
32 0x91, 0x1f, 0x73, 0xe3, 0x4f, 0xbf, 0xfd, 0x85,
33 0x55, 0x86, 0x02, 0xc7, 0x42, 0xc0, 0x29, 0xb0,
34 0x70, 0xe3, 0xee, 0xad, 0x41, 0x89, 0xb6, 0xc1,
35 0x44, 0x71, 0xde, 0x2b, 0x60, 0x4e, 0x7b, 0x75,
36 0x05, 0xbd, 0x1b, 0x85, 0xd5, 0xfd, 0x63, 0x60,
37 }
38
39 prv_1, prv_2 *ed25519.PrivateKey
40 pub_1, pub_2 *ed25519.PublicKey
41 ss_1, ss_2 []byte
42)
43
44func calcSharedSecret() bool {
45 calc := func(prv *ed25519.PrivateKey, pub *ed25519.PublicKey) []byte {
46 x := sha512.Sum512(pub.Mult(prv.D).Q.X().Bytes())
47 return x[:]
48 }
49 // compute shared secret
50 ss_1 = calc(prv_1, pub_2)
51 ss_2 = calc(prv_2, pub_1)
52 return bytes.Compare(ss_1, ss_2) == 0
53}
54
55func TestDHE(t *testing.T) {
56 // generate two key pairs
57 prv_1 = ed25519.NewPrivateKeyFromD(math.NewIntFromBytes(d_1))
58 pub_1 = prv_1.Public()
59 prv_2 = ed25519.NewPrivateKeyFromD(math.NewIntFromBytes(d_2))
60 pub_2 = prv_2.Public()
61
62 if !calcSharedSecret() {
63 t.Fatal("Shared secret mismatch")
64 }
65 if testing.Verbose() {
66 t.Logf("SS_1 = %s\n", hex.EncodeToString(ss_1))
67 t.Logf("SS_2 = %s\n", hex.EncodeToString(ss_2))
68 }
69
70 if bytes.Compare(ss_1[:], ss) != 0 {
71 t.Logf("SS(expected) = %s\n", hex.EncodeToString(ss))
72 t.Logf("SS(computed) = %s\n", hex.EncodeToString(ss_1[:]))
73 t.Fatal("Wrong shared secret:")
74 }
75
76}
77
78func TestDHERandom(t *testing.T) {
79 failed := 0
80 once := false
81 for i := 0; i < 100; i++ {
82 prv_1 = ed25519.NewPrivateKeyFromD(math.NewIntRnd(ED25519_N))
83 pub_1 = prv_1.Public()
84 prv_2 = ed25519.NewPrivateKeyFromD(math.NewIntRnd(ED25519_N))
85 pub_2 = prv_2.Public()
86
87 if !calcSharedSecret() {
88 if !once {
89 once = true
90 t.Logf("d1=%s\n", hex.EncodeToString(prv_1.D.Bytes()))
91 t.Logf("d2=%s\n", hex.EncodeToString(prv_2.D.Bytes()))
92 t.Logf("ss1=%s\n", hex.EncodeToString(ss_1))
93 t.Logf("ss2=%s\n", hex.EncodeToString(ss_2))
94 dd := prv_1.D.Mul(prv_2.D).Mod(ED25519_N)
95 pk := sha512.Sum512(ed25519.NewPrivateKeyFromD(dd).Public().Q.X().Bytes())
96 t.Logf("ss0=%s\n", hex.EncodeToString(pk[:]))
97 }
98 failed++
99 }
100 }
101 if failed > 0 {
102 t.Fatalf("Shared secret mismatches: %d/1000", failed)
103 }
104}
diff --git a/src/gnunet/crypto/keys_test.go b/src/gnunet/crypto/keys_test.go
new file mode 100644
index 0000000..69d70ca
--- /dev/null
+++ b/src/gnunet/crypto/keys_test.go
@@ -0,0 +1,69 @@
1package crypto
2
3import (
4 "bytes"
5 "encoding/hex"
6 "testing"
7
8 "github.com/bfix/gospel/crypto/ed25519"
9 "github.com/bfix/gospel/math"
10 "gnunet/util"
11)
12
13var (
14 seed = []byte{
15 0x20, 0x3f, 0x2f, 0x8c, 0x54, 0xf4, 0x1a, 0xd3,
16 0x01, 0x9a, 0x56, 0x92, 0x19, 0xda, 0xee, 0x4f,
17 0xd2, 0x53, 0x55, 0xa6, 0x3c, 0xfc, 0x57, 0x40,
18 0x8a, 0xb0, 0x86, 0x88, 0xf6, 0x86, 0xf4, 0x9c,
19 }
20
21 d = []byte{
22 0x7F, 0xDE, 0x7A, 0xAA, 0xEA, 0x0D, 0xA1, 0x7A,
23 0x7B, 0xCB, 0x4F, 0x57, 0x49, 0xCC, 0xA9, 0xBE,
24 0xA7, 0xFB, 0x2B, 0x85, 0x77, 0xAD, 0xC9, 0x55,
25 0xDA, 0xB2, 0x68, 0xB2, 0xB4, 0xCC, 0x24, 0x78,
26 }
27
28 q = []byte{
29 0x92, 0xDC, 0xBF, 0x39, 0x40, 0x2D, 0xC6, 0x3C,
30 0x97, 0xA6, 0x81, 0xE0, 0xFC, 0xD8, 0x7C, 0x74,
31 0x17, 0xD3, 0xA3, 0x8C, 0x52, 0xFD, 0xE0, 0x49,
32 0xBC, 0xD0, 0x1C, 0x0A, 0x0B, 0x8C, 0x02, 0x51,
33 }
34
35 prv = ed25519.NewPrivateKeyFromSeed(seed)
36 pub = prv.Public()
37)
38
39func TestPrvKey(t *testing.T) {
40 if testing.Verbose() {
41 t.Logf("PRIVATE (seed=%s)\n", hex.EncodeToString(seed))
42 t.Logf(" d = %s\n", hex.EncodeToString(prv_1.D.Bytes()))
43 t.Logf(" ID = '%s'\n", util.EncodeBinaryToString(seed))
44 }
45
46 pubB := pub.Bytes()
47 if testing.Verbose() {
48 t.Logf("PUBLIC = %s\n", hex.EncodeToString(pubB))
49 t.Logf(" = '%s'\n", util.EncodeBinaryToString(pubB))
50 }
51
52 if !bytes.Equal(pubB, q) {
53 t.Logf("PUBLIC(computed) = %s\n", hex.EncodeToString(pubB))
54 t.Logf("PUBLIC(expected) = %s\n", hex.EncodeToString(q))
55 t.Fatal("Public key mismatch")
56 }
57
58 dVal := math.NewIntFromBytes(d)
59 if !dVal.Equals(prv.D) {
60 t.Fatal("Private exponent mismatch")
61 }
62
63 pub2 := ed25519.NewPrivateKeyFromD(dVal).Public().Bytes()
64 if !bytes.Equal(pubB, pub2) {
65 t.Logf("PUBLIC2(computed) = %s\n", hex.EncodeToString(pub2))
66 t.Logf("PUBLIC2(expected) = %s\n", hex.EncodeToString(pubB))
67 t.Fatal("Public key mismatch")
68 }
69}
diff --git a/src/gnunet/crypto/signature.go b/src/gnunet/crypto/signature.go
new file mode 100644
index 0000000..9a69b56
--- /dev/null
+++ b/src/gnunet/crypto/signature.go
@@ -0,0 +1,6 @@
1package crypto
2
3type SignaturePurpose struct {
4 Size uint32 `order:"big"` // How many bytes are signed?
5 Purpose uint32 `order:"big"` // Signature purpose
6}
diff --git a/src/gnunet/crypto/symmetric.go b/src/gnunet/crypto/symmetric.go
new file mode 100644
index 0000000..5fb2c72
--- /dev/null
+++ b/src/gnunet/crypto/symmetric.go
@@ -0,0 +1,59 @@
1package crypto
2
3import (
4 "crypto/aes"
5 "crypto/cipher"
6 "crypto/rand"
7
8 "golang.org/x/crypto/twofish"
9)
10
11type SymmetricKey struct {
12 AESKey []byte `size:"32"`
13 TwofishKey []byte `size:"32"`
14}
15
16func NewSymmetricKey() *SymmetricKey {
17 skey := &SymmetricKey{
18 AESKey: make([]byte, 32),
19 TwofishKey: make([]byte, 32),
20 }
21 rand.Read(skey.AESKey)
22 rand.Read(skey.TwofishKey)
23 return skey
24}
25
26type SymmetricIV struct {
27 AESIv []byte `size:"16"`
28 TwofishIv []byte `size:"16"`
29}
30
31func NewSymmetricIV() *SymmetricIV {
32 iv := &SymmetricIV{
33 AESIv: make([]byte, 16),
34 TwofishIv: make([]byte, 16),
35 }
36 rand.Read(iv.AESIv)
37 rand.Read(iv.TwofishIv)
38 return iv
39}
40
41func SymmetricDecrypt(data []byte, skey *SymmetricKey, iv *SymmetricIV) ([]byte, error) {
42 // Decrypt with Twofish CFB stream cipher
43 tf, err := twofish.NewCipher(skey.TwofishKey)
44 if err != nil {
45 return nil, err
46 }
47 stream := cipher.NewCFBDecrypter(tf, iv.TwofishIv)
48 out := make([]byte, len(data))
49 stream.XORKeyStream(out, data)
50
51 // Decrypt with AES CFB stream cipher
52 aes, err := aes.NewCipher(skey.AESKey)
53 if err != nil {
54 return nil, err
55 }
56 stream = cipher.NewCFBDecrypter(aes, iv.AESIv)
57 stream.XORKeyStream(out, out)
58 return out, nil
59}
diff --git a/src/gnunet/enums/block.go b/src/gnunet/enums/block.go
new file mode 100644
index 0000000..2d179a3
--- /dev/null
+++ b/src/gnunet/enums/block.go
@@ -0,0 +1,22 @@
1package enums
2
3var (
4 BLOCK_TYPE_ANY = 0 // Any type of block, used as a wildcard when searching.
5 BLOCK_TYPE_FS_DBLOCK = 1 // Data block (leaf) in the CHK tree.
6 BLOCK_TYPE_FS_IBLOCK = 2 // Inner block in the CHK tree.
7 BLOCK_TYPE_FS_KBLOCK = 3 // Legacy type, no longer in use.
8 BLOCK_TYPE_FS_SBLOCK = 4 // Legacy type, no longer in use.
9 BLOCK_TYPE_FS_NBLOCK = 5 // Legacy type, no longer in use.
10 BLOCK_TYPE_FS_ONDEMAND = 6 // Type of a block representing a block to be encoded on demand from disk.
11 BLOCK_TYPE_DHT_HELLO = 7 // Type of a block that contains a HELLO for a peer
12 BLOCK_TYPE_TEST = 8 // Block for testing.
13 BLOCK_TYPE_FS_UBLOCK = 9 // Type of a block representing any type of search result (universal).
14 BLOCK_TYPE_DNS = 10 // Block for storing DNS exit service advertisements.
15 BLOCK_TYPE_GNS_NAMERECORD = 11 // Block for storing record data
16 BLOCK_TYPE_REVOCATION = 12 // Block type for a revocation message by which a key is revoked.
17
18 BLOCK_TYPE_REGEX = 22 // Block to store a cadet regex state
19 BLOCK_TYPE_REGEX_ACCEPT = 23 // Block to store a cadet regex accepting state
20 BLOCK_TYPE_SET_TEST = 24 // Block for testing set/consensus.
21 BLOCK_TYPE_CONSENSUS_ELEMENT = 25 // Block type for consensus elements.
22)
diff --git a/src/gnunet/enums/dht.go b/src/gnunet/enums/dht.go
new file mode 100644
index 0000000..87c36a3
--- /dev/null
+++ b/src/gnunet/enums/dht.go
@@ -0,0 +1,12 @@
1package enums
2
3var (
4 DHT_RO_NONE = 0 // Default. Do nothing special.
5 DHT_RO_DEMULTIPLEX_EVERYWHERE = 1 // Each peer along the way should look at 'enc'
6 DHT_RO_RECORD_ROUTE = 2 // keep track of the route that the message took in the P2P network.
7 DHT_RO_FIND_PEER = 3 // This is a 'FIND-PEER' request, so approximate results are fine.
8 DHT_RO_BART = 4 // Possible message option for query key randomization.
9 DHT_RO_LAST_HOP = 16 // Flag given to monitors if this was the last hop for a GET/PUT.
10
11 DHT_GNS_REPLICATION_LEVEL = 10
12)
diff --git a/src/gnunet/enums/gns.go b/src/gnunet/enums/gns.go
new file mode 100644
index 0000000..2de5048
--- /dev/null
+++ b/src/gnunet/enums/gns.go
@@ -0,0 +1,287 @@
1package enums
2
3var (
4 GNS_MAX_BLOCK_SIZE = (63 * 1024) // Maximum size of a value that can be stored in a GNS block.
5
6 // GNS record types
7 GNS_TYPE_ANY = 0 // Record type indicating any record/'*'
8 GNS_TYPE_DNS_A = 1 // [RFC1035] IPv4 Address record
9 GNS_TYPE_DNS_NS = 2 // [RFC1035] Name Server record
10 GNS_TYPE_DNS_CNAME = 5 // [RFC1035] Canonical Name record
11 GNS_TYPE_DNS_SOA = 6 // [RFC2308] Start Of [a zone of] Authority
12 GNS_TYPE_DNS_PTR = 12 // [RFC1035] Pointer record
13 GNS_TYPE_DNS_MX = 15 // [RFC7505] Mail eXchange record
14 GNS_TYPE_DNS_TXT = 16 // [RFC1035] Text record
15 GNS_TYPE_DNS_RP = 17 // [RFC1183] Responsible Person
16 GNS_TYPE_DNS_AFSDB = 18 // [RFC1183] AFS Database Record
17 GNS_TYPE_DNS_SIG = 24 // [RFC2535] Signature
18 GNS_TYPE_DNS_KEY = 25 // [RFC2930] Key record
19 GNS_TYPE_DNS_AAAA = 28 // [RFC3596] IPv6 Address record
20 GNS_TYPE_DNS_LOC = 29 // [RFC1876] Location record
21 GNS_TYPE_DNS_SRV = 33 // [RFC2782] Service locator
22 GNS_TYPE_DNS_NAPTR = 35 // [RFC3403] Naming Authority Pointer
23 GNS_TYPE_DNS_KX = 36 // [RFC2230] Key eXchanger record
24 GNS_TYPE_DNS_CERT = 37 // [RFC4398] Certificate record
25 GNS_TYPE_DNS_DNAME = 39 // [RFC2672] Delegation Name
26 GNS_TYPE_DNS_APL = 42 // [RFC3123] Address Prefix List
27 GNS_TYPE_DNS_DS = 43 // [RFC4034] Delegation Signer
28 GNS_TYPE_DNS_SSHFP = 44 // [RFC4255] SSH public key Fingerprint
29 GNS_TYPE_DNS_IPSECKEY = 45 // [RFC4025] IPsec Key
30 GNS_TYPE_DNS_RRSIG = 46 // [RFC4034] DNSSEC Signature
31 GNS_TYPE_DNS_NSEC = 47 // [RFC4034] Next-Secure record
32 GNS_TYPE_DNS_DNSKEY = 48 // [RFC4034] DNS Key record
33 GNS_TYPE_DNS_DHCID = 49 // [RFC4701] DHCP Identifier
34 GNS_TYPE_DNS_NSEC3 = 50 // [RFC5155] NSEC record version 3 or NSEC hashed
35 GNS_TYPE_DNS_NSEC3PARAM = 51 // [RFC5155] NSEC3 Parameters
36 GNS_TYPE_DNS_TLSA = 52 // [RFC6698] TLSA certificate association
37 GNS_TYPE_DNS_HIP = 55 // [RFC5205] Host Identity Protocol
38 GNS_TYPE_DNS_CDS = 59 // [RFC7344] Child DS
39 GNS_TYPE_DNS_CDNSKEY = 60 // [RFC7344] Child DNSKEY
40 GNS_TYPE_DNS_TKEY = 249 // [RFC2930] Secret Key
41 GNS_TYPE_DNS_TSIG = 250 // [RFC2845] Transaction Signature
42 GNS_TYPE_DNS_URI = 256 // [RFC7553] Uniform Resource Identifier
43 GNS_TYPE_DNS_CAA = 257 // [RFC6844] Certification Authority Authorization
44 GNS_TYPE_DNS_TA = 32768 // [–] DNSSEC Trust Authorities
45 GNS_TYPE_DNS_DLV = 32769 // [RFC4431] DNSSEC Lookaside Validation record
46 GNS_TYPE_PKEY = 65536 // Record type for GNS zone transfer ("PKEY").
47 GNS_TYPE_NICK = 65537 // Record type for GNS nick names ("NICK").
48 GNS_TYPE_LEHO = 65538 // Record type for GNS legacy hostnames ("LEHO").
49 GNS_TYPE_VPN = 65539 // Record type for VPN resolution
50 GNS_TYPE_GNS2DNS = 65540 // Record type for delegation to DNS.
51 GNS_TYPE_BOX = 65541 // Record type for a boxed record (see TLSA/SRV handling in GNS).
52 GNS_TYPE_PLACE = 65542 // Record type for a social place.
53 GNS_TYPE_PHONE = 65543 // Record type for a phone (of CONVERSATION).
54 GNS_TYPE_RECLAIM_ATTR = 65544 // Record type for identity attributes (of RECLAIM).
55 GNS_TYPE_RECLAIM_TICKET = 65545 // Record type for local ticket references
56 GNS_TYPE_CREDENTIAL = 65547 // Record type for credential
57 GNS_TYPE_POLICY = 65548 // Record type for policies
58 GNS_TYPE_ATTRIBUTE = 65549 // Record type for reverse lookups
59 GNS_TYPE_RECLAIM_ATTR_REF = 65550 // Record type for reclaim records
60 GNS_TYPE_RECLAIM_MASTER = 65551 // Record type for RECLAIM master
61 GNS_TYPE_RECLAIM_OIDC_CLIENT = 65552 // Record type for reclaim OIDC clients
62 GNS_TYPE_RECLAIM_OIDC_REDIRECT = 65553 // Record type for reclaim OIDC redirect URIs
63
64 GNS_TYPE = map[int]string{
65 GNS_TYPE_ANY: "GNS_TYPE_ANY",
66 GNS_TYPE_DNS_A: "GNS_TYPE_DNS_A",
67 GNS_TYPE_DNS_NS: "GNS_TYPE_DNS_NS ",
68 GNS_TYPE_DNS_NS: "GNS_TYPE_DNS_NS",
69 GNS_TYPE_DNS_NS: "GNS_TYPE_DNS_NS",
70 GNS_TYPE_DNS_CNAME: "GNS_TYPE_DNS_CNAME ",
71 GNS_TYPE_DNS_NS: "GNS_TYPE_DNS_NS",
72 GNS_TYPE_DNS_CNAME: "GNS_TYPE_DNS_CNAME",
73 GNS_TYPE_DNS_CNAME: "GNS_TYPE_DNS_CNAME",
74 GNS_TYPE_DNS_SOA: "GNS_TYPE_DNS_SOA ",
75 GNS_TYPE_DNS_CNAME: "GNS_TYPE_DNS_CNAME",
76 GNS_TYPE_DNS_SOA: "GNS_TYPE_DNS_SOA",
77 GNS_TYPE_DNS_SOA: "GNS_TYPE_DNS_SOA",
78 GNS_TYPE_DNS_PTR: "GNS_TYPE_DNS_PTR ",
79 GNS_TYPE_DNS_SOA: "GNS_TYPE_DNS_SOA",
80 GNS_TYPE_DNS_PTR: "GNS_TYPE_DNS_PTR",
81 GNS_TYPE_DNS_PTR: "GNS_TYPE_DNS_PTR",
82 GNS_TYPE_DNS_MX: "GNS_TYPE_DNS_MX ",
83 GNS_TYPE_DNS_PTR: "GNS_TYPE_DNS_PTR",
84 GNS_TYPE_DNS_MX: "GNS_TYPE_DNS_MX",
85 GNS_TYPE_DNS_MX: "GNS_TYPE_DNS_MX",
86 GNS_TYPE_DNS_TXT: "GNS_TYPE_DNS_TXT ",
87 GNS_TYPE_DNS_MX: "GNS_TYPE_DNS_MX",
88 GNS_TYPE_DNS_TXT: "GNS_TYPE_DNS_TXT",
89 GNS_TYPE_DNS_TXT: "GNS_TYPE_DNS_TXT",
90 GNS_TYPE_DNS_RP: "GNS_TYPE_DNS_RP ",
91 GNS_TYPE_DNS_TXT: "GNS_TYPE_DNS_TXT",
92 GNS_TYPE_DNS_RP: "GNS_TYPE_DNS_RP",
93 GNS_TYPE_DNS_RP: "GNS_TYPE_DNS_RP",
94 GNS_TYPE_DNS_AFSDB: "GNS_TYPE_DNS_AFSDB ",
95 GNS_TYPE_DNS_RP: "GNS_TYPE_DNS_RP",
96 GNS_TYPE_DNS_AFSDB: "GNS_TYPE_DNS_AFSDB",
97 GNS_TYPE_DNS_AFSDB: "GNS_TYPE_DNS_AFSDB",
98 GNS_TYPE_DNS_SIG: "GNS_TYPE_DNS_SIG ",
99 GNS_TYPE_DNS_AFSDB: "GNS_TYPE_DNS_AFSDB",
100 GNS_TYPE_DNS_SIG: "GNS_TYPE_DNS_SIG",
101 GNS_TYPE_DNS_SIG: "GNS_TYPE_DNS_SIG",
102 GNS_TYPE_DNS_KEY: "GNS_TYPE_DNS_KEY ",
103 GNS_TYPE_DNS_SIG: "GNS_TYPE_DNS_SIG",
104 GNS_TYPE_DNS_KEY: "GNS_TYPE_DNS_KEY",
105 GNS_TYPE_DNS_KEY: "GNS_TYPE_DNS_KEY",
106 GNS_TYPE_DNS_AAAA: "GNS_TYPE_DNS_AAAA ",
107 GNS_TYPE_DNS_KEY: "GNS_TYPE_DNS_KEY",
108 GNS_TYPE_DNS_AAAA: "GNS_TYPE_DNS_AAAA",
109 GNS_TYPE_DNS_AAAA: "GNS_TYPE_DNS_AAAA",
110 GNS_TYPE_DNS_LOC: "GNS_TYPE_DNS_LOC ",
111 GNS_TYPE_DNS_AAAA: "GNS_TYPE_DNS_AAAA",
112 GNS_TYPE_DNS_LOC: "GNS_TYPE_DNS_LOC",
113 GNS_TYPE_DNS_LOC: "GNS_TYPE_DNS_LOC",
114 GNS_TYPE_DNS_SRV: "GNS_TYPE_DNS_SRV ",
115 GNS_TYPE_DNS_LOC: "GNS_TYPE_DNS_LOC",
116 GNS_TYPE_DNS_SRV: "GNS_TYPE_DNS_SRV",
117 GNS_TYPE_DNS_SRV: "GNS_TYPE_DNS_SRV",
118 GNS_TYPE_DNS_NAPTR: "GNS_TYPE_DNS_NAPTR ",
119 GNS_TYPE_DNS_SRV: "GNS_TYPE_DNS_SRV",
120 GNS_TYPE_DNS_NAPTR: "GNS_TYPE_DNS_NAPTR",
121 GNS_TYPE_DNS_NAPTR: "GNS_TYPE_DNS_NAPTR",
122 GNS_TYPE_DNS_KX: "GNS_TYPE_DNS_KX ",
123 GNS_TYPE_DNS_NAPTR: "GNS_TYPE_DNS_NAPTR",
124 GNS_TYPE_DNS_KX: "GNS_TYPE_DNS_KX",
125 GNS_TYPE_DNS_KX: "GNS_TYPE_DNS_KX",
126 GNS_TYPE_DNS_CERT: "GNS_TYPE_DNS_CERT ",
127 GNS_TYPE_DNS_KX: "GNS_TYPE_DNS_KX",
128 GNS_TYPE_DNS_CERT: "GNS_TYPE_DNS_CERT",
129 GNS_TYPE_DNS_CERT: "GNS_TYPE_DNS_CERT",
130 GNS_TYPE_DNS_DNAME: "GNS_TYPE_DNS_DNAME ",
131 GNS_TYPE_DNS_CERT: "GNS_TYPE_DNS_CERT",
132 GNS_TYPE_DNS_DNAME: "GNS_TYPE_DNS_DNAME",
133 GNS_TYPE_DNS_DNAME: "GNS_TYPE_DNS_DNAME",
134 GNS_TYPE_DNS_APL: "GNS_TYPE_DNS_APL ",
135 GNS_TYPE_DNS_DNAME: "GNS_TYPE_DNS_DNAME",
136 GNS_TYPE_DNS_APL: "GNS_TYPE_DNS_APL",
137 GNS_TYPE_DNS_APL: "GNS_TYPE_DNS_APL",
138 GNS_TYPE_DNS_DS: "GNS_TYPE_DNS_DS ",
139 GNS_TYPE_DNS_APL: "GNS_TYPE_DNS_APL",
140 GNS_TYPE_DNS_DS: "GNS_TYPE_DNS_DS",
141 GNS_TYPE_DNS_DS: "GNS_TYPE_DNS_DS",
142 GNS_TYPE_DNS_SSHFP: "GNS_TYPE_DNS_SSHFP ",
143 GNS_TYPE_DNS_DS: "GNS_TYPE_DNS_DS",
144 GNS_TYPE_DNS_SSHFP: "GNS_TYPE_DNS_SSHFP",
145 GNS_TYPE_DNS_SSHFP: "GNS_TYPE_DNS_SSHFP",
146 GNS_TYPE_DNS_IPSECKEY: "GNS_TYPE_DNS_IPSECKEY ",
147 GNS_TYPE_DNS_SSHFP: "GNS_TYPE_DNS_SSHFP",
148 GNS_TYPE_DNS_IPSECKEY: "GNS_TYPE_DNS_IPSECKEY",
149 GNS_TYPE_DNS_IPSECKEY: "GNS_TYPE_DNS_IPSECKEY",
150 GNS_TYPE_DNS_RRSIG: "GNS_TYPE_DNS_RRSIG ",
151 GNS_TYPE_DNS_IPSECKEY: "GNS_TYPE_DNS_IPSECKEY",
152 GNS_TYPE_DNS_RRSIG: "GNS_TYPE_DNS_RRSIG",
153 GNS_TYPE_DNS_RRSIG: "GNS_TYPE_DNS_RRSIG",
154 GNS_TYPE_DNS_NSEC: "GNS_TYPE_DNS_NSEC ",
155 GNS_TYPE_DNS_RRSIG: "GNS_TYPE_DNS_RRSIG",
156 GNS_TYPE_DNS_NSEC: "GNS_TYPE_DNS_NSEC",
157 GNS_TYPE_DNS_NSEC: "GNS_TYPE_DNS_NSEC",
158 GNS_TYPE_DNS_DNSKEY: "GNS_TYPE_DNS_DNSKEY ",
159 GNS_TYPE_DNS_NSEC: "GNS_TYPE_DNS_NSEC",
160 GNS_TYPE_DNS_DNSKEY: "GNS_TYPE_DNS_DNSKEY",
161 GNS_TYPE_DNS_DNSKEY: "GNS_TYPE_DNS_DNSKEY",
162 GNS_TYPE_DNS_DHCID: "GNS_TYPE_DNS_DHCID ",
163 GNS_TYPE_DNS_DNSKEY: "GNS_TYPE_DNS_DNSKEY",
164 GNS_TYPE_DNS_DHCID: "GNS_TYPE_DNS_DHCID",
165 GNS_TYPE_DNS_DHCID: "GNS_TYPE_DNS_DHCID",
166 GNS_TYPE_DNS_NSEC3: "GNS_TYPE_DNS_NSEC3 ",
167 GNS_TYPE_DNS_DHCID: "GNS_TYPE_DNS_DHCID",
168 GNS_TYPE_DNS_NSEC3: "GNS_TYPE_DNS_NSEC3",
169 GNS_TYPE_DNS_NSEC3: "GNS_TYPE_DNS_NSEC3",
170 GNS_TYPE_DNS_NSEC3PARAM: "GNS_TYPE_DNS_NSEC3PARAM ",
171 GNS_TYPE_DNS_NSEC3: "GNS_TYPE_DNS_NSEC3",
172 GNS_TYPE_DNS_NSEC3PARAM: "GNS_TYPE_DNS_NSEC3PARAM",
173 GNS_TYPE_DNS_NSEC3PARAM: "GNS_TYPE_DNS_NSEC3PARAM",
174 GNS_TYPE_DNS_TLSA: "GNS_TYPE_DNS_TLSA ",
175 GNS_TYPE_DNS_NSEC3PARAM: "GNS_TYPE_DNS_NSEC3PARAM",
176 GNS_TYPE_DNS_TLSA: "GNS_TYPE_DNS_TLSA",
177 GNS_TYPE_DNS_TLSA: "GNS_TYPE_DNS_TLSA",
178 GNS_TYPE_DNS_HIP: "GNS_TYPE_DNS_HIP ",
179 GNS_TYPE_DNS_TLSA: "GNS_TYPE_DNS_TLSA",
180 GNS_TYPE_DNS_HIP: "GNS_TYPE_DNS_HIP",
181 GNS_TYPE_DNS_HIP: "GNS_TYPE_DNS_HIP",
182 GNS_TYPE_DNS_CDS: "GNS_TYPE_DNS_CDS ",
183 GNS_TYPE_DNS_HIP: "GNS_TYPE_DNS_HIP",
184 GNS_TYPE_DNS_CDS: "GNS_TYPE_DNS_CDS",
185 GNS_TYPE_DNS_CDS: "GNS_TYPE_DNS_CDS",
186 GNS_TYPE_DNS_CDNSKEY: "GNS_TYPE_DNS_CDNSKEY ",
187 GNS_TYPE_DNS_CDS: "GNS_TYPE_DNS_CDS",
188 GNS_TYPE_DNS_CDNSKEY: "GNS_TYPE_DNS_CDNSKEY",
189 GNS_TYPE_DNS_CDNSKEY: "GNS_TYPE_DNS_CDNSKEY",
190 GNS_TYPE_DNS_TKEY: "GNS_TYPE_DNS_TKEY ",
191 GNS_TYPE_DNS_CDNSKEY: "GNS_TYPE_DNS_CDNSKEY",
192 GNS_TYPE_DNS_TKEY: "GNS_TYPE_DNS_TKEY",
193 GNS_TYPE_DNS_TKEY: "GNS_TYPE_DNS_TKEY",
194 GNS_TYPE_DNS_TSIG: "GNS_TYPE_DNS_TSIG ",
195 GNS_TYPE_DNS_TKEY: "GNS_TYPE_DNS_TKEY",
196 GNS_TYPE_DNS_TSIG: "GNS_TYPE_DNS_TSIG",
197 GNS_TYPE_DNS_TSIG: "GNS_TYPE_DNS_TSIG",
198 GNS_TYPE_DNS_URI: "GNS_TYPE_DNS_URI ",
199 GNS_TYPE_DNS_TSIG: "GNS_TYPE_DNS_TSIG",
200 GNS_TYPE_DNS_URI: "GNS_TYPE_DNS_URI",
201 GNS_TYPE_DNS_URI: "GNS_TYPE_DNS_URI",
202 GNS_TYPE_DNS_CAA: "GNS_TYPE_DNS_CAA ",
203 GNS_TYPE_DNS_URI: "GNS_TYPE_DNS_URI",
204 GNS_TYPE_DNS_CAA: "GNS_TYPE_DNS_CAA",
205 GNS_TYPE_DNS_CAA: "GNS_TYPE_DNS_CAA",
206 GNS_TYPE_DNS_TA: "GNS_TYPE_DNS_TA ",
207 GNS_TYPE_DNS_CAA: "GNS_TYPE_DNS_CAA",
208 GNS_TYPE_DNS_TA: "GNS_TYPE_DNS_TA",
209 GNS_TYPE_DNS_TA: "GNS_TYPE_DNS_TA",
210 GNS_TYPE_DNS_DLV: "GNS_TYPE_DNS_DLV ",
211 GNS_TYPE_DNS_TA: "GNS_TYPE_DNS_TA",
212 GNS_TYPE_DNS_DLV: "GNS_TYPE_DNS_DLV",
213 GNS_TYPE_DNS_DLV: "GNS_TYPE_DNS_DLV",
214 GNS_TYPE_PKEY: "GNS_TYPE_PKEY ",
215 GNS_TYPE_DNS_DLV: "GNS_TYPE_DNS_DLV",
216 GNS_TYPE_PKEY: "GNS_TYPE_PKEY",
217 GNS_TYPE_PKEY: "GNS_TYPE_PKEY",
218 GNS_TYPE_NICK: "GNS_TYPE_NICK ",
219 GNS_TYPE_PKEY: "GNS_TYPE_PKEY",
220 GNS_TYPE_NICK: "GNS_TYPE_NICK",
221 GNS_TYPE_NICK: "GNS_TYPE_NICK",
222 GNS_TYPE_LEHO: "GNS_TYPE_LEHO ",
223 GNS_TYPE_NICK: "GNS_TYPE_NICK",
224 GNS_TYPE_LEHO: "GNS_TYPE_LEHO",
225 GNS_TYPE_LEHO: "GNS_TYPE_LEHO",
226 GNS_TYPE_VPN: "GNS_TYPE_VPN ",
227 GNS_TYPE_LEHO: "GNS_TYPE_LEHO",
228 GNS_TYPE_VPN: "GNS_TYPE_VPN",
229 GNS_TYPE_VPN: "GNS_TYPE_VPN",
230 GNS_TYPE_GNS2DNS: "GNS_TYPE_GNS2DNS ",
231 GNS_TYPE_VPN: "GNS_TYPE_VPN",
232 GNS_TYPE_GNS2DNS: "GNS_TYPE_GNS2DNS",
233 GNS_TYPE_GNS2DNS: "GNS_TYPE_GNS2DNS",
234 GNS_TYPE_BOX: "GNS_TYPE_BOX ",
235 GNS_TYPE_GNS2DNS: "GNS_TYPE_GNS2DNS",
236 GNS_TYPE_BOX: "GNS_TYPE_BOX",
237 GNS_TYPE_BOX: "GNS_TYPE_BOX",
238 GNS_TYPE_PLACE: "GNS_TYPE_PLACE ",
239 GNS_TYPE_BOX: "GNS_TYPE_BOX",
240 GNS_TYPE_PLACE: "GNS_TYPE_PLACE",
241 GNS_TYPE_PLACE: "GNS_TYPE_PLACE",
242 GNS_TYPE_PHONE: "GNS_TYPE_PHONE ",
243 GNS_TYPE_PLACE: "GNS_TYPE_PLACE",
244 GNS_TYPE_PHONE: "GNS_TYPE_PHONE",
245 GNS_TYPE_PHONE: "GNS_TYPE_PHONE",
246 GNS_TYPE_RECLAIM_ATTR: "GNS_TYPE_RECLAIM_ATTR ",
247 GNS_TYPE_PHONE: "GNS_TYPE_PHONE",
248 GNS_TYPE_RECLAIM_ATTR: "GNS_TYPE_RECLAIM_ATTR",
249 GNS_TYPE_RECLAIM_ATTR: "GNS_TYPE_RECLAIM_ATTR",
250 GNS_TYPE_RECLAIM_TICKET: "GNS_TYPE_RECLAIM_TICKET ",
251 GNS_TYPE_RECLAIM_ATTR: "GNS_TYPE_RECLAIM_ATTR",
252 GNS_TYPE_RECLAIM_TICKET: "GNS_TYPE_RECLAIM_TICKET",
253 GNS_TYPE_RECLAIM_TICKET: "GNS_TYPE_RECLAIM_TICKET",
254 GNS_TYPE_CREDENTIAL: "GNS_TYPE_CREDENTIAL ",
255 GNS_TYPE_RECLAIM_TICKET: "GNS_TYPE_RECLAIM_TICKET",
256 GNS_TYPE_CREDENTIAL: "GNS_TYPE_CREDENTIAL",
257 GNS_TYPE_CREDENTIAL: "GNS_TYPE_CREDENTIAL",
258 GNS_TYPE_POLICY: "GNS_TYPE_POLICY ",
259 GNS_TYPE_CREDENTIAL: "GNS_TYPE_CREDENTIAL",
260 GNS_TYPE_POLICY: "GNS_TYPE_POLICY",
261 GNS_TYPE_POLICY: "GNS_TYPE_POLICY",
262 GNS_TYPE_ATTRIBUTE: "GNS_TYPE_ATTRIBUTE ",
263 GNS_TYPE_POLICY: "GNS_TYPE_POLICY",
264 GNS_TYPE_ATTRIBUTE: "GNS_TYPE_ATTRIBUTE",
265 GNS_TYPE_ATTRIBUTE: "GNS_TYPE_ATTRIBUTE",
266 GNS_TYPE_RECLAIM_ATTR_REF: "GNS_TYPE_RECLAIM_ATTR_REF ",
267 GNS_TYPE_ATTRIBUTE: "GNS_TYPE_ATTRIBUTE",
268 GNS_TYPE_RECLAIM_ATTR_REF: "GNS_TYPE_RECLAIM_ATTR_REF",
269 GNS_TYPE_RECLAIM_ATTR_REF: "GNS_TYPE_RECLAIM_ATTR_REF",
270 GNS_TYPE_RECLAIM_MASTER: "GNS_TYPE_RECLAIM_MASTER ",
271 GNS_TYPE_RECLAIM_ATTR_REF: "GNS_TYPE_RECLAIM_ATTR_REF",
272 GNS_TYPE_RECLAIM_MASTER: "GNS_TYPE_RECLAIM_MASTER",
273 GNS_TYPE_RECLAIM_MASTER: "GNS_TYPE_RECLAIM_MASTER",
274 GNS_TYPE_RECLAIM_OIDC_CLIENT: "GNS_TYPE_RECLAIM_OIDC_CLIENT ",
275 GNS_TYPE_RECLAIM_MASTER: "GNS_TYPE_RECLAIM_MASTER",
276 GNS_TYPE_RECLAIM_OIDC_CLIENT: "GNS_TYPE_RECLAIM_OIDC_CLIENT",
277 GNS_TYPE_RECLAIM_OIDC_CLIENT: "GNS_TYPE_RECLAIM_OIDC_CLIENT",
278 GNS_TYPE_RECLAIM_OIDC_REDIRECT: "GNS_TYPE_RECLAIM_OIDC_REDIRECT ",
279 GNS_TYPE_RECLAIM_OIDC_CLIENT: "GNS_TYPE_RECLAIM_OIDC_CLIENT",
280 GNS_TYPE_RECLAIM_OIDC_REDIRECT: "GNS_TYPE_RECLAIM_OIDC_REDIRECT",
281 }
282
283 // GNS_LocalOptions
284 GNS_LO_DEFAULT = 0 // Defaults, look in cache, then in DHT.
285 GNS_LO_NO_DHT = 1 // Never look in the DHT, keep request to local cache.
286 GNS_LO_LOCAL_MASTER = 2 // For the rightmost label, only look in the cache.
287)
diff --git a/src/gnunet/enums/signature.go b/src/gnunet/enums/signature.go
new file mode 100644
index 0000000..cb60f65
--- /dev/null
+++ b/src/gnunet/enums/signature.go
@@ -0,0 +1,34 @@
1package enums
2
3// Signature purpose constants
4const (
5 SIG_TEST = iota // Only used in test cases!
6 SIG_TRANSPORT_PONG_OWN // Confirming a particular address.
7 SIG_TRANSPORT_DISCONNECT // Confirming intent to disconnect.
8 SIG_REVOCATION // Confirming a key revocation.
9 SIG_NAMESPACE_ADVERTISEMENT // Namespace/pseudonym advertisement.
10 SIG_PEER_PLACEMENT // Affirm certain content (LOCation URIs).
11 SIG_FS_KBLOCK // Obsolete, legacy value.
12 SIG_FS_SBLOCK // Obsolete, legacy value.
13 SIG_FS_NBLOCK // Obsolete, legacy value.
14 SIG_FS_NBLOCK_KSIG // Obsolete, legacy value.
15 SIG_RESOLVER_RESPONSE // DNS_Advertisement
16 SIG_DNS_RECORD //
17 SIG_CHAT_MESSAGE // Chat message.
18 SIG_CHAT_RECEIPT // Confirmation receipt for chat message.
19 SIG_NSE_SEND // Network size estimate message.
20 SIG_GNS_RECORD_SIGN // GNS record block.
21 SIG_ECC_KEY // Set a session key.
22 SIG_FS_UBLOCK // UBlock Signature, done using DSS, not ECC.
23 SIG_REGEX_ACCEPT // Accept state (affirm matching service).
24 SIG_MULTICAST_MESSAGE // Multicast message sent by origin.
25 SIG_CONVERSATION_RING // Conversation ring.
26 SIG_SECRETSHARING_DKG1 // First round of distributed key generation.
27 SIG_SECRETSHARING_DKG2 // Second round of distributed key generation.
28 SIG_SECRETSHARING_DECRYPTION // Cooperative decryption.
29 SIG_MULTICAST_REQUEST // Multicast request sent by member.
30 SIG_SENSOR_ANOMALY_REPORT // Sensor anomaly report message.
31 SIG_GNUID_TOKEN // GNUid Token.
32 SIG_GNUID_TICKET // GNUid Ticket.
33 SIG_CREDENTIAL // GNUnet credential.
34)
diff --git a/src/gnunet/go.mod b/src/gnunet/go.mod
new file mode 100644
index 0000000..fce27da
--- /dev/null
+++ b/src/gnunet/go.mod
@@ -0,0 +1,5 @@
1module gnunet
2
3go 1.12
4
5require github.com/bfix/gospel v0.0.0-20190831192707-26682cc943e5
diff --git a/src/gnunet/go.sum b/src/gnunet/go.sum
new file mode 100644
index 0000000..e1de475
--- /dev/null
+++ b/src/gnunet/go.sum
@@ -0,0 +1,10 @@
1github.com/bfix/gospel v0.0.0-20190831192707-26682cc943e5 h1:vPrWvbQmjjEaWseuni9K7ffKzYLBLPbK27oHw5DvTAY=
2github.com/bfix/gospel v0.0.0-20190831192707-26682cc943e5/go.mod h1:RQYETFV9SP+VriIsHVqCntRpSbbRvCBnNTtbUl9NAKA=
3golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
4golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
5golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
6golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
7golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
8golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
9golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
10golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
diff --git a/src/gnunet/message/const.go b/src/gnunet/message/const.go
new file mode 100644
index 0000000..245af80
--- /dev/null
+++ b/src/gnunet/message/const.go
@@ -0,0 +1,37 @@
1package message
2
3import (
4 "time"
5)
6
7// Time constants
8var (
9 // How long is a PONG signature valid? We'll recycle a signature until
10 // 1/4 of this time is remaining. PONGs should expire so that if our
11 // external addresses change an adversary cannot replay them indefinitely.
12 // OTOH, we don't want to spend too much time generating PONG signatures,
13 // so they must have some lifetime to reduce our CPU usage.
14 PONG_SIGNATURE_LIFETIME = 1 * time.Hour
15
16 // After how long do we expire an address in a HELLO that we just
17 // validated? This value is also used for our own addresses when we
18 // create a HELLO.
19 HELLO_ADDRESS_EXPIRATION = 12 * time.Hour
20
21 // How often do we allow PINGing an address that we have not yet
22 // validated? This also determines how long we track an address that
23 // we cannot validate (because after this time we can destroy the
24 // validation record).
25 UNVALIDATED_PING_KEEPALIVE = 5 * time.Minute
26
27 // How often do we PING an address that we have successfully validated
28 // in the past but are not actively using? Should be (significantly)
29 // smaller than HELLO_ADDRESS_EXPIRATION.
30 VALIDATED_PING_FREQUENCY = 15 * time.Minute
31
32 // How often do we PING an address that we are currently using?
33 CONNECTED_PING_FREQUENCY = 2 * time.Minute
34
35 // How much delay is acceptable for sending the PING or PONG?
36 ACCEPTABLE_PING_DELAY = 1 * time.Second
37)
diff --git a/src/gnunet/message/factory.go b/src/gnunet/message/factory.go
new file mode 100644
index 0000000..5feb8c3
--- /dev/null
+++ b/src/gnunet/message/factory.go
@@ -0,0 +1,64 @@
1package message
2
3import (
4 "errors"
5 "fmt"
6)
7
8// NewEmptyMessage creates a new empty message object for the given type.
9func NewEmptyMessage(msgType uint16) (Message, error) {
10 switch msgType {
11 //------------------------------------------------------------------
12 // Transport
13 //------------------------------------------------------------------
14 case TRANSPORT_TCP_WELCOME:
15 return NewTransportTcpWelcomeMsg(nil), nil
16 case HELLO:
17 return NewHelloMsg(nil), nil
18 case TRANSPORT_SESSION_QUOTA:
19 return NewSessionQuotaMsg(0), nil
20 case TRANSPORT_SESSION_SYN:
21 return NewSessionSynMsg(0), nil
22 case TRANSPORT_SESSION_SYN_ACK:
23 return NewSessionSynAckMsg(0), nil
24 case TRANSPORT_SESSION_ACK:
25 return new(SessionAckMsg), nil
26 case TRANSPORT_PING:
27 return NewTransportPingMsg(nil, nil), nil
28 case TRANSPORT_PONG:
29 return NewTransportPongMsg(0, nil), nil
30 case TRANSPORT_SESSION_KEEPALIVE:
31 return NewSessionKeepAliveMsg(), nil
32
33 //------------------------------------------------------------------
34 // Core
35 //------------------------------------------------------------------
36 case CORE_EPHEMERAL_KEY:
37 return NewEphemeralKeyMsg(), nil
38
39 //------------------------------------------------------------------
40 // DHT
41 //------------------------------------------------------------------
42 case DHT_CLIENT_GET:
43 return NewDHTClientGetMsg(nil), nil
44 case DHT_CLIENT_RESULT:
45 return NewDHTClientResultMsg(nil), nil
46
47 //------------------------------------------------------------------
48 // GNS
49 //------------------------------------------------------------------
50 case GNS_LOOKUP:
51 return NewGNSLookupMsg(), nil
52 case GNS_LOOKUP_RESULT:
53 return NewGNSLookupResultMsg(0), nil
54
55 //------------------------------------------------------------------
56 // Namecache
57 //------------------------------------------------------------------
58 case NAMECACHE_LOOKUP_BLOCK:
59 return NewNamecacheLookupMsg(nil), nil
60 case NAMECACHE_LOOKUP_BLOCK_RESPONSE:
61 return NewNamecacheLookupResultMsg(), nil
62 }
63 return nil, errors.New(fmt.Sprintf("Unknown message type %d", msgType))
64}
diff --git a/src/gnunet/message/message.go b/src/gnunet/message/message.go
new file mode 100644
index 0000000..6b49a55
--- /dev/null
+++ b/src/gnunet/message/message.go
@@ -0,0 +1,37 @@
1package message
2
3import (
4 "errors"
5
6 "github.com/bfix/gospel/data"
7)
8
9var (
10 ErrMsgHeaderTooSmall = errors.New("Message header too small")
11)
12
13type Message interface {
14 Header() *MessageHeader
15}
16
17type MessageHeader struct {
18 MsgSize uint16 `order:"big"`
19 MsgType uint16 `order:"big"`
20}
21
22func (mh *MessageHeader) Size() uint16 {
23 return mh.MsgSize
24}
25
26func (mh *MessageHeader) Type() uint16 {
27 return mh.MsgType
28}
29
30func GetMsgHeader(b []byte) (mh *MessageHeader, err error) {
31 if b == nil || len(b) < 4 {
32 return nil, ErrMsgHeaderTooSmall
33 }
34 mh = new(MessageHeader)
35 err = data.Unmarshal(mh, b)
36 return
37}
diff --git a/src/gnunet/message/msg_core.go b/src/gnunet/message/msg_core.go
new file mode 100644
index 0000000..6e9b2d1
--- /dev/null
+++ b/src/gnunet/message/msg_core.go
@@ -0,0 +1,95 @@
1package message
2
3import (
4 //"encoding/hex"
5 "fmt"
6 "time"
7
8 "github.com/bfix/gospel/crypto/ed25519"
9 "github.com/bfix/gospel/data"
10 "gnunet/enums"
11 "gnunet/util"
12)
13
14type EphKeyBlock struct {
15 SignSize uint32 `order:"big"` // length of signed block
16 SigPurpose uint32 `order:"big"` // signature purpose: SIG_ECC_KEY
17 CreateTime uint64 `order:"big"` // Time of key creation
18 ExpireTime uint64 `order:"big"` // Time of key expiration
19 EphemeralKey []byte `size:"32"` // Ephemeral EdDSA public key
20 PeerID []byte `size:"32"` // Peer identity (EdDSA public key)
21}
22
23type EphemeralKeyMsg struct {
24 MsgSize uint16 `order:"big"` // total size of message
25 MsgType uint16 `order:"big"` // CORE_EPHEMERAL_KEY (88)
26 SenderStatus uint32 `order:"big"` // enum PeerStateMachine
27 Signature []byte `size:"64"` // EdDSA signature
28 SignedBlock *EphKeyBlock
29}
30
31func NewEphemeralKeyMsg() *EphemeralKeyMsg {
32 return &EphemeralKeyMsg{
33 MsgSize: 160,
34 MsgType: CORE_EPHEMERAL_KEY,
35 SenderStatus: 1,
36 Signature: make([]byte, 64),
37 SignedBlock: &EphKeyBlock{
38 SignSize: 88,
39 SigPurpose: enums.SIG_ECC_KEY,
40 CreateTime: util.GetAbsoluteTimeNow(),
41 ExpireTime: util.GetAbsoluteTimeOffset(12 * time.Hour),
42 EphemeralKey: make([]byte, 32),
43 PeerID: make([]byte, 32),
44 },
45 }
46}
47
48func (m *EphemeralKeyMsg) String() string {
49 return fmt.Sprintf("EphKeyMsg{%s,%s,%s,%d}",
50 util.EncodeBinaryToString(m.SignedBlock.PeerID),
51 util.EncodeBinaryToString(m.SignedBlock.EphemeralKey),
52 util.Timestamp(m.SignedBlock.ExpireTime),
53 m.SenderStatus)
54}
55
56// Header returns the message header in a separate instance.
57func (msg *EphemeralKeyMsg) Header() *MessageHeader {
58 return &MessageHeader{msg.MsgSize, msg.MsgType}
59}
60
61func (m *EphemeralKeyMsg) Public() *ed25519.PublicKey {
62 return ed25519.NewPublicKeyFromBytes(m.SignedBlock.PeerID)
63}
64
65func (m *EphemeralKeyMsg) Verify(pub *ed25519.PublicKey) (bool, error) {
66 data, err := data.Marshal(m.SignedBlock)
67 if err != nil {
68 return false, err
69 }
70 sig, err := ed25519.NewEdSignatureFromBytes(m.Signature)
71 if err != nil {
72 return false, err
73 }
74 return pub.EdVerify(data, sig)
75}
76
77func NewEphemeralKey(peerId []byte, ltPrv *ed25519.PrivateKey) (*ed25519.PrivateKey, *EphemeralKeyMsg, error) {
78 msg := NewEphemeralKeyMsg()
79 copy(msg.SignedBlock.PeerID, peerId)
80 seed := util.NewRndArray(32)
81 prv := ed25519.NewPrivateKeyFromSeed(seed)
82 copy(msg.SignedBlock.EphemeralKey, prv.Public().Bytes())
83
84 data, err := data.Marshal(msg.SignedBlock)
85 if err != nil {
86 return nil, nil, err
87 }
88 sig, err := ltPrv.EdSign(data)
89 if err != nil {
90 return nil, nil, err
91 }
92 copy(msg.Signature, sig.Bytes())
93
94 return prv, msg, nil
95}
diff --git a/src/gnunet/message/msg_dht.go b/src/gnunet/message/msg_dht.go
new file mode 100644
index 0000000..8b0e49c
--- /dev/null
+++ b/src/gnunet/message/msg_dht.go
@@ -0,0 +1,106 @@
1package message
2
3import (
4 "encoding/hex"
5 "fmt"
6
7 "gnunet/crypto"
8 "gnunet/enums"
9 "gnunet/util"
10)
11
12//----------------------------------------------------------------------
13// DHT_CLIENT_GET
14//----------------------------------------------------------------------
15
16// DHTClientGetMsg
17type DHTClientGetMsg struct {
18 MsgSize uint16 `order:"big"` // total size of message
19 MsgType uint16 `order:"big"` // DHT_CLIENT_GET (143)
20 Options uint32 `order:"big"` // Message options (DHT_RO_???)
21 ReplLevel uint32 `order:"big"` // Replication level for this message
22 Type uint32 `order:"big"` // The type for the data for the GET request (BLOCK_TYPE_???)
23 Key *crypto.HashCode // The key to search for
24 Id uint64 `order:"big"` // Unique ID identifying this request
25 XQuery []byte `size:"*"` // Optional xquery
26}
27
28// NewDHTClientGetMsg creates a new default DHTClientGetMsg object.
29func NewDHTClientGetMsg(key *crypto.HashCode) *DHTClientGetMsg {
30 if key == nil {
31 key = new(crypto.HashCode)
32 }
33 return &DHTClientGetMsg{
34 MsgSize: 88,
35 MsgType: DHT_CLIENT_GET,
36 Options: uint32(enums.DHT_RO_NONE),
37 ReplLevel: 1,
38 Type: uint32(enums.BLOCK_TYPE_ANY),
39 Key: key,
40 Id: 0,
41 XQuery: make([]byte, 0),
42 }
43}
44
45// Set a (new) XQuery in this message and return previous XQuery.
46func (m *DHTClientGetMsg) SetXQuery(xq []byte) []byte {
47 prev := m.XQuery
48 m.MsgSize -= uint16(len(prev))
49 m.XQuery = util.Clone(xq)
50 m.MsgSize += uint16(len(xq))
51 return prev
52}
53
54func (m *DHTClientGetMsg) String() string {
55 return fmt.Sprintf("DHTClientGetMsg{Id:%d,Type=%d,Options=%d,Repl=%d,Key=%s}",
56 m.Id, m.Type, m.Options, m.ReplLevel, hex.EncodeToString(m.Key.Bits))
57}
58
59// Header returns the message header in a separate instance.
60func (msg *DHTClientGetMsg) Header() *MessageHeader {
61 return &MessageHeader{msg.MsgSize, msg.MsgType}
62}
63
64//----------------------------------------------------------------------
65// DHT_CLIENT_RESULT
66//----------------------------------------------------------------------
67
68// DHTClientResultMsg
69type DHTClientResultMsg struct {
70 MsgSize uint16 `order:"big"` // total size of message
71 MsgType uint16 `order:"big"` // DHT_CLIENT_RESULT (145)
72 Type uint32 `order:"big"` // The type for the data
73 PutPathLen uint32 `order:"big"` // Number of peers recorded in outgoing path
74 GetPathLen uint32 `order:"big"` // Number of peers recorded from storage location
75 Id uint64 `order:"big"` // Unique ID of the matching GET request
76 Expire uint64 `order:"big"` // Expiration time
77 Key *crypto.HashCode // The key that was searched for
78 Data []byte `size:"*"` // put path, get path and actual data
79}
80
81// NewDHTClientResultMsg creates a new default DHTClientResultMsg object.
82func NewDHTClientResultMsg(key *crypto.HashCode) *DHTClientResultMsg {
83 if key == nil {
84 key = crypto.NewHashCode()
85 }
86 return &DHTClientResultMsg{
87 MsgSize: 64, // empty message size (no data)
88 MsgType: DHT_CLIENT_RESULT,
89 Type: 0,
90 PutPathLen: 0,
91 GetPathLen: 0,
92 Id: 0,
93 Expire: 0,
94 Key: key,
95 Data: make([]byte, 0),
96 }
97}
98
99func (m *DHTClientResultMsg) String() string {
100 return fmt.Sprintf("DHTClientResultMsg{Id:%d}", m.Id)
101}
102
103// Header returns the message header in a separate instance.
104func (msg *DHTClientResultMsg) Header() *MessageHeader {
105 return &MessageHeader{msg.MsgSize, msg.MsgType}
106}
diff --git a/src/gnunet/message/msg_gns.go b/src/gnunet/message/msg_gns.go
new file mode 100644
index 0000000..7ea7d3c
--- /dev/null
+++ b/src/gnunet/message/msg_gns.go
@@ -0,0 +1,128 @@
1package message
2
3import (
4 "fmt"
5
6 "github.com/bfix/gospel/logger"
7 "gnunet/enums"
8 "gnunet/util"
9)
10
11//----------------------------------------------------------------------
12// GNS_LOOKUP
13//----------------------------------------------------------------------
14
15// GNSLookupMsg
16type GNSLookupMsg struct {
17 MsgSize uint16 `order:"big"` // total size of message
18 MsgType uint16 `order:"big"` // GNS_LOOKUP (500)
19 Id uint32 `order:"big"` // Unique identifier for this request (for key collisions).
20 Zone []byte `size:"32"` // Zone that is to be used for lookup
21 Options uint16 `order:"big"` // Local options for where to look for results
22 Reserved uint16 `order:"big"` // Always 0
23 Type uint32 `order:"big"` // the type of record to look up
24 Name []byte `size:"*"` // zero-terminated name to look up
25}
26
27// NewGNSLookupMsg creates a new default message.
28func NewGNSLookupMsg() *GNSLookupMsg {
29 return &GNSLookupMsg{
30 MsgSize: 48, // record size with no name
31 MsgType: GNS_LOOKUP,
32 Id: 0,
33 Zone: make([]byte, 32),
34 Options: uint16(enums.GNS_LO_DEFAULT),
35 Reserved: 0,
36 Type: uint32(enums.GNS_TYPE_ANY),
37 Name: nil,
38 }
39}
40
41// SetName
42func (m *GNSLookupMsg) SetName(name string) {
43 m.Name = util.Clone(append([]byte(name), 0))
44 m.MsgSize = uint16(48 + len(m.Name))
45}
46
47// GetName
48func (m *GNSLookupMsg) GetName() string {
49 size := len(m.Name)
50 if m.Name[size-1] != 0 {
51 logger.Println(logger.WARN, "GNS_LOOKUP name not NULL-terminated")
52 } else {
53 size -= 1
54 }
55 return string(m.Name[:size])
56}
57
58// String
59func (m *GNSLookupMsg) String() string {
60 return fmt.Sprintf(
61 "GNSLookupMsg{Id=%d,Zone=%s,Options=%d,Type=%d,Name=%s}",
62 m.Id, util.EncodeBinaryToString(m.Zone),
63 m.Options, m.Type, m.GetName())
64}
65
66// Header returns the message header in a separate instance.
67func (msg *GNSLookupMsg) Header() *MessageHeader {
68 return &MessageHeader{msg.MsgSize, msg.MsgType}
69}
70
71//----------------------------------------------------------------------
72// GNS_LOOKUP_RESULT
73//----------------------------------------------------------------------
74
75type GNSResourceRecord struct {
76 Expires uint64 `order:"big"` // Expiration time for the record
77 Size uint32 `order:"big"` // Number of bytes in 'Data'
78 Type uint32 `order:"big"` // Type of the GNS/DNS record
79 Flags uint32 `order:"big"` // Flags for the record
80 Data []byte `size:"Size"` // Record data
81}
82
83func (r *GNSResourceRecord) String() string {
84 return fmt.Sprintf("GNSResourceRecord{Type=%s,Expire=%s,Flag=%d,Size=%d}",
85 enums.GNS_TYPE[int(r.Type)], util.Timestamp(r.Expires), r.Flags, r.Size)
86}
87
88// GNSLookupResultMsg
89type GNSLookupResultMsg struct {
90 MsgSize uint16 `order:"big"` // total size of message
91 MsgType uint16 `order:"big"` // GNS_LOOKUP_RESULT (501)
92 Id uint32 `order:"big"` // Unique identifier for this request (for key collisions).
93 Count uint32 `order:"big"` // The number of records contained in response
94 Records []*GNSResourceRecord `size:"Count"` // GNS resource records
95}
96
97// NewGNSLookupResultMsg
98func NewGNSLookupResultMsg(id uint32) *GNSLookupResultMsg {
99 return &GNSLookupResultMsg{
100 MsgSize: 12, // Empty result (no records)
101 MsgType: GNS_LOOKUP_RESULT,
102 Id: id,
103 Count: 0,
104 Records: make([]*GNSResourceRecord, 0),
105 }
106}
107
108// AddRecord
109func (m *GNSLookupResultMsg) AddRecord(rec *GNSResourceRecord) error {
110 recSize := 20 + int(rec.Size)
111 if int(m.MsgSize)+recSize > enums.GNS_MAX_BLOCK_SIZE {
112 return fmt.Errorf("gns.AddRecord(): MAX_BLOCK_SIZE reached")
113 }
114 m.Records = append(m.Records, rec)
115 m.MsgSize += uint16(recSize)
116 m.Count++
117 return nil
118}
119
120// String
121func (m *GNSLookupResultMsg) String() string {
122 return fmt.Sprintf("GNSLookupResultMsg{Id=%d,Count=%d}", m.Id, m.Count)
123}
124
125// Header returns the message header in a separate instance.
126func (msg *GNSLookupResultMsg) Header() *MessageHeader {
127 return &MessageHeader{msg.MsgSize, msg.MsgType}
128}
diff --git a/src/gnunet/message/msg_namecache.go b/src/gnunet/message/msg_namecache.go
new file mode 100644
index 0000000..421b625
--- /dev/null
+++ b/src/gnunet/message/msg_namecache.go
@@ -0,0 +1,86 @@
1package message
2
3import (
4 "encoding/hex"
5 "fmt"
6
7 //"github.com/bfix/gospel/logger"
8 "gnunet/crypto"
9 //"gnunet/enums"
10 "gnunet/util"
11)
12
13//----------------------------------------------------------------------
14// NAMECACHE_LOOKUP_BLOCK
15//----------------------------------------------------------------------
16
17// NamecacheLookupMsg
18type NamecacheLookupMsg struct {
19 MsgSize uint16 `order:"big"` // total size of message
20 MsgType uint16 `order:"big"` // NAMECACHE_LOOKUP_BLOCK (431)
21 Id uint32 `order:"big"` // Request Id
22 Query *crypto.HashCode // Query data
23}
24
25// NewNamecacheLookupMsg creates a new default message.
26func NewNamecacheLookupMsg(query *crypto.HashCode) *NamecacheLookupMsg {
27 if query == nil {
28 query = crypto.NewHashCode()
29 }
30 return &NamecacheLookupMsg{
31 MsgSize: 72,
32 MsgType: NAMECACHE_LOOKUP_BLOCK,
33 Id: 0,
34 Query: query,
35 }
36}
37
38// String
39func (m *NamecacheLookupMsg) String() string {
40 return fmt.Sprintf("NamecacheLookupMsg{Id=%d,Query=%s}",
41 m.Id, hex.EncodeToString(m.Query.Bits))
42}
43
44// Header returns the message header in a separate instance.
45func (msg *NamecacheLookupMsg) Header() *MessageHeader {
46 return &MessageHeader{msg.MsgSize, msg.MsgType}
47}
48
49//----------------------------------------------------------------------
50// NAMECACHE_LOOKUP_BLOCK_RESPONSE
51//----------------------------------------------------------------------
52
53// NamecacheLookupResultMsg
54type NamecacheLookupResultMsg struct {
55 MsgSize uint16 `order:"big"` // total size of message
56 MsgType uint16 `order:"big"` // NAMECACHE_LOOKUP_BLOCK_RESPONSE (432)
57 Id uint32 `order:"big"` // Request Id
58 Expire uint64 `order:"big"` // Expiration time
59 Signature []byte `size:"64"` // ECDSA signature
60 DerivedKey []byte `size:"32"` // Derived public key
61 EncData []byte `size:"*"` // Encrypted block data
62}
63
64// NewNamecacheLookupResultMsg creates a new default message.
65func NewNamecacheLookupResultMsg() *NamecacheLookupResultMsg {
66 return &NamecacheLookupResultMsg{
67 MsgSize: 112,
68 MsgType: NAMECACHE_LOOKUP_BLOCK_RESPONSE,
69 Id: 0,
70 Expire: 0,
71 Signature: make([]byte, 64),
72 DerivedKey: make([]byte, 32),
73 EncData: make([]byte, 0),
74 }
75}
76
77// String
78func (m *NamecacheLookupResultMsg) String() string {
79 return fmt.Sprintf("NamecacheLookupResultMsg{Id=%d,Expire=%s}",
80 m.Id, util.Timestamp(m.Expire))
81}
82
83// Header returns the message header in a separate instance.
84func (msg *NamecacheLookupResultMsg) Header() *MessageHeader {
85 return &MessageHeader{msg.MsgSize, msg.MsgType}
86}
diff --git a/src/gnunet/message/msg_transport.go b/src/gnunet/message/msg_transport.go
new file mode 100644
index 0000000..ec4e143
--- /dev/null
+++ b/src/gnunet/message/msg_transport.go
@@ -0,0 +1,440 @@
1package message
2
3import (
4 "fmt"
5 "time"
6
7 "github.com/bfix/gospel/crypto/ed25519"
8 "github.com/bfix/gospel/data"
9 "gnunet/enums"
10 "gnunet/util"
11)
12
13//----------------------------------------------------------------------
14// TRANSPORT_TCP_WELCOME
15//----------------------------------------------------------------------
16
17type TransportTcpWelcomeMsg struct {
18 MsgSize uint16 `order:"big"` // total size of message
19 MsgType uint16 `order:"big"` // TRANSPORT_TCP_WELCOME (61)
20 PeerID []byte `size:"32"` // Peer identity (EdDSA public key)
21}
22
23func NewTransportTcpWelcomeMsg(peerid []byte) *TransportTcpWelcomeMsg {
24 msg := &TransportTcpWelcomeMsg{
25 MsgSize: 36,
26 MsgType: TRANSPORT_TCP_WELCOME,
27 PeerID: make([]byte, 32),
28 }
29 if peerid != nil {
30 copy(msg.PeerID[:], peerid)
31 } else {
32 msg.MsgSize = 0
33 msg.MsgType = 0
34 }
35 return msg
36}
37
38func (m *TransportTcpWelcomeMsg) String() string {
39 return fmt.Sprintf("TransportTcpWelcomeMsg{'%s'}", util.EncodeBinaryToString(m.PeerID))
40}
41
42// Header returns the message header in a separate instance.
43func (msg *TransportTcpWelcomeMsg) Header() *MessageHeader {
44 return &MessageHeader{msg.MsgSize, msg.MsgType}
45}
46
47//----------------------------------------------------------------------
48// TRANSPORT_PONG
49//
50// Message used to validate a HELLO. The challenge is included in the
51// confirmation to make matching of replies to requests possible. The
52// signature signs our public key, an expiration time and our address.<p>
53//
54// This message is followed by our transport address that the PING tried
55// to confirm (if we liked it). The address can be empty (zero bytes)
56// if the PING had not address either (and we received the request via
57// a connection that we initiated).
58//----------------------------------------------------------------------
59
60type SignedAddress struct {
61 SignLength uint32 `order:"big"` // Length of signed block
62 Purpose uint32 `order:"big"` // SIG_TRANSPORT_PONG_OWN
63 ExpireOn uint64 `order:"big"` // usec epoch
64 AddrSize uint32 `order:"big"` // size of address
65 Address []byte `size:"AddrSize"` // address
66}
67
68func NewSignedAddress(a *util.Address) *SignedAddress {
69 // serialize address
70 addrData, _ := data.Marshal(a)
71 alen := len(addrData)
72 addr := &SignedAddress{
73 SignLength: uint32(alen + 20),
74 Purpose: enums.SIG_TRANSPORT_PONG_OWN,
75 ExpireOn: util.GetAbsoluteTimeOffset(12 * time.Hour),
76 AddrSize: uint32(alen),
77 Address: make([]byte, alen),
78 }
79 copy(addr.Address, addrData)
80 return addr
81}
82
83type TransportPongMsg struct {
84 MsgSize uint16 `order:"big"` // total size of message
85 MsgType uint16 `order:"big"` // TRANSPORT_PING (372)
86 Challenge uint32 // Challenge code (to ensure fresh reply)
87 Signature []byte `size:"64"` // Signature of address
88 SignedBlock *SignedAddress // signed block of data
89}
90
91func NewTransportPongMsg(challenge uint32, a *util.Address) *TransportPongMsg {
92 m := &TransportPongMsg{
93 MsgSize: 72,
94 MsgType: TRANSPORT_PONG,
95 Challenge: challenge,
96 Signature: make([]byte, 64),
97 SignedBlock: new(SignedAddress),
98 }
99 if a != nil {
100 sa := NewSignedAddress(a)
101 m.MsgSize += uint16(sa.SignLength)
102 m.SignedBlock = sa
103 }
104 return m
105}
106
107func (m *TransportPongMsg) String() string {
108 a := new(util.Address)
109 if err := data.Unmarshal(a, m.SignedBlock.Address); err == nil {
110 return fmt.Sprintf("TransportPongMsg{%s,%d}", a, m.Challenge)
111 }
112 return fmt.Sprintf("TransportPongMsg{<unkown>,%d}", m.Challenge)
113}
114
115// Header returns the message header in a separate instance.
116func (msg *TransportPongMsg) Header() *MessageHeader {
117 return &MessageHeader{msg.MsgSize, msg.MsgType}
118}
119
120func (m *TransportPongMsg) Sign(prv *ed25519.PrivateKey) error {
121 data, err := data.Marshal(m.SignedBlock)
122 if err != nil {
123 fmt.Printf("Sign: %s\n", err)
124 return err
125 }
126 sig, err := prv.EdSign(data)
127 if err != nil {
128 fmt.Printf("Sign: %s\n", err)
129 return err
130 }
131 copy(m.Signature, sig.Bytes())
132 return nil
133}
134
135func (m *TransportPongMsg) Verify(pub *ed25519.PublicKey) (bool, error) {
136 data, err := data.Marshal(m.SignedBlock)
137 if err != nil {
138 return false, err
139 }
140 sig, err := ed25519.NewEdSignatureFromBytes(m.Signature)
141 if err != nil {
142 return false, err
143 }
144 return pub.EdVerify(data, sig)
145}
146
147//----------------------------------------------------------------------
148// TRANSPORT_PING
149//
150// Message used to ask a peer to validate receipt (to check an address
151// from a HELLO). Followed by the address we are trying to validate,
152// or an empty address if we are just sending a PING to confirm that a
153// connection which the receiver (of the PING) initiated is still valid.
154//----------------------------------------------------------------------
155
156type TransportPingMsg struct {
157 MsgSize uint16 `order:"big"` // total size of message
158 MsgType uint16 `order:"big"` // TRANSPORT_PING (372)
159 Challenge uint32 // Challenge code (to ensure fresh reply)
160 Target []byte `size:"32"` // EdDSA public key (long-term) of target peer
161 Address []byte `size:"*"` // encoded address
162}
163
164func NewTransportPingMsg(target []byte, a *util.Address) *TransportPingMsg {
165 m := &TransportPingMsg{
166 MsgSize: uint16(40),
167 MsgType: TRANSPORT_PING,
168 Challenge: util.RndUInt32(),
169 Target: make([]byte, 32),
170 Address: nil,
171 }
172 if target != nil {
173 copy(m.Target, target)
174 }
175 if a != nil {
176 if addrData, err := data.Marshal(a); err == nil {
177 m.Address = addrData
178 m.MsgSize += uint16(len(addrData))
179 }
180 }
181 return m
182}
183
184func (m *TransportPingMsg) String() string {
185 a := new(util.Address)
186 data.Unmarshal(a, m.Address)
187 return fmt.Sprintf("TransportPingMsg{%s,%s,%d}",
188 util.EncodeBinaryToString(m.Target), a, m.Challenge)
189}
190
191// Header returns the message header in a separate instance.
192func (msg *TransportPingMsg) Header() *MessageHeader {
193 return &MessageHeader{msg.MsgSize, msg.MsgType}
194}
195
196//----------------------------------------------------------------------
197// HELLO
198//
199// A HELLO message is used to exchange information about
200// transports with other peers. This struct is always
201// followed by the actual network addresses which have
202// the format:
203//
204// 1) transport-name (0-terminated)
205// 2) address-length (uint16_t, network byte order)
206// 3) address expiration
207// 4) address (address-length bytes)
208//----------------------------------------------------------------------
209
210type HelloAddress struct {
211 Transport string // Name of transport
212 AddrSize uint16 `order:"big"` // Size of address entry
213 ExpireOn uint64 `order:"big"` // Expiry date
214 Address []byte `size:"AddrSize"` // Address specification
215}
216
217func NewAddress(a *util.Address) *HelloAddress {
218 addr := &HelloAddress{
219 Transport: a.Transport,
220 AddrSize: uint16(len(a.Address)),
221 ExpireOn: util.GetAbsoluteTimeOffset(12 * time.Hour),
222 Address: make([]byte, len(a.Address)),
223 }
224 copy(addr.Address, a.Address)
225 return addr
226}
227
228func (a *HelloAddress) String() string {
229 return fmt.Sprintf("Address{%s,%s}", util.AddressString(a.Transport, a.Address), util.Timestamp(a.ExpireOn))
230}
231
232type HelloMsg struct {
233 MsgSize uint16 `order:"big"` // total size of message
234 MsgType uint16 `order:"big"` // HELLO (17)
235 FriendOnly uint32 `order:"big"` // =1: do not gossip this HELLO
236 PeerID []byte `size:"32"` // EdDSA public key (long-term)
237 Addresses []*HelloAddress `size:"*"` // List of end-point addressess
238}
239
240func NewHelloMsg(peerid []byte) *HelloMsg {
241 m := &HelloMsg{
242 MsgSize: 40,
243 MsgType: HELLO,
244 FriendOnly: 0,
245 PeerID: make([]byte, 32),
246 Addresses: make([]*HelloAddress, 0),
247 }
248 if peerid != nil {
249 copy(m.PeerID, peerid)
250 }
251 return m
252}
253
254func (m *HelloMsg) String() string {
255 return fmt.Sprintf("HelloMsg{%s,%d,%v}", util.EncodeBinaryToString(m.PeerID), m.FriendOnly, m.Addresses)
256}
257
258func (m *HelloMsg) AddAddress(a *HelloAddress) {
259 m.Addresses = append(m.Addresses, a)
260 m.MsgSize += uint16(len(a.Transport)) + a.AddrSize + 11
261}
262
263// Header returns the message header in a separate instance.
264func (msg *HelloMsg) Header() *MessageHeader {
265 return &MessageHeader{msg.MsgSize, msg.MsgType}
266}
267
268//----------------------------------------------------------------------
269// TRANSPORT_SESSION_ACK
270//----------------------------------------------------------------------
271
272type SessionAckMsg struct {
273 MsgSize uint16 `order:"big"` // total size of message
274 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_ACK (377)
275}
276
277func NewSessionAckMsg() *SessionAckMsg {
278 return &SessionAckMsg{
279 MsgSize: 16,
280 MsgType: TRANSPORT_SESSION_ACK,
281 }
282}
283
284func (m *SessionAckMsg) String() string {
285 return "SessionAck{}"
286}
287
288// Header returns the message header in a separate instance.
289func (msg *SessionAckMsg) Header() *MessageHeader {
290 return &MessageHeader{msg.MsgSize, msg.MsgType}
291}
292
293//----------------------------------------------------------------------
294// TRANSPORT_SESSION_SYN
295//----------------------------------------------------------------------
296
297type SessionSynMsg struct {
298 MsgSize uint16 `order:"big"` // total size of message
299 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_SYN (375)
300 Reserved uint32 `order:"big"` // reserved (=0)
301 Timestamp uint64 `order:"big"` // usec epoch
302}
303
304func NewSessionSynMsg(t uint64) *SessionSynMsg {
305 if t == 0 {
306 t = util.GetAbsoluteTimeNow()
307 }
308 return &SessionSynMsg{
309 MsgSize: 16,
310 MsgType: TRANSPORT_SESSION_SYN,
311 Reserved: 0,
312 Timestamp: t,
313 }
314}
315
316func (m *SessionSynMsg) String() string {
317 return fmt.Sprintf("SessionSyn{%s}", util.Timestamp(m.Timestamp))
318}
319
320// Header returns the message header in a separate instance.
321func (msg *SessionSynMsg) Header() *MessageHeader {
322 return &MessageHeader{msg.MsgSize, msg.MsgType}
323}
324
325//----------------------------------------------------------------------
326// TRANSPORT_SESSION_SYN_ACK
327//----------------------------------------------------------------------
328
329type SessionSynAckMsg struct {
330 MsgSize uint16 `order:"big"` // total size of message
331 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_SYN_ACK (376)
332 Reserved uint32 `order:"big"` // reserved (=0)
333 Timestamp uint64 `order:"big"` // usec epoch
334}
335
336func NewSessionSynAckMsg(t uint64) *SessionSynAckMsg {
337 if t == 0 {
338 t = util.GetAbsoluteTimeNow()
339 }
340 return &SessionSynAckMsg{
341 MsgSize: 16,
342 MsgType: TRANSPORT_SESSION_SYN_ACK,
343 Reserved: 0,
344 Timestamp: t,
345 }
346}
347
348func (m *SessionSynAckMsg) String() string {
349 return fmt.Sprintf("SessionSynAck{%s}", util.Timestamp(m.Timestamp))
350}
351
352// Header returns the message header in a separate instance.
353func (msg *SessionSynAckMsg) Header() *MessageHeader {
354 return &MessageHeader{msg.MsgSize, msg.MsgType}
355}
356
357//----------------------------------------------------------------------
358// TRANSPORT_SESSION_QUOTA
359//----------------------------------------------------------------------
360
361type SessionQuotaMsg struct {
362 MsgSize uint16 `order:"big"` // total size of message
363 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_QUOTA (379)
364 Quota uint32 `order:"big"` // Quota in bytes per second
365}
366
367func NewSessionQuotaMsg(quota uint32) *SessionQuotaMsg {
368 m := new(SessionQuotaMsg)
369 if quota > 0 {
370 m.MsgSize = 8
371 m.MsgType = TRANSPORT_SESSION_QUOTA
372 m.Quota = quota
373 }
374 return m
375}
376
377func (m *SessionQuotaMsg) String() string {
378 return fmt.Sprintf("SessionQuotaMsg{%sB/s}", util.Scale1024(uint64(m.Quota)))
379}
380
381// Header returns the message header in a separate instance.
382func (msg *SessionQuotaMsg) Header() *MessageHeader {
383 return &MessageHeader{msg.MsgSize, msg.MsgType}
384}
385
386//----------------------------------------------------------------------
387// TRANSPORT_SESSION_KEEPALIVE_RESPONSE
388//----------------------------------------------------------------------
389
390type SessionKeepAliveRespMsg struct {
391 MsgSize uint16 `order:"big"` // total size of message
392 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_KEEPALIVE_RESPONSE (382)
393 Nonce uint32
394}
395
396func NewSessionKeepAliveRespMsg(nonce uint32) *SessionKeepAliveRespMsg {
397 m := &SessionKeepAliveRespMsg{
398 MsgSize: 8,
399 MsgType: TRANSPORT_SESSION_KEEPALIVE_RESPONSE,
400 Nonce: nonce,
401 }
402 return m
403}
404
405func (m *SessionKeepAliveRespMsg) String() string {
406 return fmt.Sprintf("SessionKeepAliveRespMsg{%d}", m.Nonce)
407}
408
409// Header returns the message header in a separate instance.
410func (msg *SessionKeepAliveRespMsg) Header() *MessageHeader {
411 return &MessageHeader{msg.MsgSize, msg.MsgType}
412}
413
414//----------------------------------------------------------------------
415// TRANSPORT_SESSION_KEEPALIVE
416//----------------------------------------------------------------------
417
418type SessionKeepAliveMsg struct {
419 MsgSize uint16 `order:"big"` // total size of message
420 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_KEEPALIVE (381)
421 Nonce uint32
422}
423
424func NewSessionKeepAliveMsg() *SessionKeepAliveMsg {
425 m := &SessionKeepAliveMsg{
426 MsgSize: 8,
427 MsgType: TRANSPORT_SESSION_KEEPALIVE,
428 Nonce: util.RndUInt32(),
429 }
430 return m
431}
432
433func (m *SessionKeepAliveMsg) String() string {
434 return fmt.Sprintf("SessionKeepAliveMsg{%d}", m.Nonce)
435}
436
437// Header returns the message header in a separate instance.
438func (msg *SessionKeepAliveMsg) Header() *MessageHeader {
439 return &MessageHeader{msg.MsgSize, msg.MsgType}
440}
diff --git a/src/gnunet/message/types.go b/src/gnunet/message/types.go
new file mode 100644
index 0000000..e3ab9b4
--- /dev/null
+++ b/src/gnunet/message/types.go
@@ -0,0 +1,817 @@
1package message
2
3// GNUnet message types
4const (
5 TEST = 1 // Test if service is online (deprecated)
6 DUMMY = 2 // Dummy messages for testing / benchmarking
7 DUMMY2 = 3 // Another dummy messages for testing / benchmarking
8
9 //------------------------------------------------------------------
10 // RESOLVER message types
11 //------------------------------------------------------------------
12
13 RESOLVER_REQUEST = 4 // Request DNS resolution
14 RESOLVER_RESPONSE = 5 // Response to a DNS resolution request
15
16 //------------------------------------------------------------------
17 // AGPL source code download
18 //------------------------------------------------------------------
19
20 REQUEST_AGPL = 6 // Message to request source code link
21 RESPONSE_AGPL = 7 // Source code link
22
23 //------------------------------------------------------------------
24 // ARM message types
25 //------------------------------------------------------------------
26
27 ARM_START = 8 // Request to ARM to start a service
28 ARM_STOP = 9 // Request to ARM to stop a service
29 ARM_RESULT = 10 // Response from ARM
30 ARM_STATUS = 11 // Status update from ARM
31 ARM_LIST = 12 // Request to ARM to list all currently running services
32 ARM_LIST_RESULT = 13 // Response from ARM for listing currently running services
33 ARM_MONITOR = 14 // Request to ARM to notify client of service status changes
34 ARM_TEST = 15 // Test if ARM service is online
35
36 //------------------------------------------------------------------
37 // HELLO message types
38 //------------------------------------------------------------------
39
40 HELLO_LEGACY = 16 // Deprecated HELLO message
41 HELLO = 17 // HELLO message with friend_only flag
42
43 //------------------------------------------------------------------
44 // FRAGMENTATION message types
45 //------------------------------------------------------------------
46
47 FRAGMENT = 18 // FRAGMENT of a larger message
48 FRAGMENT_ACK = 19 // Acknowledgement of a FRAGMENT of a larger message
49
50 //------------------------------------------------------------------
51 // Transport-WLAN message types
52 //------------------------------------------------------------------
53
54 WLAN_DATA_TO_HELPER = 39 // Type of data messages from the plugin to the gnunet-wlan-helper
55 WLAN_DATA_FROM_HELPER = 40 // Type of data messages from the gnunet-wlan-helper to the plugin
56 WLAN_HELPER_CONTROL = 41 // Control message between the gnunet-wlan-helper and the daemon (with the MAC)
57 WLAN_ADVERTISEMENT = 42 // Type of messages for advertisement over wlan
58 WLAN_DATA = 43 // Type of messages for data over the wlan
59
60 //------------------------------------------------------------------
61 // Transport-DV message types
62 //------------------------------------------------------------------
63
64 DV_RECV = 44 // DV service to DV Plugin message
65 DV_SEND = 45 // DV Plugin to DV service message
66 DV_SEND_ACK = 46 // Confirmation or failure of a DV_SEND message
67 DV_ROUTE = 47 // P2P DV message encapsulating some real message
68 DV_START = 48 // DV Plugin to DV service message, indicating startup.
69 DV_CONNECT = 49 // P2P DV message telling plugin that a peer connected
70 DV_DISCONNECT = 50 // P2P DV message telling plugin that a peer disconnected
71 DV_SEND_NACK = 51 // P2P DV message telling plugin that a message transmission failed (negative ACK)
72 DV_DISTANCE_CHANGED = 52 // P2P DV message telling plugin that our distance to a peer changed
73 DV_BOX = 53 // DV message box for boxing multiple messages.
74 TRANSPORT_XU_MESSAGE = 55 // Experimental message type.
75
76 //------------------------------------------------------------------
77 // Transport-UDP message types
78 //------------------------------------------------------------------
79
80 TRANSPORT_UDP_MESSAGE = 56 // Normal UDP message type.
81 TRANSPORT_UDP_ACK = 57 // UDP ACK.
82
83 //------------------------------------------------------------------
84 // Transport-TCP message types
85 //------------------------------------------------------------------
86
87 TRANSPORT_TCP_NAT_PROBE = 60 // TCP NAT probe message
88 TRANSPORT_TCP_WELCOME = 61 // Welcome message between TCP transports.
89 TRANSPORT_ATS = 62 // Message to force transport to update bandwidth assignment (LEGACY)
90
91 //------------------------------------------------------------------
92 // NAT message types
93 //------------------------------------------------------------------
94
95 NAT_TEST = 63 // Message to ask NAT server to perform traversal test
96
97 //------------------------------------------------------------------
98 // CORE message types
99 //------------------------------------------------------------------
100
101 CORE_INIT = 64 // Initial setup message from core client to core.
102 CORE_INIT_REPLY = 65 // Response from core to core client to INIT message.
103 CORE_NOTIFY_CONNECT = 67 // Notify clients about new peer-to-peer connections (triggered after key exchange).
104 CORE_NOTIFY_DISCONNECT = 68 // Notify clients about peer disconnecting.
105 CORE_NOTIFY_STATUS_CHANGE = 69 // Notify clients about peer status change.
106 CORE_NOTIFY_INBOUND = 70 // Notify clients about incoming P2P messages.
107 CORE_NOTIFY_OUTBOUND = 71 // Notify clients about outgoing P2P transmissions.
108 CORE_SEND_REQUEST = 74 // Request from client to transmit message.
109 CORE_SEND_READY = 75 // Confirmation from core that message can now be sent
110 CORE_SEND = 76 // Client with message to transmit (after SEND_READY confirmation was received).
111 CORE_MONITOR_PEERS = 78 // Request for connection monitoring from CORE service.
112 CORE_MONITOR_NOTIFY = 79 // Reply for monitor by CORE service.
113 CORE_ENCRYPTED_MESSAGE = 82 // Encapsulation for an encrypted message between peers.
114 CORE_PING = 83 // Check that other peer is alive (challenge).
115 CORE_PONG = 84 // Confirmation that other peer is alive.
116 CORE_HANGUP = 85 // Request by the other peer to terminate the connection.
117 CORE_COMPRESSED_TYPE_MAP = 86 // gzip-compressed type map of the sender
118 CORE_BINARY_TYPE_MAP = 87 // uncompressed type map of the sender
119 CORE_EPHEMERAL_KEY = 88 // Session key exchange between peers.
120 CORE_CONFIRM_TYPE_MAP = 89 // Other peer confirms having received the type map
121
122 //------------------------------------------------------------------
123 // DATASTORE message types
124 //------------------------------------------------------------------
125
126 DATASTORE_RESERVE = 92 // Message sent by datastore client on join.
127 DATASTORE_RELEASE_RESERVE = 93 // Message sent by datastore client on join.
128 DATASTORE_STATUS = 94 // Message sent by datastore to client informing about status processing a request (in response to RESERVE, RELEASE_RESERVE, PUT, UPDATE and REMOVE requests).
129 DATASTORE_PUT = 95 // Message sent by datastore client to store data.
130 DATASTORE_GET = 97 // Message sent by datastore client to get data.
131 DATASTORE_GET_REPLICATION = 98 // Message sent by datastore client to get random data.
132 DATASTORE_GET_ZERO_ANONYMITY = 99 // Message sent by datastore client to get random data.
133 DATASTORE_DATA = 100 // Message sent by datastore to client providing requested data (in response to GET or GET_RANDOM request).
134 DATASTORE_DATA_END = 101 // Message sent by datastore to client signaling end of matching data. This message will also be sent for "GET_RANDOM", even though "GET_RANDOM" returns at most one data item.
135 DATASTORE_REMOVE = 102 // Message sent by datastore client to remove data.
136 DATASTORE_DROP = 103 // Message sent by datastore client to drop the database.
137 DATASTORE_GET_KEY = 104 // Message sent by datastore client to get data by key.
138
139 //------------------------------------------------------------------
140 // FS message types
141 //------------------------------------------------------------------
142
143 FS_REQUEST_LOC_SIGN = 126 // Message sent by fs client to request LOC signature.
144 FS_REQUEST_LOC_SIGNATURE = 127 // Reply sent by fs service with LOC signature.
145 FS_INDEX_START = 128 // Message sent by fs client to start indexing.
146 FS_INDEX_START_OK = 129 // Affirmative response to a request for start indexing.
147 FS_INDEX_START_FAILED = 130 // Response to a request for start indexing that refuses.
148 FS_INDEX_LIST_GET = 131 // Request from client for list of indexed files.
149 FS_INDEX_LIST_ENTRY = 132 // Reply to client with an indexed file name.
150 FS_INDEX_LIST_END = 133 // Reply to client indicating end of list.
151 FS_UNINDEX = 134 // Request from client to unindex a file.
152 FS_UNINDEX_OK = 135 // Reply to client indicating unindex receipt.
153 FS_START_SEARCH = 136 // Client asks FS service to start a (keyword) search.
154 FS_GET = 137 // P2P request for content (one FS to another).
155 FS_PUT = 138 // P2P response with content or active migration of content. Also used between the service and clients (in response to #FS_START_SEARCH).
156 FS_MIGRATION_STOP = 139 // Peer asks us to stop migrating content towards it for a while.
157 FS_CADET_QUERY = 140 // P2P request for content (one FS to another via a cadet).
158 FS_CADET_REPLY = 141 // P2P answer for content (one FS to another via a cadet).
159
160 //------------------------------------------------------------------
161 // DHT message types
162 //------------------------------------------------------------------
163
164 DHT_CLIENT_PUT = 142 // Client wants to store item in DHT.
165 DHT_CLIENT_GET = 143 // Client wants to lookup item in DHT.
166 DHT_CLIENT_GET_STOP = 144 // Client wants to stop search in DHT.
167 DHT_CLIENT_RESULT = 145 // Service returns result to client.
168 DHT_P2P_PUT = 146 // Peer is storing data in DHT.
169 DHT_P2P_GET = 147 // Peer tries to find data in DHT.
170 DHT_P2P_RESULT = 148 // Data is returned to peer from DHT.
171 DHT_MONITOR_GET = 149 // Receive information about transiting GETs
172 DHT_MONITOR_GET_RESP = 150 // Receive information about transiting GET responses
173 DHT_MONITOR_PUT = 151 // Receive information about transiting PUTs
174 DHT_MONITOR_PUT_RESP = 152 // Receive information about transiting PUT responses (TODO)
175 DHT_MONITOR_START = 153 // Request information about transiting messages
176 DHT_MONITOR_STOP = 154 // Stop information about transiting messages
177 DHT_CLIENT_GET_RESULTS_KNOWN = 156 // Certain results are already known to the client, filter those.
178
179 //------------------------------------------------------------------
180 // HOSTLIST message types
181 //------------------------------------------------------------------
182
183 HOSTLIST_ADVERTISEMENT = 160 // Hostlist advertisement message
184
185 //------------------------------------------------------------------
186 // STATISTICS message types
187 //------------------------------------------------------------------
188
189 STATISTICS_SET = 168 // Set a statistical value.
190 STATISTICS_GET = 169 // Get a statistical value(s).
191 STATISTICS_VALUE = 170 // Response to a STATISTICS_GET message (with value).
192 STATISTICS_END = 171 // Response to a STATISTICS_GET message (end of value stream).
193 STATISTICS_WATCH = 172 // Watch changes to a statistical value. Message format is the same as for GET, except that the subsystem and entry name must be given.
194 STATISTICS_WATCH_VALUE = 173 // Changes to a watched value.
195 STATISTICS_DISCONNECT = 174 // Client is done sending service requests and will now disconnect.
196 STATISTICS_DISCONNECT_CONFIRM = 175 // Service confirms disconnect and that it is done processing all requests from the client.
197
198 //------------------------------------------------------------------
199 // VPN message types
200 //------------------------------------------------------------------
201
202 VPN_HELPER = 185 // Type of messages between the gnunet-vpn-helper and the daemon
203 VPN_ICMP_TO_SERVICE = 190 // ICMP packet for a service.
204 VPN_ICMP_TO_INTERNET = 191 // ICMP packet for the Internet.
205 VPN_ICMP_TO_VPN = 192 // ICMP packet for the VPN
206 VPN_DNS_TO_INTERNET = 193 // DNS request for a DNS exit service.
207 VPN_DNS_FROM_INTERNET = 194 // DNS reply from a DNS exit service.
208 VPN_TCP_TO_SERVICE_START = 195 // TCP packet for a service.
209 VPN_TCP_TO_INTERNET_START = 196 // TCP packet for the Internet.
210 VPN_TCP_DATA_TO_EXIT = 197 // TCP packet of an established connection.
211 VPN_TCP_DATA_TO_VPN = 198 // TCP packet of an established connection.
212 VPN_UDP_TO_SERVICE = 199 // UDP packet for a service.
213 VPN_UDP_TO_INTERNET = 200 // UDP packet for the Internet.
214 VPN_UDP_REPLY = 201 // UDP packet from a remote host
215 VPN_CLIENT_REDIRECT_TO_IP = 202 // Client asks VPN service to setup an IP to redirect traffic via an exit node to some global IP address.
216 VPN_CLIENT_REDIRECT_TO_SERVICE = 203 // Client asks VPN service to setup an IP to redirect traffic to some peer offering a service.
217 VPN_CLIENT_USE_IP = 204 // VPN service responds to client with an IP to use for the requested redirection.
218
219 //------------------------------------------------------------------
220 // VPN-DNS message types
221 //------------------------------------------------------------------
222
223 DNS_CLIENT_INIT = 211 // Initial message from client to DNS service for registration.
224 DNS_CLIENT_REQUEST = 212 // Type of messages between the gnunet-helper-dns and the service
225 DNS_CLIENT_RESPONSE = 213 // Type of messages between the gnunet-helper-dns and the service
226 DNS_HELPER = 214 // Type of messages between the gnunet-helper-dns and the service
227
228 //------------------------------------------------------------------
229 // CHAT message types START
230 //------------------------------------------------------------------
231
232 CHAT_JOIN_REQUEST = 300 // Message sent from client to join a chat room.
233 CHAT_JOIN_NOTIFICATION = 301 // Message sent to client to indicate joining of another room member.
234 CHAT_LEAVE_NOTIFICATION = 302 // Message sent to client to indicate leaving of another room member.
235 CHAT_MESSAGE_NOTIFICATION = 303 // Notification sent by service to client indicating that we've received a chat message.
236 CHAT_TRANSMIT_REQUEST = 304 // Request sent by client to transmit a chat message to another room members.
237 CHAT_CONFIRMATION_RECEIPT = 305 // Receipt sent from a message receiver to the service to confirm delivery of a chat message.
238 CHAT_CONFIRMATION_NOTIFICATION = 306 // Notification sent from the service to the original sender to acknowledge delivery of a chat message.
239 CHAT_P2P_JOIN_NOTIFICATION = 307 // P2P message sent to indicate joining of another room member.
240 CHAT_P2P_LEAVE_NOTIFICATION = 308 // P2P message sent to indicate leaving of another room member.
241 CHAT_P2P_SYNC_REQUEST = 309 // P2P message sent to a newly connected peer to request its known clients in order to synchronize room members.
242 CHAT_P2P_MESSAGE_NOTIFICATION = 310 // Notification sent from one peer to another to indicate that we have received a chat message.
243 CHAT_P2P_CONFIRMATION_RECEIPT = 311 // P2P receipt confirming delivery of a chat message.
244
245 //------------------------------------------------------------------
246 // NSE (network size estimation) message types
247 //------------------------------------------------------------------
248
249 NSE_START = 321 // client->service message indicating start
250 NSE_P2P_FLOOD = 322 // P2P message sent from nearest peer
251 NSE_ESTIMATE = 323 // service->client message indicating
252
253 //------------------------------------------------------------------
254 // PEERINFO message types
255 //------------------------------------------------------------------
256
257 PEERINFO_GET = 330 // Request update and listing of a peer
258 PEERINFO_GET_ALL = 331 // Request update and listing of all peers
259 PEERINFO_INFO = 332 // Information about one of the peers
260 PEERINFO_INFO_END = 333 // End of information about other peers
261 PEERINFO_NOTIFY = 334 // Start notifying this client about changes
262
263 //------------------------------------------------------------------
264 // ATS message types
265 //------------------------------------------------------------------
266
267 ATS_START = 340 // Type of the 'struct ClientStartMessage' sent by clients to ATS to identify the type of the client.
268 ATS_REQUEST_ADDRESS = 341 // Type of the 'struct RequestAddressMessage' sent by clients to request an address to help connect.
269 ATS_REQUEST_ADDRESS_CANCEL = 342 // Type of the 'struct RequestAddressMessage' sent by clients to request an address to help connect.
270 ATS_ADDRESS_UPDATE = 343 // Type of the 'struct AddressUpdateMessage' sent by clients to ATS to inform ATS about performance changes.
271 ATS_ADDRESS_DESTROYED = 344 // Type of the 'struct AddressDestroyedMessage' sent by clients to ATS to inform ATS about an address being unavailable.
272 ATS_ADDRESS_SUGGESTION = 345 // Type of the 'struct AddressSuggestionMessage' sent by ATS to clients to suggest switching to a different address.
273 ATS_PEER_INFORMATION = 346 // Type of the 'struct PeerInformationMessage' sent by ATS to clients to inform about QoS for a particular connection.
274 ATS_RESERVATION_REQUEST = 347 // Type of the 'struct ReservationRequestMessage' sent by clients to ATS to ask for inbound bandwidth reservations.
275 ATS_RESERVATION_RESULT = 348 // Type of the 'struct ReservationResultMessage' sent by ATS to clients in response to a reservation request.
276 ATS_PREFERENCE_CHANGE = 349 // Type of the 'struct ChangePreferenceMessage' sent by clients to ATS to ask for allocation preference changes.
277 ATS_SESSION_RELEASE = 350 // Type of the 'struct SessionReleaseMessage' sent by ATS to client to confirm that a session ID was destroyed.
278 ATS_ADDRESS_ADD = 353 // Type of the 'struct AddressUpdateMessage' sent by client to ATS to add a new address
279 ATS_ADDRESSLIST_REQUEST = 354 // Type of the 'struct AddressListRequestMessage' sent by client to ATS to request information about addresses
280 ATS_ADDRESSLIST_RESPONSE = 355 // Type of the 'struct AddressListResponseMessage' sent by ATS to client with information about addresses
281 ATS_PREFERENCE_FEEDBACK = 356 // Type of the 'struct ChangePreferenceMessage' sent by clients to ATS to ask for allocation preference changes.
282
283 //------------------------------------------------------------------
284 // TRANSPORT message types
285 //------------------------------------------------------------------
286
287 TRANSPORT_START = 360 // Message from the core saying that the transport server should start giving it messages. This should automatically trigger the transmission of a HELLO message.
288 TRANSPORT_CONNECT = 361 // Message from TRANSPORT notifying about a client that connected to us.
289 TRANSPORT_DISCONNECT = 362 // Message from TRANSPORT notifying about a client that disconnected from us.
290 TRANSPORT_SEND = 363 // Request to TRANSPORT to transmit a message.
291 TRANSPORT_SEND_OK = 364 // Confirmation from TRANSPORT that message for transmission has been queued (and that the next message to this peer can now be passed to the service). Note that this confirmation does NOT imply that the message was fully transmitted.
292 TRANSPORT_RECV = 365 // Message from TRANSPORT notifying about a message that was received.
293 TRANSPORT_SET_QUOTA = 366 // Message telling transport to limit its receive rate.
294 TRANSPORT_ADDRESS_TO_STRING = 367 // Request to look addresses of peers in server.
295 TRANSPORT_ADDRESS_TO_STRING_REPLY = 368 // Response to the address lookup request.
296 TRANSPORT_BLACKLIST_INIT = 369 // Register a client that wants to do blacklisting.
297 TRANSPORT_BLACKLIST_QUERY = 370 // Query to a blacklisting client (is this peer blacklisted)?
298 TRANSPORT_BLACKLIST_REPLY = 371 // Reply from blacklisting client (answer to blacklist query).
299 TRANSPORT_PING = 372 // Transport PING message
300 TRANSPORT_PONG = 373 // Transport PONG message
301 TRANSPORT_SESSION_SYN = 375 // Transport SYN message exchanged between transport services to indicate that a session should be marked as 'connected'.
302 TRANSPORT_SESSION_SYN_ACK = 376 // Transport SYN_ACK message exchanged between transport services to indicate that a SYN message was accepted
303 TRANSPORT_SESSION_ACK = 377 // Transport ACK message exchanged between transport services to indicate that a SYN_ACK message was accepted
304 TRANSPORT_SESSION_DISCONNECT = 378 // Transport DISCONNECT message exchanged between transport services to indicate that a connection should be dropped.
305 TRANSPORT_SESSION_QUOTA = 379 // Message exchanged between transport services to indicate that the sender should limit its transmission rate to the indicated quota.
306 TRANSPORT_MONITOR_PEER_REQUEST = 380 // Request to monitor addresses used by a peer or all peers.
307 TRANSPORT_SESSION_KEEPALIVE = 381 // Message send by a peer to notify the other to keep the session alive and measure latency in a regular interval
308 TRANSPORT_SESSION_KEEPALIVE_RESPONSE = 382 // Response to a #TRANSPORT_SESSION_KEEPALIVE message to measure latency in a regular interval
309 TRANSPORT_MONITOR_PEER_RESPONSE = 383 // Response to #TRANSPORT_MONITOR_PEER_REQUEST request to iterate over all known addresses.
310 TRANSPORT_BROADCAST_BEACON = 384 // Message send by a peer to notify the other to keep the session alive.
311 TRANSPORT_TRAFFIC_METRIC = 385 // Message containing traffic metrics for transport service
312 TRANSPORT_MONITOR_PLUGIN_START = 388 // Request to start monitoring the connection state of plugins.
313 TRANSPORT_MONITOR_PLUGIN_EVENT = 389 // Monitoring event about the connection state of plugins, generated in response to a subscription initiated via #TRANSPORT_MONITOR_PLUGIN_START
314 TRANSPORT_MONITOR_PLUGIN_SYNC = 390 // Monitoring event notifying client that the initial iteration is now completed and we are in sync with the state of the subsystem.
315 TRANSPORT_MONITOR_PEER_RESPONSE_END = 391 // terminating list of replies.
316
317 //------------------------------------------------------------------
318 // FS-PUBLISH-HELPER IPC Messages
319 //------------------------------------------------------------------
320
321 FS_PUBLISH_HELPER_PROGRESS_FILE = 420 // Progress information from the helper: found a file
322 FS_PUBLISH_HELPER_PROGRESS_DIRECTORY = 421 // Progress information from the helper: found a directory
323 FS_PUBLISH_HELPER_ERROR = 422 // Error signal from the helper.
324 FS_PUBLISH_HELPER_SKIP_FILE = 423 // Signal that helper skipped a file.
325 FS_PUBLISH_HELPER_COUNTING_DONE = 424 // Signal that helper is done scanning the directory tree.
326 FS_PUBLISH_HELPER_META_DATA = 425 // Extracted meta data from the helper.
327 FS_PUBLISH_HELPER_FINISHED = 426 // Signal that helper is done.
328
329 //------------------------------------------------------------------
330 // NAMECACHE message types
331 //------------------------------------------------------------------
332
333 NAMECACHE_LOOKUP_BLOCK = 431 // Client to service: lookup block
334 NAMECACHE_LOOKUP_BLOCK_RESPONSE = 432 // Service to client: result of block lookup
335 NAMECACHE_BLOCK_CACHE = 433 // Client to service: cache a block
336 NAMECACHE_BLOCK_CACHE_RESPONSE = 434 // Service to client: result of block cache request
337
338 //------------------------------------------------------------------
339 // NAMESTORE message types
340 //------------------------------------------------------------------
341
342 NAMESTORE_RECORD_STORE = 435 // Client to service: store records (as authority)
343 NAMESTORE_RECORD_STORE_RESPONSE = 436 // Service to client: result of store operation.
344 NAMESTORE_RECORD_LOOKUP = 437 // Client to service: lookup label
345 NAMESTORE_RECORD_LOOKUP_RESPONSE = 438 // Service to client: lookup label
346 NAMESTORE_ZONE_TO_NAME = 439 // Client to service: "reverse" lookup for zone name based on zone key
347 NAMESTORE_ZONE_TO_NAME_RESPONSE = 440 // Service to client: result of zone-to-name lookup.
348 NAMESTORE_MONITOR_START = 441 // Client to service: start monitoring (yields sequence of "ZONE_ITERATION_RESPONSES" --- forever).
349 NAMESTORE_MONITOR_SYNC = 442 // Service to client: you're now in sync.
350 NAMESTORE_RECORD_RESULT = 443 // Service to client: here is a (plaintext) record you requested.
351 NAMESTORE_MONITOR_NEXT = 444 // Client to service: I am now ready for the next (set of) monitor events. Monitoring equivlaent of #NAMESTORE_ZONE_ITERATION_NEXT.
352 NAMESTORE_ZONE_ITERATION_START = 445 // Client to service: please start iteration; receives "NAMESTORE_LOOKUP_NAME_RESPONSE" messages in return.
353 NAMESTORE_ZONE_ITERATION_NEXT = 447 // Client to service: next record(s) in iteration please.
354 NAMESTORE_ZONE_ITERATION_STOP = 448 // Client to service: stop iterating.
355
356 //------------------------------------------------------------------
357 // LOCKMANAGER message types
358 //------------------------------------------------------------------
359
360 LOCKMANAGER_ACQUIRE = 450 // Message to acquire Lock
361 LOCKMANAGER_RELEASE = 451 // Message to release lock
362 LOCKMANAGER_SUCCESS = 452 // SUCCESS reply from lockmanager
363
364 //------------------------------------------------------------------
365 // TESTBED message types
366 //------------------------------------------------------------------
367
368 TESTBED_INIT = 460 // Initial message from a client to a testing control service
369 TESTBED_ADD_HOST = 461 // Message to add host
370 TESTBED_ADD_HOST_SUCCESS = 462 // Message to signal that a add host succeeded
371 TESTBED_LINK_CONTROLLERS = 463 // Message to link delegated controller to slave controller
372 TESTBED_CREATE_PEER = 464 // Message to create a peer at a host
373 TESTBED_RECONFIGURE_PEER = 465 // Message to reconfigure a peer
374 TESTBED_START_PEER = 466 // Message to start a peer at a host
375 TESTBED_STOP_PEER = 467 // Message to stop a peer at a host
376 TESTBED_DESTROY_PEER = 468 // Message to destroy a peer
377 TESTBED_CONFIGURE_UNDERLAY_LINK = 469 // Configure underlay link message
378 TESTBED_OVERLAY_CONNECT = 470 // Message to connect peers in a overlay
379 TESTBED_PEER_EVENT = 471 // Message for peer events
380 TESTBED_PEER_CONNECT_EVENT = 472 // Message for peer connect events
381 TESTBED_OPERATION_FAIL_EVENT = 473 // Message for operation events
382 TESTBED_CREATE_PEER_SUCCESS = 474 // Message to signal successful peer creation
383 TESTBED_GENERIC_OPERATION_SUCCESS = 475 // Message to signal a generic operation has been successful
384 TESTBED_GET_PEER_INFORMATION = 476 // Message to get a peer's information
385 TESTBED_PEER_INFORMATION = 477 // Message containing the peer's information
386 TESTBED_REMOTE_OVERLAY_CONNECT = 478 // Message to request a controller to make one of its peer to connect to another peer using the contained HELLO
387 TESTBED_GET_SLAVE_CONFIGURATION = 479 // Message to request configuration of a slave controller
388 TESTBED_SLAVE_CONFIGURATION = 480 // Message which contains the configuration of slave controller
389 TESTBED_LINK_CONTROLLERS_RESULT = 481 // Message to signal the result of #TESTBED_LINK_CONTROLLERS request
390 TESTBED_SHUTDOWN_PEERS = 482 // A controller receiving this message floods it to its directly-connected sub-controllers and then stops and destroys all peers
391 TESTBED_MANAGE_PEER_SERVICE = 483 // Message to start/stop a service of a peer
392 TESTBED_BARRIER_INIT = 484 // Message to initialise a barrier. Messages of these type are flooded to all sub-controllers
393 TESTBED_BARRIER_CANCEL = 485 // Message to cancel a barrier. This message is flooded to all sub-controllers
394 TESTBED_BARRIER_STATUS = 486 // Message for signalling status of a barrier
395 TESTBED_BARRIER_WAIT = 487 // Message sent by a peer when it has reached a barrier and is waiting for it to be crossed
396 TESTBED_MAX = 488 // Not really a message, but for careful checks on the testbed messages; Should always be the maximum and never be used to send messages with this type
397 TESTBED_HELPER_INIT = 495 // The initialization message towards gnunet-testbed-helper
398 TESTBED_HELPER_REPLY = 496 // The reply message from gnunet-testbed-helper
399
400 //------------------------------------------------------------------
401 // GNS.
402 //------------------------------------------------------------------
403
404 GNS_LOOKUP = 500 // Client would like to resolve a name.
405 GNS_LOOKUP_RESULT = 501 // Service response to name resolution request from client.
406 GNS_REVERSE_LOOKUP = 502 // Reverse lookup
407 GNS_REVERSE_LOOKUP_RESULT = 503 // Response to reverse lookup
408
409 //------------------------------------------------------------------
410 // CONSENSUS message types
411 //------------------------------------------------------------------
412
413 CONSENSUS_CLIENT_JOIN = 520 // Join a consensus session. Sent by client to service as first message.
414 CONSENSUS_CLIENT_INSERT = 521 // Insert an element. Sent by client to service.
415 CONSENSUS_CLIENT_BEGIN = 522 // Begin accepting new elements from other participants. Sent by client to service.
416 CONSENSUS_CLIENT_RECEIVED_ELEMENT = 523 // Sent by service when a new element is added.
417 CONSENSUS_CLIENT_CONCLUDE = 524 // Sent by client to service in order to start the consensus conclusion.
418 CONSENSUS_CLIENT_CONCLUDE_DONE = 525 // Sent by service to client in order to signal a completed consensus conclusion. Last message sent in a consensus session.
419 CONSENSUS_CLIENT_ACK = 540 // Sent by client to service, telling whether a received element should be accepted and propagated further or not.
420 CONSENSUS_P2P_DELTA_ESTIMATE = 541 // Strata estimator.
421 CONSENSUS_P2P_DIFFERENCE_DIGEST = 542 // IBF containing all elements of a peer.
422 CONSENSUS_P2P_ELEMENTS = 543 // One or more elements that are sent from peer to peer.
423 CONSENSUS_P2P_ELEMENTS_REQUEST = 544 // Elements, and requests for further elements
424 CONSENSUS_P2P_ELEMENTS_REPORT = 545 // Elements that a peer reports to be missing at the remote peer.
425 CONSENSUS_P2P_HELLO = 546 // Initialization message for consensus p2p communication.
426 CONSENSUS_P2P_SYNCED = 547 // Report that the peer is synced with the partner after successfuly decoding the invertible bloom filter.
427 CONSENSUS_P2P_FIN = 548 // Interaction os over, got synched and reported all elements
428 CONSENSUS_P2P_ABORT = 548 // Abort a round, don't send requested elements anymore
429 CONSENSUS_P2P_ROUND_CONTEXT = 547 // Abort a round, don't send requested elements anymore
430
431 //------------------------------------------------------------------
432 // SET message types
433 //------------------------------------------------------------------
434
435 SET_UNION_P2P_REQUEST_FULL = 565 // Demand the whole element from the other peer, given only the hash code.
436 SET_UNION_P2P_DEMAND = 566 // Demand the whole element from the other peer, given only the hash code.
437 SET_UNION_P2P_INQUIRY = 567 // Tell the other peer to send us a list of hashes that match an IBF key.
438 SET_UNION_P2P_OFFER = 568 // Tell the other peer which hashes match a given IBF key.
439 SET_REJECT = 569 // Reject a set request.
440 SET_CANCEL = 570 // Cancel a set operation
441 SET_ITER_ACK = 571 // Acknowledge result from iteration
442 SET_RESULT = 572 // Create an empty set
443 SET_ADD = 573 // Add element to set
444 SET_REMOVE = 574 // Remove element from set
445 SET_LISTEN = 575 // Listen for operation requests
446 SET_ACCEPT = 576 // Accept a set request
447 SET_EVALUATE = 577 // Evaluate a set operation
448 SET_CONCLUDE = 578 // Start a set operation with the given set
449 SET_REQUEST = 579 // Notify the client of a request from a remote peer
450 SET_CREATE = 580 // Create a new local set
451 SET_P2P_OPERATION_REQUEST = 581 // Request a set operation from a remote peer.
452 SET_UNION_P2P_SE = 582 // Strata estimator.
453 SET_UNION_P2P_IBF = 583 // Invertible bloom filter.
454 SET_P2P_ELEMENTS = 584 // Actual set elements.
455 SET_P2P_ELEMENT_REQUESTS = 585 // Requests for the elements with the given hashes.
456 SET_UNION_P2P_DONE = 586 // Set operation is done.
457 SET_ITER_REQUEST = 587 // Start iteration over set elements.
458 SET_ITER_ELEMENT = 588 // Element result for the iterating client.
459 SET_ITER_DONE = 589 // Iteration end marker for the client.
460 SET_UNION_P2P_SEC = 590 // Compressed strata estimator.
461 SET_INTERSECTION_P2P_ELEMENT_INFO = 591 // Information about the element count for intersection
462 SET_INTERSECTION_P2P_BF = 592 // Bloom filter message for intersection exchange started by Bob.
463 SET_INTERSECTION_P2P_DONE = 593 // Intersection operation is done.
464 SET_COPY_LAZY_PREPARE = 594 // Ask the set service to prepare a copy of a set.
465 SET_COPY_LAZY_RESPONSE = 595 // Give the client an ID for connecting to the set's copy.
466 SET_COPY_LAZY_CONNECT = 596 // Sent by the client to the server to connect to an existing, lazily copied set.
467 SET_UNION_P2P_FULL_DONE = 597 // Request all missing elements from the other peer, based on their sets and the elements we previously sent with #SET_P2P_ELEMENTS.
468 SET_UNION_P2P_FULL_ELEMENT = 598 // Send a set element, not as response to a demand but because we're sending the full set.
469 SET_UNION_P2P_OVER = 599 // Request all missing elements from the other peer, based on their sets and the elements we previously sent with #SET_P2P_ELEMENTS.
470
471 //------------------------------------------------------------------
472 // TESTBED LOGGER message types
473 //------------------------------------------------------------------
474
475 TESTBED_LOGGER_MSG = 600 // Message for TESTBED LOGGER
476 TESTBED_LOGGER_ACK = 601 // Message for TESTBED LOGGER acknowledgement
477
478 REGEX_ANNOUNCE = 620 // Advertise regex capability.
479 REGEX_SEARCH = 621 // Search for peer with matching capability.
480 REGEX_RESULT = 622 // Result in response to regex search.
481
482 //------------------------------------------------------------------
483 // IDENTITY message types
484 //------------------------------------------------------------------
485
486 IDENTITY_START = 624 // First message send from identity client to service (to subscribe to updates).
487 IDENTITY_RESULT_CODE = 625 // Generic response from identity service with success and/or error message.
488 IDENTITY_UPDATE = 626 // Update about identity status from service to clients.
489 IDENTITY_GET_DEFAULT = 627 // Client requests to know default identity for a subsystem.
490 IDENTITY_SET_DEFAULT = 628 // Client sets default identity; or service informs about default identity.
491 IDENTITY_CREATE = 629 // Create new identity (client->service).
492 IDENTITY_RENAME = 630 // Rename existing identity (client->service).
493 IDENTITY_DELETE = 631 // Delete identity (client->service).
494 IDENTITY_LOOKUP = 632
495 IDENTITY_LOOKUP_BY_NAME = 633
496
497 //------------------------------------------------------------------
498 // REVOCATION message types
499 //------------------------------------------------------------------
500
501 REVOCATION_QUERY = 636 // Client to service: was this key revoked?
502 REVOCATION_QUERY_RESPONSE = 637 // Service to client: answer if key was revoked!
503 REVOCATION_REVOKE = 638 // Client to service OR peer-to-peer: revoke this key!
504 REVOCATION_REVOKE_RESPONSE = 639 // Service to client: revocation confirmed
505
506 //------------------------------------------------------------------
507 // SCALARPRODUCT message types
508 //------------------------------------------------------------------
509
510 SCALARPRODUCT_CLIENT_TO_ALICE = 640 // Client -> Alice
511 SCALARPRODUCT_CLIENT_TO_BOB = 641 // Client -> Bob
512 SCALARPRODUCT_CLIENT_MULTIPART_ALICE = 642 // Client -> Alice multipart
513 SCALARPRODUCT_CLIENT_MULTIPART_BOB = 643 // Client -> Bob multipart
514 SCALARPRODUCT_SESSION_INITIALIZATION = 644 // Alice -> Bob session initialization
515 SCALARPRODUCT_ALICE_CRYPTODATA = 645 // Alice -> Bob SP crypto-data (after intersection)
516 SCALARPRODUCT_BOB_CRYPTODATA = 647 // Bob -> Alice SP crypto-data
517 SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART = 648 // Bob -> Alice SP crypto-data multipart
518 SCALARPRODUCT_RESULT = 649 // Alice/Bob -> Client Result
519 SCALARPRODUCT_ECC_SESSION_INITIALIZATION = 650 // Alice -> Bob ECC session initialization
520 SCALARPRODUCT_ECC_ALICE_CRYPTODATA = 651 // Alice -> Bob ECC crypto data
521 SCALARPRODUCT_ECC_BOB_CRYPTODATA = 652 // Bob -> Alice ECC crypto data
522
523 //------------------------------------------------------------------
524 // PSYCSTORE message types
525 //------------------------------------------------------------------
526
527 PSYCSTORE_MEMBERSHIP_STORE = 660 // Store a membership event.
528 PSYCSTORE_MEMBERSHIP_TEST = 661 // Test for membership of a member at a particular point in time.
529 PSYCSTORE_FRAGMENT_STORE = 662 //
530 PSYCSTORE_FRAGMENT_GET = 663 //
531 PSYCSTORE_MESSAGE_GET = 664 //
532 PSYCSTORE_MESSAGE_GET_FRAGMENT = 665 //
533 PSYCSTORE_COUNTERS_GET = 666 //
534 PSYCSTORE_STATE_MODIFY = 668 //
535 PSYCSTORE_STATE_SYNC = 669 //
536 PSYCSTORE_STATE_RESET = 670 //
537 PSYCSTORE_STATE_HASH_UPDATE = 671 //
538 PSYCSTORE_STATE_GET = 672 //
539 PSYCSTORE_STATE_GET_PREFIX = 673 //
540 PSYCSTORE_RESULT_CODE = 674 // Generic response from PSYCstore service with success and/or error message.
541 PSYCSTORE_RESULT_FRAGMENT = 675 //
542 PSYCSTORE_RESULT_COUNTERS = 676 //
543 PSYCSTORE_RESULT_STATE = 677 //
544
545 //------------------------------------------------------------------
546 // PSYC message types
547 //------------------------------------------------------------------
548
549 PSYC_RESULT_CODE = 680 // S->C: result of an operation
550 PSYC_MASTER_START = 681 // C->S: request to start a channel as a master
551 PSYC_MASTER_START_ACK = 682 // S->C: master start acknowledgement
552 PSYC_SLAVE_JOIN = 683 // C->S: request to join a channel as a slave
553 PSYC_SLAVE_JOIN_ACK = 684 // S->C: slave join acknowledgement
554 PSYC_PART_REQUEST = 685 // C->S: request to part from a channel
555 PSYC_PART_ACK = 686 // S->C: acknowledgement that a slave of master parted from a channel
556 PSYC_JOIN_REQUEST = 687 // M->S->C: incoming join request from multicast
557 PSYC_JOIN_DECISION = 688 // C->S->M: decision about a join request
558 PSYC_CHANNEL_MEMBERSHIP_STORE = 689 // C->S: request to add/remove channel slave in the membership database.
559 PSYC_MESSAGE = 691 // S<--C: PSYC message which contains one or more message parts.
560 PSYC_MESSAGE_HEADER = 692 // M<->S<->C: PSYC message which contains a header and one or more message parts.
561 PSYC_MESSAGE_METHOD = 693 // Message part: method
562 PSYC_MESSAGE_MODIFIER = 694 // Message part: modifier
563 PSYC_MESSAGE_MOD_CONT = 695 // Message part: modifier continuation
564 PSYC_MESSAGE_DATA = 696 // Message part: data
565 PSYC_MESSAGE_END = 697 // Message part: end of message
566 PSYC_MESSAGE_CANCEL = 698 // Message part: message cancelled
567 PSYC_MESSAGE_ACK = 699 // S->C: message acknowledgement
568 PSYC_HISTORY_REPLAY = 701 // C->S: request channel history replay from PSYCstore.
569 PSYC_HISTORY_RESULT = 702 // S->C: result for a channel history request
570 PSYC_STATE_GET = 703 // C->S: request best matching state variable from PSYCstore.
571 PSYC_STATE_GET_PREFIX = 704 // C->S: request state variables with a given prefix from PSYCstore.
572 PSYC_STATE_RESULT = 705 // S->C: result for a state request.
573
574 //------------------------------------------------------------------
575 // CONVERSATION message types
576 //------------------------------------------------------------------
577
578 CONVERSATION_AUDIO = 730 // Message to transmit the audio between helper and speaker/microphone library.
579 CONVERSATION_CS_PHONE_REGISTER = 731 // Client -> Server message to register a phone.
580 CONVERSATION_CS_PHONE_PICK_UP = 732 // Client -> Server message to reject/hangup a call
581 CONVERSATION_CS_PHONE_HANG_UP = 733 // Client -> Server message to reject/hangup a call
582 CONVERSATION_CS_PHONE_CALL = 734 // Client <- Server message to indicate a ringing phone
583 CONVERSATION_CS_PHONE_RING = 735 // Client <- Server message to indicate a ringing phone
584 CONVERSATION_CS_PHONE_SUSPEND = 736 // Client <-> Server message to suspend connection.
585 CONVERSATION_CS_PHONE_RESUME = 737 // Client <-> Server message to resume connection.
586 CONVERSATION_CS_PHONE_PICKED_UP = 738 // Service -> Client message to notify that phone was picked up.
587 CONVERSATION_CS_AUDIO = 739 // Client <-> Server message to send audio data.
588 CONVERSATION_CADET_PHONE_RING = 740 // Cadet: call initiation
589 CONVERSATION_CADET_PHONE_HANG_UP = 741 // Cadet: hang up / refuse call
590 CONVERSATION_CADET_PHONE_PICK_UP = 742 // Cadet: pick up phone (establish audio channel)
591 CONVERSATION_CADET_PHONE_SUSPEND = 743 // Cadet: phone suspended.
592 CONVERSATION_CADET_PHONE_RESUME = 744 // Cadet: phone resumed.
593 CONVERSATION_CADET_AUDIO = 745 // Cadet: audio data
594
595 //------------------------------------------------------------------
596 // MULTICAST message types
597 //------------------------------------------------------------------
598
599 MULTICAST_ORIGIN_START = 750 // C->S: Start the origin.
600 MULTICAST_MEMBER_JOIN = 751 // C->S: Join group as a member.
601 MULTICAST_JOIN_REQUEST = 752 // C<--S<->T: A peer wants to join the group. Unicast message to the origin or another group member.
602 MULTICAST_JOIN_DECISION = 753 // C<->S<->T: Response to a join request. Unicast message from a group member to the peer wanting to join.
603 MULTICAST_PART_REQUEST = 754 // A peer wants to part the group.
604 MULTICAST_PART_ACK = 755 // Acknowledgement sent in response to a part request. Unicast message from a group member to the peer wanting to part.
605 MULTICAST_GROUP_END = 756 // Group terminated.
606 MULTICAST_MESSAGE = 757 // C<->S<->T: Multicast message from the origin to all members.
607 MULTICAST_REQUEST = 758 // C<->S<->T: Unicast request from a group member to the origin.
608 MULTICAST_FRAGMENT_ACK = 759 // C->S: Acknowledgement of a message or request fragment for the client.
609 MULTICAST_REPLAY_REQUEST = 760 // C<->S<->T: Replay request from a group member to another member.
610 MULTICAST_REPLAY_RESPONSE = 761 // C<->S<->T: Replay response from a group member to another member.
611 MULTICAST_REPLAY_RESPONSE_END = 762 // C<->S: End of replay response.
612
613 //------------------------------------------------------------------
614 // SECRETSHARING message types
615 //------------------------------------------------------------------
616
617 SECRETSHARING_CLIENT_GENERATE = 780 // Establish a new session.
618 SECRETSHARING_CLIENT_DECRYPT = 781 // Request the decryption of a ciphertext.
619 SECRETSHARING_CLIENT_DECRYPT_DONE = 782 // The service succeeded in decrypting a ciphertext.
620 SECRETSHARING_CLIENT_SECRET_READY = 783 // Contains the peer's share.
621
622 //------------------------------------------------------------------
623 // PEERSTORE message types
624 //------------------------------------------------------------------
625
626 PEERSTORE_STORE = 820 // Store request message
627 PEERSTORE_ITERATE = 821 // Iteration request
628 PEERSTORE_ITERATE_RECORD = 822 // Iteration record message
629 PEERSTORE_ITERATE_END = 823 // Iteration end message
630 PEERSTORE_WATCH = 824 // Watch request
631 PEERSTORE_WATCH_RECORD = 825 // Watch response
632 PEERSTORE_WATCH_CANCEL = 826 // Watch cancel request
633
634 //------------------------------------------------------------------
635 // SOCIAL message types
636 //------------------------------------------------------------------
637
638 SOCIAL_RESULT_CODE = 840 // S->C: result of an operation
639 SOCIAL_HOST_ENTER = 841 // C->S: request to enter a place as the host
640 SOCIAL_HOST_ENTER_ACK = 842 // S->C: host enter acknowledgement
641 SOCIAL_GUEST_ENTER = 843 // C->S: request to enter a place as a guest
642 SOCIAL_GUEST_ENTER_BY_NAME = 844 // C->S: request to enter a place as a guest, using a GNS address
643 SOCIAL_GUEST_ENTER_ACK = 845 // S->C: guest enter acknowledgement
644 SOCIAL_ENTRY_REQUEST = 846 // P->S->C: incoming entry request from PSYC
645 SOCIAL_ENTRY_DECISION = 847 // C->S->P: decision about an entry request
646 SOCIAL_PLACE_LEAVE = 848 // C->S: request to leave a place
647 SOCIAL_PLACE_LEAVE_ACK = 849 // S->C: place leave acknowledgement
648 SOCIAL_ZONE_ADD_PLACE = 850 // C->S: add place to GNS zone
649 SOCIAL_ZONE_ADD_NYM = 851 // C->S: add nym to GNS zone
650 SOCIAL_APP_CONNECT = 852 // C->S: connect application
651 SOCIAL_APP_DETACH = 853 // C->S: detach a place from application
652 SOCIAL_APP_EGO = 854 // S->C: notify about an existing ego
653 SOCIAL_APP_EGO_END = 855 // S->C: end of ego list
654 SOCIAL_APP_PLACE = 856 // S->C: notify about an existing place
655 SOCIAL_APP_PLACE_END = 857 // S->C: end of place list
656 SOCIAL_MSG_PROC_SET = 858 // C->S: set message processing flags
657 SOCIAL_MSG_PROC_CLEAR = 859 // C->S: clear message processing flags
658
659 //------------------------------------------------------------------
660 // X-VINE DHT messages
661 //------------------------------------------------------------------
662
663 XDHT_P2P_TRAIL_SETUP = 880 // Trail setup request is received by a peer.
664 XDHT_P2P_TRAIL_SETUP_RESULT = 881 // Trail to a particular peer is returned to this peer.
665 XDHT_P2P_VERIFY_SUCCESSOR = 882 // Verify if your immediate successor is still your immediate successor.
666 XDHT_P2P_NOTIFY_NEW_SUCCESSOR = 883 // Notify your new immediate successor that you are its new predecessor.
667 XDHT_P2P_VERIFY_SUCCESSOR_RESULT = 884 // Message which contains the immediate predecessor of requested successor
668 XDHT_P2P_GET_RESULT = 885 // Message which contains the get result.
669 XDHT_P2P_TRAIL_SETUP_REJECTION = 886 // Trail Rejection Message.
670 XDHT_P2P_TRAIL_TEARDOWN = 887 // Trail Tear down Message.
671 XDHT_P2P_ADD_TRAIL = 888 // Routing table add message.
672 XDHT_P2P_PUT = 890 // Peer is storing the data in DHT.
673 XDHT_P2P_GET = 891 // Peer tries to find data in DHT.
674 XDHT_P2P_NOTIFY_SUCCESSOR_CONFIRMATION = 892 // Send back peer that considers you are its successor.
675
676 DHT_ACT_MALICIOUS = 893 // Turn X-VINE DHT service malicious
677 DHT_CLIENT_ACT_MALICIOUS_OK = 894 // Acknowledge receiving ACT MALICIOUS request
678
679 //------------------------------------------------------------------
680 // Whanau DHT messages
681 //------------------------------------------------------------------
682
683 WDHT_RANDOM_WALK = 910 // This message contains the query for performing a random walk
684 WDHT_RANDOM_WALK_RESPONSE = 911 // This message contains the result of a random walk
685 WDHT_TRAIL_DESTROY = 912 // This message contains a notification for the death of a trail
686 WDHT_TRAIL_ROUTE = 913 // This message are used to route a query to a peer
687 WDHT_SUCCESSOR_FIND = 914 // This message contains the query to transfer successor values.
688 WDHT_GET = 915 // Message which contains the get query
689 WDHT_PUT = 916 // Message which contains the "put", a response to #WDHT_SUCCESSOR_FIND.
690 WDHT_GET_RESULT = 917 // Message which contains the get result, a response to #WDHT_GET.
691
692 //------------------------------------------------------------------
693 // RPS messages
694 //------------------------------------------------------------------
695
696 RPS_PP_CHECK_LIVE = 950 // RPS check liveliness message to check liveliness of other peer
697 RPS_PP_PUSH = 951 // RPS PUSH message to push own ID to another peer
698 RPS_PP_PULL_REQUEST = 952 // RPS PULL REQUEST message to request the local view of another peer
699 RPS_PP_PULL_REPLY = 953 // RPS PULL REPLY message which contains the view of the other peer
700 RPS_CS_SEED = 954 // RPS CS SEED Message for the Client to seed peers into rps
701 RPS_ACT_MALICIOUS = 955 // Turn RPS service malicious
702 RPS_CS_SUB_START = 956 // RPS client-service message to start a sub sampler
703 RPS_CS_SUB_STOP = 957 // RPS client-service message to stop a sub sampler
704
705 //------------------------------------------------------------------
706 // RECLAIM messages
707 //------------------------------------------------------------------
708
709 RECLAIM_ATTRIBUTE_STORE = 961
710 RECLAIM_SUCCESS_RESPONSE = 962
711 RECLAIM_ATTRIBUTE_ITERATION_START = 963
712 RECLAIM_ATTRIBUTE_ITERATION_STOP = 964
713 RECLAIM_ATTRIBUTE_ITERATION_NEXT = 965
714 RECLAIM_ATTRIBUTE_RESULT = 966
715 RECLAIM_ISSUE_TICKET = 967
716 RECLAIM_TICKET_RESULT = 968
717 RECLAIM_REVOKE_TICKET = 969
718 RECLAIM_REVOKE_TICKET_RESULT = 970
719 RECLAIM_CONSUME_TICKET = 971
720 RECLAIM_CONSUME_TICKET_RESULT = 972
721 RECLAIM_TICKET_ITERATION_START = 973
722 RECLAIM_TICKET_ITERATION_STOP = 974
723 RECLAIM_TICKET_ITERATION_NEXT = 975
724 RECLAIM_ATTRIBUTE_DELETE = 976
725
726 //------------------------------------------------------------------
727 // CREDENTIAL messages
728 //------------------------------------------------------------------
729
730 CREDENTIAL_VERIFY = 981 //
731 CREDENTIAL_VERIFY_RESULT = 982 //
732 CREDENTIAL_COLLECT = 983 //
733 CREDENTIAL_COLLECT_RESULT = 984 //
734
735 //------------------------------------------------------------------
736 // CADET messages
737 //------------------------------------------------------------------
738
739 CADET_CONNECTION_CREATE = 1000 // Request the creation of a connection
740 CADET_CONNECTION_CREATE_ACK = 1001 // Send origin an ACK that the connection is complete
741 CADET_CONNECTION_BROKEN = 1002 // Notify that a connection is no longer valid
742 CADET_CONNECTION_DESTROY = 1003 // Request the destuction of a connection
743 CADET_CONNECTION_PATH_CHANGED_UNIMPLEMENTED = 1004 // At some point, the route will spontaneously change TODO
744 CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK = 1005 // Hop-by-hop, connection dependent ACK. deprecated
745
746 CADET_TUNNEL_ENCRYPTED_POLL = 1006 // We do not bother with ACKs for #CADET_TUNNEL_ENCRYPTED messages, but we instead poll for one if we got nothing for a while and start to be worried. deprecated
747 CADET_TUNNEL_KX = 1007 // Axolotl key exchange.
748 CADET_TUNNEL_ENCRYPTED = 1008 // Axolotl encrypted data.
749 CADET_TUNNEL_KX_AUTH = 1009 // Axolotl key exchange response with authentication.
750
751 CADET_CHANNEL_APP_DATA = 1010 // Payload data (inside an encrypted tunnel).
752 CADET_CHANNEL_APP_DATA_ACK = 1011 // Confirm payload data end-to-end.
753 CADET_CHANNEL_KEEPALIVE = 1012 // Announce connection is still alive (direction sensitive).
754 CADET_CHANNEL_OPEN = 1013 // Ask the cadet service to create a new channel.
755 CADET_CHANNEL_DESTROY = 1014 // Ask the cadet service to destroy a channel.
756 CADET_CHANNEL_OPEN_ACK = 1015 // Confirm the creation of a channel
757 CADET_CHANNEL_OPEN_NACK_DEPRECATED = 1016 // Reject the creation of a channel deprecated
758
759 CADET_LOCAL_DATA = 1020 // Payload client <-> service
760 CADET_LOCAL_ACK = 1021 // Local ACK for data.
761 CADET_LOCAL_PORT_OPEN = 1022 // Start listening on a port.
762 CADET_LOCAL_PORT_CLOSE = 1023 // Stop listening on a port.
763 CADET_LOCAL_CHANNEL_CREATE = 1024 // Ask the cadet service to create a new channel.
764 CADET_LOCAL_CHANNEL_DESTROY = 1025 // Tell client that a channel was destroyed.
765
766 CADET_LOCAL_REQUEST_INFO_CHANNEL = 1030 // Local information about all channels of service.
767 CADET_LOCAL_INFO_CHANNEL = 1031 // Local information of service about a specific channel.
768 CADET_LOCAL_INFO_CHANNEL_END = 1032 // End of local information of service about channels.
769 CADET_LOCAL_REQUEST_INFO_PEERS = 1033 // Request local information about all peers known to the service.
770 CADET_LOCAL_INFO_PEERS = 1034 // Local information about all peers known to the service.
771 CADET_LOCAL_INFO_PEERS_END = 1035 // End of local information about all peers known to the service.
772 CADET_LOCAL_REQUEST_INFO_PATH = 1036 // Request local information of service about paths to specific peer.
773 CADET_LOCAL_INFO_PATH = 1037 // Local information of service about a specific path.
774 CADET_LOCAL_INFO_PATH_END = 1038 // End of local information of service about a specific path.
775 CADET_LOCAL_REQUEST_INFO_TUNNELS = 1039 // Request local information about all tunnels of service.
776 CADET_LOCAL_INFO_TUNNELS = 1040 // Local information about all tunnels of service.
777 CADET_LOCAL_INFO_TUNNELS_END = 1041 // End of local information about all tunnels of service.
778
779 CADET_CLI = 1059 // Traffic (net-cat style) used by the Command Line Interface.
780
781 //------------------------------------------------------------------
782 // NAT messages
783 //------------------------------------------------------------------
784
785 NAT_REGISTER = 1060 // Message to ask NAT service to register a client.
786 NAT_HANDLE_STUN = 1061 // Message to ask NAT service to handle a STUN packet.
787 NAT_REQUEST_CONNECTION_REVERSAL = 1062 // Message to ask NAT service to request connection reversal.
788 NAT_CONNECTION_REVERSAL_REQUESTED = 1063 // Message to from NAT service notifying us that connection reversal was requested by another peer.
789 NAT_ADDRESS_CHANGE = 1064 // Message to from NAT service notifying us that one of our addresses changed.
790 NAT_AUTO_REQUEST_CFG = 1066 // Message to ask NAT service to request autoconfiguration.
791 NAT_AUTO_CFG_RESULT = 1065 // Message from NAT service with the autoconfiguration result.
792
793 //------------------------------------------------------------------
794 // AUCTION messages
795 //------------------------------------------------------------------
796
797 AUCTION_CLIENT_CREATE = 1110 // Client wants to create a new auction.
798 AUCTION_CLIENT_JOIN = 1111 // Client wants to join an existing auction.
799 AUCTION_CLIENT_OUTCOME = 1112 // Service reports the auction outcome to the client.
800
801 //------------------------------------------------------------------
802 // RPS_DEBUG messages
803 //------------------------------------------------------------------
804
805 RPS_CS_DEBUG_VIEW_REQUEST = 1130 // Request updates of the view
806 RPS_CS_DEBUG_VIEW_REPLY = 1131 // Send update of the view
807 RPS_CS_DEBUG_VIEW_CANCEL = 1132 // Cancel getting updates of the view
808 RPS_CS_DEBUG_STREAM_REQUEST = 1133 // Request biased input stream
809 RPS_CS_DEBUG_STREAM_REPLY = 1134 // Send peer of biased stream
810 RPS_CS_DEBUG_STREAM_CANCEL = 1135 // Cancel getting biased stream
811
812 //------------------------------------------------------------------
813 // CATCH-ALL_DEBUG message
814 //------------------------------------------------------------------
815
816 ALL = 65535 // Type used to match 'all' message types.
817)
diff --git a/src/gnunet/service/client.go b/src/gnunet/service/client.go
new file mode 100644
index 0000000..2d1c3dd
--- /dev/null
+++ b/src/gnunet/service/client.go
@@ -0,0 +1,59 @@
1package service
2
3import (
4 "github.com/bfix/gospel/logger"
5 "gnunet/message"
6 "gnunet/transport"
7)
8
9// Client
10type Client struct {
11 ch *transport.MsgChannel
12}
13
14// NewClient
15func NewClient(endp string) (*Client, error) {
16 //
17 ch, err := transport.NewChannel(endp)
18 if err != nil {
19 return nil, err
20 }
21 return &Client{
22 ch: transport.NewMsgChannel(ch),
23 }, nil
24}
25
26func (c *Client) SendRequest(req message.Message) error {
27 return c.ch.Send(req)
28}
29
30func (c *Client) ReceiveResponse() (message.Message, error) {
31 return c.ch.Receive()
32}
33
34func (c *Client) Close() error {
35 return c.ch.Close()
36}
37
38func ServiceRequestResponse(caller, callee, endp string, req message.Message) (message.Message, error) {
39 // client-connect to the service
40 logger.Printf(logger.DBG, "[%s] Connect to %s service\n", caller, callee)
41 cl, err := NewClient(endp)
42 if err != nil {
43 return nil, err
44 }
45 // send request
46 logger.Printf(logger.DBG, "[%s] Sending request to %s service\n", caller, callee)
47 if err = cl.SendRequest(req); err != nil {
48 return nil, err
49 }
50 // wait for a single response, then close the connection
51 logger.Printf(logger.DBG, "[%s] Waiting for response from %s service\n", caller, callee)
52 var resp message.Message
53 if resp, err = cl.ReceiveResponse(); err != nil {
54 return nil, err
55 }
56 logger.Printf(logger.DBG, "[%s] Closing connection to %s service\n", caller, callee)
57 cl.Close()
58 return resp, nil
59}
diff --git a/src/gnunet/service/gns/crypto.go b/src/gnunet/service/gns/crypto.go
new file mode 100644
index 0000000..f7ef111
--- /dev/null
+++ b/src/gnunet/service/gns/crypto.go
@@ -0,0 +1,41 @@
1package gns
2
3import (
4 "crypto/sha256"
5 "crypto/sha512"
6
7 "github.com/bfix/gospel/crypto/ed25519"
8 "gnunet/crypto"
9 "golang.org/x/crypto/hkdf"
10)
11
12// QueryFromPublickeyDerive calculates the DHT query for a given label in a
13// given zone (identified by PKEY).
14func QueryFromPublickeyDerive(pkey *ed25519.PublicKey, label string) *crypto.HashCode {
15 pd := crypto.DerivePublicKey(pkey, label, "gns")
16 return crypto.Hash(pd.Bytes())
17}
18
19// DecryptBlock
20func DecryptBlock(data []byte, zoneKey *ed25519.PublicKey, label string) (out []byte, err error) {
21 // derive key material for decryption
22 iv, skey := deriveBlockKey(label, zoneKey)
23 // perform decryption
24 return crypto.SymmetricDecrypt(data, skey, iv)
25}
26
27// Derive a symmetric key to decipher a GNS block
28func deriveBlockKey(label string, pub *ed25519.PublicKey) (iv *crypto.SymmetricIV, skey *crypto.SymmetricKey) {
29 // generate symmetric key
30 prk := hkdf.Extract(sha512.New, []byte(label), pub.Bytes())
31 rdr := hkdf.Expand(sha256.New, prk, []byte("gns-aes-ctx-key"))
32 skey = crypto.NewSymmetricKey()
33 rdr.Read(skey.AESKey)
34 rdr.Read(skey.TwofishKey)
35 // generate initialization vector
36 rdr = hkdf.Expand(sha256.New, prk, []byte("gns-aes-ctx-iv"))
37 iv = crypto.NewSymmetricIV()
38 rdr.Read(iv.AESIv)
39 rdr.Read(iv.TwofishIv)
40 return
41}
diff --git a/src/gnunet/service/gns/crypto_test.go b/src/gnunet/service/gns/crypto_test.go
new file mode 100644
index 0000000..2abfb99
--- /dev/null
+++ b/src/gnunet/service/gns/crypto_test.go
@@ -0,0 +1,150 @@
1package gns
2
3import (
4 "bytes"
5 "encoding/hex"
6 "testing"
7
8 "github.com/bfix/gospel/crypto/ed25519"
9)
10
11var (
12 PUB = []byte{
13 0x93, 0x34, 0x71, 0xF6, 0x99, 0x19, 0x0C, 0x62,
14 0x85, 0xC7, 0x9B, 0x83, 0x9D, 0xCA, 0x83, 0x91,
15 0x38, 0xFA, 0x87, 0xFB, 0xB8, 0xD4, 0xF6, 0xF0,
16 0xF0, 0x4B, 0x7F, 0x0A, 0x48, 0xBF, 0x95, 0xF7,
17 }
18 LABEL = "home"
19)
20
21func TestDeriveBlockKey(t *testing.T) {
22 var (
23 SKEY = []byte{
24 0x1D, 0x86, 0x8E, 0xF7, 0x30, 0x96, 0x3B, 0x39,
25 0x66, 0xE6, 0x49, 0xD8, 0xF1, 0x13, 0x18, 0x39,
26 0x8A, 0x7A, 0xB0, 0xF3, 0xDC, 0xF6, 0xE7, 0x2A,
27 0xF6, 0x65, 0xDE, 0x86, 0x47, 0x7B, 0x20, 0x1B,
28
29 0x21, 0xA6, 0xFA, 0x55, 0x7C, 0x29, 0xF5, 0x94,
30 0x8E, 0x9A, 0x80, 0xB0, 0xB6, 0xD5, 0x4D, 0x38,
31 0x0E, 0x6A, 0x0F, 0x42, 0x4B, 0x27, 0xBB, 0x6A,
32 0x1E, 0xD1, 0x33, 0x08, 0xD6, 0x2E, 0x21, 0x8C,
33 }
34 IV = []byte{
35 0xAC, 0x18, 0x03, 0xB7, 0x8B, 0x1E, 0x09, 0xA9,
36 0xD0, 0x20, 0x47, 0x2B, 0x1B, 0x23, 0xE8, 0x24,
37
38 0xC9, 0x23, 0x9E, 0x61, 0x3A, 0x8D, 0x95, 0xA9,
39 0x3F, 0x6C, 0x1C, 0xC8, 0xCB, 0xD1, 0xBD, 0x6B,
40 }
41 )
42
43 iv, skey := deriveBlockKey(LABEL, ed25519.NewPublicKeyFromBytes(PUB))
44
45 if bytes.Compare(IV[:16], iv.AESIv) != 0 {
46 t.Logf("AES_IV(computed) = %s\n", hex.EncodeToString(iv.AESIv))
47 t.Logf("AES_IV(expected) = %s\n", hex.EncodeToString(IV[:16]))
48 t.Fatal("AES IV mismatch")
49 }
50 if bytes.Compare(IV[16:], iv.TwofishIv) != 0 {
51 t.Logf("Twofish_IV(computed) = %s\n", hex.EncodeToString(iv.TwofishIv))
52 t.Logf("Twofish_IV(expected) = %s\n", hex.EncodeToString(IV[16:]))
53 t.Fatal("Twofish IV mismatch")
54 }
55
56 if bytes.Compare(SKEY[:32], skey.AESKey) != 0 {
57 t.Logf("AES_KEY(computed) = %s\n", hex.EncodeToString(skey.AESKey))
58 t.Logf("AES_KEY(expected) = %s\n", hex.EncodeToString(SKEY[:32]))
59 t.Fatal("AES KEY mismatch")
60 }
61 if bytes.Compare(SKEY[32:], skey.TwofishKey) != 0 {
62 t.Logf("Twofish_KEY(computed) = %s\n", hex.EncodeToString(skey.TwofishKey))
63 t.Logf("Twofish_KEY(expected) = %s\n", hex.EncodeToString(SKEY[32:]))
64 t.Fatal("Twofish KEY mismatch")
65 }
66}
67
68func TestDecryptBlock(t *testing.T) {
69 var (
70 DATA = []byte{
71 0xAC, 0xA5, 0x3C, 0x55, 0x63, 0x21, 0x31, 0x1F,
72 0x11, 0x6E, 0xEF, 0x48, 0xED, 0x53, 0x46, 0x31,
73 0x7C, 0x50, 0xFB, 0x6B, 0xA6, 0xC8, 0x6C, 0x46,
74 0x1E, 0xE3, 0xCA, 0x45, 0xCD, 0x5B, 0xD6, 0x86,
75 0x42, 0x87, 0xEF, 0x18, 0xCE, 0x8E, 0x83, 0x21,
76 0x04, 0xCB, 0xCF, 0x40, 0x7E, 0x0F, 0x51, 0x54,
77 0xE2, 0x3C, 0xDE, 0xE9, 0x22, 0x00, 0xFF, 0x40,
78 0xBB, 0x53, 0xE3, 0x69, 0x99, 0x92, 0x47, 0x97,
79 0xF0, 0x4E, 0x3B, 0x70,
80 }
81 OUT = []byte{
82 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0xAD, 0x0E,
83 0x60, 0x28, 0xFE, 0x80, 0x00, 0x00, 0x00, 0x10,
84 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
85 0x0A, 0x68, 0x6F, 0x69, 0x2D, 0x70, 0x6F, 0x6C,
86 0x6C, 0x6F, 0x69, 0x03, 0x6F, 0x72, 0x67, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00,
91 }
92 )
93
94 out, err := DecryptBlock(DATA, ed25519.NewPublicKeyFromBytes(PUB), LABEL)
95 if err != nil {
96 t.Fatal(err)
97 }
98 if bytes.Compare(out, OUT) != 0 {
99 t.Logf("Decrypt(computed) = %s\n", hex.EncodeToString(out))
100 t.Logf("Decrypt(expected) = %s\n", hex.EncodeToString(OUT))
101 t.Fatal("Decryptions failed")
102 }
103}
104
105func TestVerifyBlock(t *testing.T) {
106 var (
107 SIGNED = []byte{
108 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x0f,
109 0x00, 0x05, 0xad, 0x0e, 0x60, 0x28, 0xfe, 0x80,
110 0xac, 0xa5, 0x3c, 0x55, 0x63, 0x21, 0x31, 0x1f,
111 0x11, 0x6e, 0xef, 0x48, 0xed, 0x53, 0x46, 0x31,
112 0x7c, 0x50, 0xfb, 0x6b, 0xa6, 0xc8, 0x6c, 0x46,
113 0x1e, 0xe3, 0xca, 0x45, 0xcd, 0x5b, 0xd6, 0x86,
114 0x42, 0x87, 0xef, 0x18, 0xce, 0x8e, 0x83, 0x21,
115 0x04, 0xcb, 0xcf, 0x40, 0x7e, 0x0f, 0x51, 0x54,
116 0xe2, 0x3c, 0xde, 0xe9, 0x22, 0x00, 0xff, 0x40,
117 0xbb, 0x53, 0xe3, 0x69, 0x99, 0x92, 0x47, 0x97,
118 0xf0, 0x4e, 0x3b, 0x70,
119 }
120 SIG = []byte{
121 0x09, 0xc9, 0x6a, 0xda, 0x69, 0xce, 0x7c, 0x91,
122 0xbd, 0xa4, 0x59, 0xdc, 0xc9, 0x76, 0xf4, 0x6c,
123 0x62, 0xb7, 0x79, 0x3f, 0x94, 0xb2, 0xf6, 0xf0,
124 0x90, 0x17, 0x4e, 0x2f, 0x68, 0x49, 0xf8, 0xcc,
125
126 0x0b, 0x77, 0x32, 0x32, 0x28, 0x77, 0x2d, 0x2a,
127 0x31, 0x31, 0xc1, 0x2c, 0x44, 0x18, 0xf2, 0x5f,
128 0x1a, 0xe9, 0x8b, 0x2e, 0x65, 0xca, 0x1d, 0xe8,
129 0x22, 0x82, 0x6a, 0x06, 0xe0, 0x6a, 0x5a, 0xe5,
130 }
131 PUB = []byte{
132 0x26, 0x84, 0x1b, 0x24, 0x35, 0xa4, 0x63, 0xe9,
133 0xf0, 0x48, 0xae, 0x3e, 0xf7, 0xe8, 0x1b, 0xca,
134 0x55, 0x9f, 0x4c, 0x1e, 0x16, 0x18, 0xa6, 0xd3,
135 0x5b, 0x91, 0x0d, 0x54, 0x31, 0x6e, 0xbf, 0x97,
136 }
137 )
138 sig, err := ed25519.NewEcSignatureFromBytes(SIG)
139 if err != nil {
140 t.Fatal(err)
141 }
142 dkey := ed25519.NewPublicKeyFromBytes(PUB)
143 ok, err := dkey.EcVerify(SIGNED, sig)
144 if err != nil {
145 t.Fatal(err)
146 }
147 if !ok {
148 t.Fatal("EcDSA verify failed")
149 }
150}
diff --git a/src/gnunet/service/gns/gns.go b/src/gnunet/service/gns/gns.go
new file mode 100644
index 0000000..4156e2a
--- /dev/null
+++ b/src/gnunet/service/gns/gns.go
@@ -0,0 +1,248 @@
1package gns
2
3import (
4 "encoding/hex"
5 "io"
6 "time"
7
8 "github.com/bfix/gospel/crypto/ed25519"
9 "github.com/bfix/gospel/logger"
10 "gnunet/config"
11 "gnunet/crypto"
12 "gnunet/enums"
13 "gnunet/message"
14 "gnunet/service"
15 "gnunet/transport"
16 "gnunet/util"
17)
18
19//----------------------------------------------------------------------
20// "GNUnet Name System" service implementation
21//----------------------------------------------------------------------
22
23// GNSService
24type GNSService struct {
25}
26
27// NewGNSService
28func NewGNSService() service.Service {
29 return &GNSService{}
30}
31
32// Start the GNS service
33func (s *GNSService) Start(spec string) error {
34 return nil
35}
36
37// Stop the GNS service
38func (s *GNSService) Stop() error {
39 return nil
40}
41
42// Serve a client channel.
43func (s *GNSService) ServeClient(mc *transport.MsgChannel) {
44 for {
45 // receive next message from client
46 msg, err := mc.Receive()
47 if err != nil {
48 if err == io.EOF {
49 logger.Println(logger.INFO, "[gns] Client channel closed.")
50 } else {
51 logger.Printf(logger.ERROR, "[gns] Message-receive failed: %s\n", err.Error())
52 }
53 break
54 }
55 logger.Printf(logger.INFO, "[gns] Received msg: %v\n", msg)
56
57 // perform lookup
58 var resp message.Message
59 switch m := msg.(type) {
60 case *message.GNSLookupMsg:
61 //----------------------------------------------------------
62 // GNS_LOOKUP
63 //----------------------------------------------------------
64 logger.Println(logger.INFO, "[gns] Lookup request received.")
65 respX := message.NewGNSLookupResultMsg(m.Id)
66 resp = respX
67
68 // perform lookup on block (either from Namecache or DHT)
69 // TODO: run code in a go routine concurrently (would need
70 // access to the message channel to send responses)
71 block, err := s.Lookup(m)
72 if err != nil {
73 logger.Printf(logger.ERROR, "[gns] Failed to lookup block: %s\n", err.Error())
74 break
75 }
76 // handle block
77 if block != nil {
78 logger.Printf(logger.DBG, "[gns] Received block data: %s\n", hex.EncodeToString(block.Block.Data))
79
80 // get records from block
81 records, err := block.Records()
82 if err != nil {
83 logger.Printf(logger.ERROR, "[gns] Failed to extract records: %s\n", err.Error())
84 break
85 }
86 if len(records) == 0 {
87 logger.Println(logger.WARN, "[gns] No records in block")
88 break
89 }
90 // process records
91 for i, rec := range records {
92 logger.Printf(logger.DBG, "[gns] Record #%d: %v\n", i, rec)
93
94 // is this the record type we are looking for?
95 if rec.Type == m.Type || int(m.Type) == enums.GNS_TYPE_ANY {
96 // add it to the response message
97 respX.AddRecord(rec)
98 }
99 }
100 }
101
102 default:
103 //----------------------------------------------------------
104 // UNKNOWN message type received
105 //----------------------------------------------------------
106 logger.Printf(logger.ERROR, "[gns] Unhandled message of type (%d)\n", msg.Header().MsgType)
107 continue
108 }
109
110 // send response
111 if err := mc.Send(resp); err != nil {
112 logger.Printf(logger.ERROR, "[gns] Failed to send response: %s\n", err.Error())
113 }
114
115 }
116 // close client connection
117 mc.Close()
118}
119
120// Lookup handles GNU_LOOKUP messages
121func (s *GNSService) Lookup(m *message.GNSLookupMsg) (block *GNSBlock, err error) {
122 // create DHT/NAMECACHE query
123 pkey := ed25519.NewPublicKeyFromBytes(m.Zone)
124 label := m.GetName()
125 query := QueryFromPublickeyDerive(pkey, label)
126
127 // try namecache lookup first
128 if block, err = s.LookupNamecache(query, pkey, label); err != nil {
129 logger.Printf(logger.ERROR, "gns.Lookup(namecache): %s\n", err.Error())
130 block = nil
131 return
132 }
133 if block == nil {
134 logger.Println(logger.DBG, "gns.Lookup(namecache): no block found")
135 if int(m.Options) == enums.GNS_LO_DEFAULT {
136 // get the block from the DHT
137 if block, err = s.LookupDHT(query, pkey, label); err != nil || block == nil {
138 if err != nil {
139 logger.Printf(logger.ERROR, "gns.Lookup(dht): %s\n", err.Error())
140 block = nil
141 } else {
142 logger.Println(logger.DBG, "gns.Lookup(dht): no block found")
143 }
144 // lookup fails completely -- no result
145 }
146 }
147 }
148 return
149}
150
151// LookupNamecache
152func (s *GNSService) LookupNamecache(query *crypto.HashCode, zoneKey *ed25519.PublicKey, label string) (block *GNSBlock, err error) {
153 logger.Printf(logger.DBG, "[gns] LookupNamecache(%s)...\n", hex.EncodeToString(query.Bits))
154
155 // assemble Namecache request
156 req := message.NewNamecacheLookupMsg(query)
157 req.Id = uint32(util.NextID())
158 block = nil
159
160 // get response from Namecache service
161 var resp message.Message
162 if resp, err = service.ServiceRequestResponse("gns", "Namecache", config.Cfg.Namecache.Endpoint, req); err != nil {
163 return
164 }
165
166 // handle message depending on its type
167 logger.Println(logger.DBG, "[gns] Handling response from Namecache service")
168 switch m := resp.(type) {
169 case *message.NamecacheLookupResultMsg:
170 // check for matching IDs
171 if m.Id != req.Id {
172 logger.Println(logger.ERROR, "[gns] Got response for unknown ID")
173 break
174 }
175 // check if block was found
176 if len(m.EncData) == 0 {
177 logger.Println(logger.DBG, "[gns] block not found in namecache")
178 break
179 }
180 // check if record has expired
181 if m.Expire > 0 && int64(m.Expire) < time.Now().Unix() {
182 logger.Printf(logger.ERROR, "[gns] block expired at %s\n", util.Timestamp(m.Expire))
183 break
184 }
185
186 // assemble the GNSBlock from message
187 block = new(GNSBlock)
188 block.Signature = m.Signature
189 block.DerivedKey = m.DerivedKey
190 sb := new(SignedBlockData)
191 sb.Purpose = new(crypto.SignaturePurpose)
192 sb.Purpose.Purpose = enums.SIG_GNS_RECORD_SIGN
193 sb.Purpose.Size = uint32(16 + len(m.EncData))
194 sb.Expire = m.Expire
195 sb.Data = m.EncData
196 block.Block = sb
197
198 // verify and decrypt block
199 if err = block.Verify(zoneKey, label); err != nil {
200 break
201 }
202 if err = block.Decrypt(zoneKey, label); err != nil {
203 break
204 }
205 }
206 return
207}
208
209// LookupDHT
210func (s *GNSService) LookupDHT(query *crypto.HashCode, zoneKey *ed25519.PublicKey, label string) (block *GNSBlock, err error) {
211 logger.Printf(logger.DBG, "[gns] LookupDHT(%s)...\n", hex.EncodeToString(query.Bits))
212
213 // assemble DHT request
214 req := message.NewDHTClientGetMsg(query)
215 req.Id = uint64(util.NextID())
216 req.ReplLevel = uint32(enums.DHT_GNS_REPLICATION_LEVEL)
217 req.Type = uint32(enums.BLOCK_TYPE_GNS_NAMERECORD)
218 req.Options = uint32(enums.DHT_RO_DEMULTIPLEX_EVERYWHERE)
219 block = nil
220
221 // get response from DHT service
222 var resp message.Message
223 if resp, err = service.ServiceRequestResponse("gns", "DHT", config.Cfg.DHT.Endpoint, req); err != nil {
224 return
225 }
226
227 // handle message depending on its type
228 logger.Println(logger.DBG, "[gns] Handling response from DHT service")
229 switch m := resp.(type) {
230 case *message.DHTClientResultMsg:
231 // check for matching IDs
232 if m.Id != req.Id {
233 logger.Println(logger.ERROR, "[gns] Got response for unknown ID")
234 break
235 }
236 // check if block was found
237 if len(m.Data) == 0 {
238 logger.Println(logger.DBG, "[gns] block not found in DHT")
239 break
240 }
241 // check if record has expired
242 if m.Expire > 0 && int64(m.Expire) < time.Now().Unix() {
243 logger.Printf(logger.ERROR, "[gns] block expired at %s\n", util.Timestamp(m.Expire))
244 break
245 }
246 }
247 return
248}
diff --git a/src/gnunet/service/gns/record.go b/src/gnunet/service/gns/record.go
new file mode 100644
index 0000000..4825432
--- /dev/null
+++ b/src/gnunet/service/gns/record.go
@@ -0,0 +1,111 @@
1package gns
2
3import (
4 "fmt"
5
6 "github.com/bfix/gospel/crypto/ed25519"
7 "github.com/bfix/gospel/data"
8 "gnunet/crypto"
9 "gnunet/message"
10)
11
12var (
13 ErrBlockNotDecrypted = fmt.Errorf("GNS block not decrypted")
14)
15
16type GNSRecordSet struct {
17 Count uint32 `order:"big"` // number of resource records
18 Records []*message.GNSResourceRecord `size:"Count"` // list of resource records
19 Padding []byte `size:"*"` // padding
20}
21
22func NewGNSRecordSet() *GNSRecordSet {
23 return &GNSRecordSet{
24 Count: 0,
25 Records: make([]*message.GNSResourceRecord, 0),
26 Padding: make([]byte, 0),
27 }
28}
29
30type SignedBlockData struct {
31 Purpose *crypto.SignaturePurpose // Size and purpose of signature (8 bytes)
32 Expire uint64 `order:"big"` // Expiration time of the block.
33 Data []byte `size:"*"` // (encrypted) GNSRecordSet
34}
35
36type GNSBlock struct {
37 Signature []byte `size:"64"` // Signature of the block.
38 DerivedKey []byte `size:"32"` // Derived key used for signing
39 Block *SignedBlockData
40
41 checked bool // block integrity checked
42 verified bool // block signature verified (internal)
43 decrypted bool // block data decrypted (internal)
44}
45
46func (b *GNSBlock) String() string {
47 return fmt.Sprintf("GNSBlock{Verified=%v,Decrypted=%v,data=[%d]}",
48 b.verified, b.decrypted, len(b.Block.Data))
49}
50
51func (b *GNSBlock) Records() ([]*message.GNSResourceRecord, error) {
52 // check if block is decrypted
53 if !b.decrypted {
54 return nil, ErrBlockNotDecrypted
55 }
56 // parse block data into record set
57 rs := NewGNSRecordSet()
58 if err := data.Unmarshal(rs, b.Block.Data); err != nil {
59 return nil, err
60 }
61 return rs.Records, nil
62}
63
64func (b *GNSBlock) Verify(zoneKey *ed25519.PublicKey, label string) (err error) {
65 // Integrity check performed
66 b.checked = true
67
68 // verify derived key
69 dkey := ed25519.NewPublicKeyFromBytes(b.DerivedKey)
70 dkey2 := crypto.DerivePublicKey(zoneKey, label, "gns")
71 if !dkey.Q.Equals(dkey2.Q) {
72 return fmt.Errorf("Invalid signature key for GNS Block")
73 }
74 // verify signature
75 var (
76 sig *ed25519.EcSignature
77 buf []byte
78 ok bool
79 )
80 if sig, err = ed25519.NewEcSignatureFromBytes(b.Signature); err != nil {
81 return
82 }
83 if buf, err = data.Marshal(b.Block); err != nil {
84 return
85 }
86 if ok, err = dkey.EcVerify(buf, sig); err == nil && !ok {
87 err = fmt.Errorf("Signature verification failed for GNS block")
88 }
89 b.verified = true
90 return
91}
92
93func (b *GNSBlock) Decrypt(zoneKey *ed25519.PublicKey, label string) (err error) {
94 // decrypt payload
95 b.Block.Data, err = DecryptBlock(b.Block.Data, zoneKey, label)
96 b.decrypted = true
97 return
98}
99
100func NewGNSBlock() *GNSBlock {
101 return &GNSBlock{
102 Signature: make([]byte, 64),
103 DerivedKey: make([]byte, 32),
104 Block: &SignedBlockData{
105 Data: nil,
106 },
107 checked: false,
108 verified: false,
109 decrypted: false,
110 }
111}
diff --git a/src/gnunet/service/service.go b/src/gnunet/service/service.go
new file mode 100644
index 0000000..f43c385
--- /dev/null
+++ b/src/gnunet/service/service.go
@@ -0,0 +1,91 @@
1package service
2
3import (
4 "fmt"
5
6 "github.com/bfix/gospel/logger"
7 "gnunet/transport"
8)
9
10// Service is an interface for GNUnet services. Every service has one channel
11// end-point it listens to for incoming channel requests (network-based
12// channels established by service clients). The end-point is specified in
13// Channel semantics in the specification string.
14type Service interface {
15 Start(spec string) error
16 ServeClient(ch *transport.MsgChannel)
17 Stop() error
18}
19
20// ServiceImpl is an implementation of generic service functionality.
21type ServiceImpl struct {
22 impl Service
23 hdlr chan transport.Channel
24 srvc transport.ChannelServer
25 name string
26 running bool
27}
28
29// NewServiceImpl instantiates a new ServiceImpl object.
30func NewServiceImpl(name string, srv Service) *ServiceImpl {
31 return &ServiceImpl{
32 impl: srv,
33 hdlr: make(chan transport.Channel),
34 srvc: nil,
35 name: name,
36 running: false,
37 }
38}
39
40// Start a service
41func (si *ServiceImpl) Start(spec string) (err error) {
42 // check if we are already running
43 if si.running {
44 logger.Printf(logger.ERROR, "Service '%s' already running.\n", si.name)
45 return fmt.Errorf("service already running")
46 }
47
48 // start channel server
49 logger.Printf(logger.DBG, "[%s] Service starting.\n", si.name)
50 if si.srvc, err = transport.NewChannelServer(spec, si.hdlr); err != nil {
51 return
52 }
53 si.running = true
54
55 // handle clients
56 go func() {
57 loop:
58 for si.running {
59 select {
60 case in := <-si.hdlr:
61 if in == nil {
62 logger.Printf(logger.DBG, "[%s] Listener terminated.\n", si.name)
63 break loop
64 }
65 switch ch := in.(type) {
66 case transport.Channel:
67 logger.Printf(logger.DBG, "[%s] Client connected.\n", si.name)
68 go si.impl.ServeClient(transport.NewMsgChannel(ch))
69 }
70 default:
71 }
72 }
73 logger.Printf(logger.DBG, "[%s] Service closing.\n", si.name)
74 si.srvc.Close()
75 si.running = false
76 }()
77
78 return si.impl.Start(spec)
79}
80
81// Stop a service
82func (si *ServiceImpl) Stop() error {
83 if !si.running {
84 logger.Printf(logger.WARN, "Service '%s' not running.\n", si.name)
85 return fmt.Errorf("service not running")
86 }
87 si.running = false
88 logger.Printf(logger.DBG, "[%s] Service terminating.\n", si.name)
89
90 return si.impl.Stop()
91}
diff --git a/src/gnunet/transport/channel.go b/src/gnunet/transport/channel.go
new file mode 100644
index 0000000..8502d8f
--- /dev/null
+++ b/src/gnunet/transport/channel.go
@@ -0,0 +1,180 @@
1package transport
2
3import (
4 "encoding/hex"
5 "errors"
6 "fmt"
7 "strings"
8
9 "github.com/bfix/gospel/data"
10 "github.com/bfix/gospel/logger"
11 "gnunet/message"
12)
13
14var (
15 ErrChannelNotImplemented = fmt.Errorf("Protocol not implemented")
16 ErrChannelNotOpened = fmt.Errorf("Channel not opened")
17)
18
19////////////////////////////////////////////////////////////////////////
20// CHANNEL
21
22// Channel is an abstraction for exchanging arbitrary data over various
23// transport protocols and mechanisms. They are created by clients via
24// 'NewChannel()' or by services run via 'NewChannelServer()'.
25// A string specifies the end-point of the channel:
26// "unix+/tmp/test.sock" -- for UDS channels
27// "tcp+1.2.3.4:5" -- for TCP channels
28// "udp+1.2.3.4:5" -- for UDP channels
29type Channel interface {
30 Open(spec string) error
31 Close() error
32 Read([]byte) (int, error)
33 Write([]byte) (int, error)
34}
35
36// ChannelFactory instantiates specific Channel imülementations.
37type ChannelFactory func() Channel
38
39// Known channel implementations.
40var channelImpl = map[string]ChannelFactory{
41 "unix": NewSocketChannel,
42 "tcp": NewTCPChannel,
43 "udp": NewUDPChannel,
44}
45
46// NewChannel creates a new channel to the specified endpoint.
47// Called by a client to connect to a service.
48func NewChannel(spec string) (Channel, error) {
49 parts := strings.Split(spec, "+")
50 if fac, ok := channelImpl[parts[0]]; ok {
51 inst := fac()
52 err := inst.Open(spec)
53 return inst, err
54 }
55 return nil, ErrChannelNotImplemented
56}
57
58////////////////////////////////////////////////////////////////////////
59// CHANNEL SERVER
60
61// ChannelServer creates a listener for the specified endpoint.
62// The specification string has the same format as for Channel with slightly
63// different semantics (for TCP, and ICMP the address specifies is a mask
64// for client addresses accepted for a channel request).
65type ChannelServer interface {
66 Open(spec string, hdlr chan<- Channel) error
67 Close() error
68}
69
70// ChannelServerFactory instantiates specific ChannelServer imülementations.
71type ChannelServerFactory func() ChannelServer
72
73// Known channel server implementations.
74var channelServerImpl = map[string]ChannelServerFactory{
75 "unix": NewSocketChannelServer,
76 "tcp": NewTCPChannelServer,
77 "udp": NewUDPChannelServer,
78}
79
80// NewChannelServer
81func NewChannelServer(spec string, hdlr chan<- Channel) (ChannelServer, error) {
82 parts := strings.Split(spec, "+")
83 if fac, ok := channelServerImpl[parts[0]]; ok {
84 inst := fac()
85 err := inst.Open(spec, hdlr)
86 return inst, err
87 }
88 return nil, ErrChannelNotImplemented
89}
90
91////////////////////////////////////////////////////////////////////////
92// MESSAGE CHANNEL
93
94// MsgChannel s a wrapper around a generic channel for GNUnet message exchange.
95type MsgChannel struct {
96 ch Channel
97 buf []byte
98}
99
100// NewMsgChannel wraps a plain Channel for GNUnet message exchange.
101func NewMsgChannel(ch Channel) *MsgChannel {
102 return &MsgChannel{
103 ch: ch,
104 buf: make([]byte, 65536),
105 }
106}
107
108// Close a MsgChannel by closing the wrapped plain Channel.
109func (c *MsgChannel) Close() error {
110 return c.ch.Close()
111}
112
113// Send a GNUnet message over a channel.
114func (c *MsgChannel) Send(msg message.Message) error {
115
116 // convert message to binary data
117 data, err := data.Marshal(msg)
118 if err != nil {
119 return err
120 }
121 logger.Printf(logger.DBG, "==> %v\n", msg)
122 logger.Printf(logger.DBG, " [%s]\n", hex.EncodeToString(data))
123
124 // check message header size and packet size
125 mh, err := message.GetMsgHeader(data)
126 if err != nil {
127 return err
128 }
129 if len(data) != int(mh.MsgSize) {
130 return errors.New("Send: message size mismatch")
131 }
132
133 // send packet
134 n, err := c.ch.Write(data)
135 if err != nil {
136 return err
137 }
138 if n != len(data) {
139 return errors.New("Incomplete send")
140 }
141 return nil
142}
143
144// Receive GNUnet messages over a plain Channel.
145func (c *MsgChannel) Receive() (message.Message, error) {
146 get := func(pos, count int) error {
147 n, err := c.ch.Read(c.buf[pos : pos+count])
148 if err != nil {
149 return err
150 }
151 if n != count {
152 return errors.New("not enough bytes on network")
153 }
154 return nil
155 }
156 if err := get(0, 4); err != nil {
157 return nil, err
158 }
159 mh, err := message.GetMsgHeader(c.buf[:4])
160 if err != nil {
161 return nil, err
162 }
163
164 if err := get(4, int(mh.MsgSize)-4); err != nil {
165 return nil, err
166 }
167 msg, err := message.NewEmptyMessage(mh.MsgType)
168 if err != nil {
169 return nil, err
170 }
171 if msg == nil {
172 return nil, fmt.Errorf("Message{%d} is nil!\n", mh.MsgType)
173 }
174 if err = data.Unmarshal(msg, c.buf[:mh.MsgSize]); err != nil {
175 return nil, err
176 }
177 logger.Printf(logger.DBG, "<== %v\n", msg)
178 logger.Printf(logger.DBG, " [%s]\n", hex.EncodeToString(c.buf[:mh.MsgSize]))
179 return msg, nil
180}
diff --git a/src/gnunet/transport/channel_netw.go b/src/gnunet/transport/channel_netw.go
new file mode 100644
index 0000000..69ddda5
--- /dev/null
+++ b/src/gnunet/transport/channel_netw.go
@@ -0,0 +1,173 @@
1package transport
2
3import (
4 "net"
5 "os"
6 "strconv"
7 "strings"
8
9 "github.com/bfix/gospel/logger"
10)
11
12////////////////////////////////////////////////////////////////////////
13// Generic network-based Channel
14
15// NetworkChannel
16type NetworkChannel struct {
17 network string
18 conn net.Conn
19}
20
21// NewNetworkChannel
22func NewNetworkChannel(netw string) Channel {
23 return &NetworkChannel{
24 network: netw,
25 conn: nil,
26 }
27}
28
29// Open
30func (c *NetworkChannel) Open(spec string) (err error) {
31 parts := strings.Split(spec, "+")
32 // check for correct protocol
33 if parts[0] != c.network {
34 return ErrChannelNotImplemented
35 }
36 // open connection
37 c.conn, err = net.Dial(c.network, parts[1])
38 return
39}
40
41// Close
42func (c *NetworkChannel) Close() error {
43 if c.conn != nil {
44 return c.conn.Close()
45 }
46 return ErrChannelNotOpened
47}
48
49// Read
50func (c *NetworkChannel) Read(buf []byte) (int, error) {
51 if c.conn == nil {
52 return 0, ErrChannelNotOpened
53 }
54 return c.conn.Read(buf)
55}
56
57// Write
58func (c *NetworkChannel) Write(buf []byte) (int, error) {
59 if c.conn == nil {
60 return 0, ErrChannelNotOpened
61 }
62 return c.conn.Write(buf)
63}
64
65////////////////////////////////////////////////////////////////////////
66// Generic network-based ChannelServer
67
68// NetworkChannelServer
69type NetworkChannelServer struct {
70 network string
71 listener net.Listener
72}
73
74// NewNetworkChannelServer
75func NewNetworkChannelServer(netw string) ChannelServer {
76 return &NetworkChannelServer{
77 network: netw,
78 listener: nil,
79 }
80}
81
82// Open
83func (s *NetworkChannelServer) Open(spec string, hdlr chan<- Channel) (err error) {
84 parts := strings.Split(spec, "+")
85 // check for correct protocol
86 if parts[0] != s.network {
87 return ErrChannelNotImplemented
88 }
89 // create listener
90 if s.listener, err = net.Listen(s.network, parts[1]); err != nil {
91 return
92 }
93 // handle additional parameters ('key[=value]')
94 for _, param := range parts[2:] {
95 frag := strings.Split(param, "=")
96 switch frag[0] {
97 case "perm": // set permissions on 'unix'
98 if s.network == "unix" {
99 if perm, err := strconv.ParseInt(frag[1], 8, 32); err == nil {
100 if err := os.Chmod(parts[1], os.FileMode(perm)); err != nil {
101 logger.Printf(
102 logger.ERROR,
103 "NetworkChannelServer: Failed to set permissions: %s\n",
104 err.Error())
105
106 }
107 } else {
108 logger.Printf(
109 logger.ERROR,
110 "NetworkChannelServer: Invalid permissions '%s'\n",
111 frag[1])
112 }
113 }
114 }
115 }
116 // run go routine to handle channel requests from clients
117 go func() {
118 for {
119 conn, err := s.listener.Accept()
120 if err != nil {
121 // signal failure and terminate
122 hdlr <- nil
123 break
124 }
125 // send channel to handler
126 hdlr <- &NetworkChannel{
127 network: s.network,
128 conn: conn,
129 }
130 }
131 if s.listener != nil {
132 s.listener.Close()
133 }
134 }()
135
136 return nil
137}
138
139// Close
140func (s *NetworkChannelServer) Close() error {
141 if s.listener != nil {
142 err := s.listener.Close()
143 s.listener = nil
144 return err
145 }
146 return nil
147}
148
149////////////////////////////////////////////////////////////////////////
150
151func NewSocketChannel() Channel {
152 return NewNetworkChannel("unix")
153}
154
155func NewTCPChannel() Channel {
156 return NewNetworkChannel("tcp")
157}
158
159func NewUDPChannel() Channel {
160 return NewNetworkChannel("udp")
161}
162
163func NewSocketChannelServer() ChannelServer {
164 return NewNetworkChannelServer("unix")
165}
166
167func NewTCPChannelServer() ChannelServer {
168 return NewNetworkChannelServer("tcp")
169}
170
171func NewUDPChannelServer() ChannelServer {
172 return NewNetworkChannelServer("udp")
173}
diff --git a/src/gnunet/transport/channel_test.go b/src/gnunet/transport/channel_test.go
new file mode 100644
index 0000000..c59e3e1
--- /dev/null
+++ b/src/gnunet/transport/channel_test.go
@@ -0,0 +1,203 @@
1package transport
2
3import (
4 "bytes"
5 "fmt"
6 "testing"
7 "time"
8)
9
10const (
11 SOCK_ADDR = "/tmp/gnunet-go-test.sock"
12 TCP_ADDR_CLIENT = "gnunet.org:80"
13 TCP_ADDR_SERVER = "127.0.0.1:12086"
14)
15
16type TestChannelServer struct {
17 hdlr chan Channel
18 srvc ChannelServer
19 running bool
20}
21
22func NewTestChannelServer() *TestChannelServer {
23 return &TestChannelServer{
24 hdlr: make(chan Channel),
25 srvc: nil,
26 running: false,
27 }
28}
29
30func (s *TestChannelServer) handle(ch Channel) {
31 buf := make([]byte, 4096)
32 for {
33 n, err := ch.Read(buf)
34 if err != nil {
35 break
36 }
37 _, err = ch.Write(buf[:n])
38 if err != nil {
39 break
40 }
41 }
42 ch.Close()
43}
44
45func (s *TestChannelServer) Start(spec string) (err error) {
46 // check if we are already running
47 if s.running {
48 return fmt.Errorf("Server already running")
49 }
50
51 // start channel server
52 if s.srvc, err = NewChannelServer(spec, s.hdlr); err != nil {
53 return
54 }
55 s.running = true
56
57 // handle clients
58 go func() {
59 for s.running {
60 select {
61 case in := <-s.hdlr:
62 if in == nil {
63 break
64 }
65 switch x := in.(type) {
66 case Channel:
67 go s.handle(x)
68 }
69 }
70 }
71 s.srvc.Close()
72 s.running = false
73 }()
74 return nil
75}
76
77func (s *TestChannelServer) Stop() {
78 s.running = false
79}
80
81func TestChannelServerTCPSingle(t *testing.T) {
82 time.Sleep(time.Second)
83 s := NewTestChannelServer()
84 if err := s.Start("tcp+" + TCP_ADDR_SERVER); err != nil {
85 t.Fatal(err)
86 }
87 s.Stop()
88}
89
90func TestChannelServerTCPTwice(t *testing.T) {
91 time.Sleep(time.Second)
92 s1 := NewTestChannelServer()
93 if err := s1.Start("tcp+" + TCP_ADDR_SERVER); err != nil {
94 t.Fatal(err)
95 }
96 s2 := NewTestChannelServer()
97 if err := s2.Start("tcp+" + TCP_ADDR_SERVER); err == nil {
98 t.Fatal("SocketServer started twice!!")
99 }
100 s1.Stop()
101}
102
103func TestChannelClientTCP(t *testing.T) {
104 time.Sleep(time.Second)
105 ch, err := NewChannel("tcp+" + TCP_ADDR_CLIENT)
106 if err != nil {
107 t.Fatal(err)
108 }
109 msg := []byte("GET /\n\n")
110 n, err := ch.Write(msg)
111 if err != nil {
112 t.Fatal(err)
113 }
114 if n != len(msg) {
115 t.Fatal("Send size mismatch")
116 }
117 buf := make([]byte, 4096)
118 n = 0
119 start := time.Now().Unix()
120 for n == 0 && (time.Now().Unix()-start) < 3 {
121 if n, err = ch.Read(buf); err != nil {
122 t.Fatal(err)
123 }
124 }
125 if err = ch.Close(); err != nil {
126 t.Fatal(err)
127 }
128 t.Logf("'%s' [%d]\n", string(buf[:n]), n)
129}
130
131func TestChannelClientServerTCP(t *testing.T) {
132 time.Sleep(time.Second)
133 s := NewTestChannelServer()
134 if err := s.Start("tcp+" + TCP_ADDR_SERVER); err != nil {
135 t.Fatal(err)
136 }
137
138 ch, err := NewChannel("tcp+" + TCP_ADDR_SERVER)
139 if err != nil {
140 t.Fatal(err)
141 }
142 msg := []byte("GET /\n\n")
143 n, err := ch.Write(msg)
144 if err != nil {
145 t.Fatal(err)
146 }
147 if n != len(msg) {
148 t.Fatal("Send size mismatch")
149 }
150 buf := make([]byte, 4096)
151 n = 0
152 start := time.Now().Unix()
153 for n == 0 && (time.Now().Unix()-start) < 3 {
154 if n, err = ch.Read(buf); err != nil {
155 t.Fatal(err)
156 }
157 }
158 if err = ch.Close(); err != nil {
159 t.Fatal(err)
160 }
161 if bytes.Compare(buf[:n], msg) != 0 {
162 t.Fatal("message send/receive mismatch")
163 }
164
165 s.Stop()
166}
167
168func TestChannelClientServerSock(t *testing.T) {
169 time.Sleep(time.Second)
170 s := NewTestChannelServer()
171 if err := s.Start("unix+" + SOCK_ADDR); err != nil {
172 t.Fatal(err)
173 }
174
175 ch, err := NewChannel("unix+" + SOCK_ADDR)
176 if err != nil {
177 t.Fatal(err)
178 }
179 msg := []byte("This is just a test -- please ignore...")
180 n, err := ch.Write(msg)
181 if err != nil {
182 t.Fatal(err)
183 }
184 if n != len(msg) {
185 t.Fatal("Send size mismatch")
186 }
187 buf := make([]byte, 4096)
188 n = 0
189 start := time.Now().Unix()
190 for n == 0 && (time.Now().Unix()-start) < 3 {
191 if n, err = ch.Read(buf); err != nil {
192 t.Fatal(err)
193 }
194 }
195 if err = ch.Close(); err != nil {
196 t.Fatal(err)
197 }
198 if bytes.Compare(buf[:n], msg) != 0 {
199 t.Fatal("message send/receive mismatch")
200 }
201
202 s.Stop()
203}
diff --git a/src/gnunet/transport/connection.go b/src/gnunet/transport/connection.go
new file mode 100644
index 0000000..e66bec1
--- /dev/null
+++ b/src/gnunet/transport/connection.go
@@ -0,0 +1,52 @@
1package transport
2
3import (
4 "gnunet/core"
5 "gnunet/message"
6)
7
8////////////////////////////////////////////////////////////////////////
9// Connection for communicating peers
10type Connection struct {
11 from, to *core.Peer
12 ch *MsgChannel
13 buf []byte
14 bandwidth uint32
15 init bool
16 state int
17 shared []byte
18}
19
20func NewConnection(ch *MsgChannel, from, to *core.Peer) *Connection {
21 return &Connection{
22 from: from,
23 to: to,
24 state: 1,
25 ch: ch,
26 }
27}
28
29func (c *Connection) SharedSecret(secret []byte) {
30 c.shared = make([]byte, len(secret))
31 copy(c.shared, secret)
32}
33
34func (c *Connection) GetState() int {
35 return c.state
36}
37
38func (c *Connection) SetBandwidth(bw uint32) {
39 c.bandwidth = bw
40}
41
42func (c *Connection) Close() error {
43 return c.ch.Close()
44}
45
46func (c *Connection) Send(msg message.Message) error {
47 return c.ch.Send(msg)
48}
49
50func (c *Connection) Receive() (message.Message, error) {
51 return c.ch.Receive()
52}
diff --git a/src/gnunet/transport/session.go b/src/gnunet/transport/session.go
new file mode 100644
index 0000000..90e4016
--- /dev/null
+++ b/src/gnunet/transport/session.go
@@ -0,0 +1,12 @@
1package transport
2
3import ()
4
5const (
6 KX_STATE_DOWN = iota // No handshake yet.
7 KX_STATE_KEY_SENT // We've sent our session key.
8 KX_STATE_KEY_RECEIVED // We've received the other peers session key.
9 KX_STATE_UP // Key exchange is done.
10 KX_STATE_REKEY_SENT // We're rekeying (or had a timeout).
11 KX_PEER_DISCONNECT // Last state of a KX (when it is being terminated).
12)
diff --git a/src/gnunet/util/address.go b/src/gnunet/util/address.go
new file mode 100644
index 0000000..04e2254
--- /dev/null
+++ b/src/gnunet/util/address.go
@@ -0,0 +1,39 @@
1package util
2
3import (
4 "fmt"
5)
6
7type IPAddress struct {
8 Host []byte `size:"*-2"`
9 Port uint16 `order:"big"`
10}
11
12func NewIPAddress(host []byte, port uint16) *IPAddress {
13 ip := &IPAddress{
14 Host: make([]byte, len(host)),
15 Port: port,
16 }
17 copy(ip.Host, host)
18 return ip
19}
20
21type Address struct {
22 Transport string
23 Options uint32 `order:"big"`
24 Address []byte `size:"*"`
25}
26
27func NewAddress(transport string, addr []byte) *Address {
28 a := &Address{
29 Transport: transport,
30 Options: 0,
31 Address: make([]byte, len(addr)),
32 }
33 copy(a.Address, addr)
34 return a
35}
36
37func (a *Address) String() string {
38 return fmt.Sprintf("Address{%s}", AddressString(a.Transport, a.Address))
39}
diff --git a/src/gnunet/util/array.go b/src/gnunet/util/array.go
new file mode 100644
index 0000000..2ffb618
--- /dev/null
+++ b/src/gnunet/util/array.go
@@ -0,0 +1,48 @@
1package util
2
3import (
4 "fmt"
5)
6
7var (
8 ErrUtilArrayTooSmall = fmt.Errorf("Array to small")
9)
10
11func Clone(d []byte) []byte {
12 r := make([]byte, len(d))
13 copy(r, d)
14 return r
15}
16
17func Reverse(b []byte) []byte {
18 bl := len(b)
19 r := make([]byte, bl)
20 for i := 0; i < bl; i++ {
21 r[bl-i-1] = b[i]
22 }
23 return r
24}
25
26// CopyBlock copies 'in' to 'out' so that 'out' is filled completely.
27// - If 'in' is larger than 'out', it is left-truncated before copy
28// - If 'in' is smaller than 'out', it is left-padded with 0 before copy
29func CopyBlock(out, in []byte) {
30 count := len(in)
31 size := len(out)
32 from, to := 0, 0
33 if count > size {
34 from = count - size
35 } else if count < size {
36 to = size - count
37 for i := 0; i < to; i++ {
38 out[i] = 0
39 }
40 }
41 copy(out[to:], in[from:])
42}
43
44func Fill(b []byte, val byte) {
45 for i := 0; i < len(b); i++ {
46 b[i] = val
47 }
48}
diff --git a/src/gnunet/util/base32.go b/src/gnunet/util/base32.go
new file mode 100644
index 0000000..ff5711e
--- /dev/null
+++ b/src/gnunet/util/base32.go
@@ -0,0 +1,109 @@
1package util
2
3import (
4 "errors"
5 "strings"
6)
7
8//------------------------------------------------------------------------
9// Base32 conversion between binary data and string representation
10//------------------------------------------------------------------------
11//
12// A binary array of size m is viewed as a consecutive stream of bits
13// from left to right. Bytes are ordered with ascending address, while
14// bits (in a byte) are ordered MSB to LSB.
15
16// For encoding the stream is partitioned into 5-bit chunks; the last chunk
17// is right-padded with 0's if 8*m is not divisible by 5. Each chunk (value
18// between 0 and 31) is encoded into a character; the mapping for encoding
19// is the same as in [https://www.crockford.com/wrmg/base32.html].
20//
21// For decoding each character is converted to a 5-bit chunk based on the
22// encoder mapping (with one addition: the character 'U' maps to the value
23// 27). The chunks are concatenated to produce the bit stream to be stored
24// in the output array.
25
26// character set used for encoding/decoding
27const xlate = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
28
29var (
30 // ErrInvalidEncoding signals an invalid encoding
31 ErrInvalidEncoding = errors.New("Invalid encoding")
32 // ErrBufferTooSmall signalsa too small buffer for decoding
33 ErrBufferTooSmall = errors.New("Buffer to small")
34)
35
36// EncodeBinaryToString encodes a byte array into a string.
37func EncodeBinaryToString(data []byte) string {
38 size, pos, bits, n := len(data), 0, 0, 0
39 out := ""
40 for {
41 if n < 5 {
42 if pos < size {
43 bits = (bits << 8) | (int(data[pos]) & 0xFF)
44 pos++
45 n += 8
46 } else if n > 0 {
47 bits <<= uint(5 - n)
48 n = 5
49 } else {
50 break
51 }
52 }
53 out += string(xlate[(bits>>uint(n-5))&0x1F])
54 n -= 5
55 }
56 return out
57}
58
59// DecodeStringToBinary decodes a string into a byte array.
60// The function expects the size of the output buffer to be sepcified as an
61// argument ('num'); the function returns an error if the buffer is overrun
62// or if an invalid character is found in the encoded string. If the decoded
63// bit stream is smaller than the output buffer, it is padded with 0's.
64func DecodeStringToBinary(s string, num int) ([]byte, error) {
65 size := len(s)
66 out := make([]byte, num)
67 rpos, wpos, n, bits := 0, 0, 0, 0
68 for {
69 if n < 8 {
70 if rpos < size {
71 c := rune(s[rpos])
72 rpos++
73 v := strings.IndexRune(xlate, c)
74 if v == -1 {
75 switch c {
76 case 'O':
77 v = 0
78 case 'I', 'L':
79 v = 1
80 case 'U':
81 v = 27
82 default:
83 return nil, ErrInvalidEncoding
84 }
85 }
86 bits = (bits << 5) | (v & 0x1F)
87 n += 5
88 } else {
89 if wpos < num {
90 out[wpos] = byte(bits & ((1 << uint(n+1)) - 1))
91 wpos++
92 for i := wpos; i < num; i++ {
93 out[i] = 0
94 }
95 }
96 break
97 }
98 } else {
99 if wpos < num {
100 out[wpos] = byte((bits >> uint(n-8)) & 0xFF)
101 wpos++
102 n -= 8
103 } else {
104 return nil, ErrBufferTooSmall
105 }
106 }
107 }
108 return out, nil
109}
diff --git a/src/gnunet/util/base32_test.go b/src/gnunet/util/base32_test.go
new file mode 100644
index 0000000..e89109d
--- /dev/null
+++ b/src/gnunet/util/base32_test.go
@@ -0,0 +1,86 @@
1package util
2
3import (
4 "bytes"
5 "crypto/rand"
6 "encoding/hex"
7 "testing"
8)
9
10var (
11 tests = []struct {
12 bin []byte
13 str string
14 }{
15 {[]byte{
16 0xD4,
17 }, "TG"},
18 {[]byte{
19 0x78, 0xD3,
20 }, "F39G"},
21 {[]byte{
22 0x43, 0xA4, 0x59, 0x57,
23 }, "8EJ5JNR"},
24 {[]byte{
25 0x59, 0x40, 0xB3, 0x2D, 0xB8, 0x86, 0x61, 0xC2,
26 }, "B50B6BDRGSGW4"},
27 {[]byte{
28 0xF9, 0x7F, 0x85, 0x6D, 0x8D, 0x8D, 0x65, 0x91,
29 0x50, 0x3A, 0x2F, 0x36, 0x9F, 0x63, 0x01, 0x45,
30 }, "Z5ZRAVCDHNJS2M1T5WV9YRR18M"},
31 {[]byte{
32 0x7B, 0x46, 0x0D, 0xFD, 0xC9, 0x04, 0xA6, 0x99,
33 0x54, 0x94, 0xB0, 0xCE, 0xFE, 0x17, 0x72, 0x31,
34 0xC8, 0x90, 0xBA, 0x9F, 0x3C, 0xD1, 0x42, 0xA1,
35 }, "FD30VZE90JK9JN4MP37FW5VJ67491EMZ7K8M588"},
36 {[]byte{
37 0xC0, 0x78, 0x05, 0x04, 0xB8, 0xE2, 0x4A, 0xA5,
38 0x61, 0x82, 0xCE, 0xCC, 0xE3, 0xCA, 0x53, 0x01,
39 0x67, 0x5F, 0xA3, 0x05, 0xA9, 0x27, 0xC5, 0xE2,
40 0x6B, 0xB5, 0xB5, 0x86, 0xAB, 0x84, 0x32, 0x6C,
41 }, "R1W0A15RW95AARC2SV6E7JJK05KNZ8R5N4KWBRKBPPTRDAW469P0"},
42 }
43)
44
45func TestBase32Preset(t *testing.T) {
46 for _, x := range tests {
47 s := EncodeBinaryToString(x.bin)
48 if testing.Verbose() {
49 t.Logf("[%s] ==> %s\n", hex.EncodeToString(x.bin), s)
50 }
51 if s != x.str {
52 t.Fatalf("Encoding mismatch: '%s' != '%s' for %s\n", s, x.str, hex.EncodeToString(x.bin))
53 }
54 e, err := DecodeStringToBinary(x.str, len(x.bin))
55 if err != nil {
56 t.Fatal(err)
57 }
58 if bytes.Compare(x.bin, e) != 0 {
59 t.Fatalf("Decoding mismatch: '%s' != '%s' for '%s'\n", hex.EncodeToString(e), hex.EncodeToString(x.bin), x.str)
60 }
61 }
62}
63
64func TestBase32Random(t *testing.T) {
65 buf := make([]byte, 32)
66 for i := 0; i < 100; i++ {
67 n, err := rand.Read(buf)
68 if err != nil || n != 32 {
69 t.Fatal(err)
70 }
71 s := EncodeBinaryToString(buf)
72 r, err := DecodeStringToBinary(s, len(buf))
73 if err != nil {
74 t.Fatal(err)
75 }
76 if len(buf) != len(r) {
77 x := make([]byte, len(buf))
78 n := len(buf) - len(r)
79 copy(x[n:], r)
80 r = x
81 }
82 if !bytes.Equal(buf, r) {
83 t.Fatal("Encode/Decode mismatch")
84 }
85 }
86}
diff --git a/src/gnunet/util/format.go b/src/gnunet/util/format.go
new file mode 100644
index 0000000..b52418f
--- /dev/null
+++ b/src/gnunet/util/format.go
@@ -0,0 +1,36 @@
1package util
2
3import (
4 "encoding/hex"
5 "fmt"
6 "net"
7 "time"
8)
9
10func AddressString(transport string, addr []byte) string {
11 if transport == "tcp" || transport == "udp" {
12 alen := len(addr)
13 port := uint(addr[alen-2])*256 + uint(addr[alen-1])
14 return fmt.Sprintf("%s:%s:%d", transport, net.IP(addr[:alen-2]).String(), port)
15 }
16 return fmt.Sprintf("%s:%s", transport, hex.EncodeToString(addr))
17}
18
19func Timestamp(ts uint64) string {
20 t := time.Unix(int64(ts/(1000*1000)), int64((ts%1000)*1000))
21 return t.Format(time.RFC3339Nano)
22}
23
24var scale = " kMGTPEO"
25
26func Scale1024(n uint64) string {
27 v := float64(n)
28 var i int
29 for i = 0; v > 1024; i++ {
30 v /= 1024
31 }
32 if i == 0 {
33 return fmt.Sprintf("%d", n)
34 }
35 return fmt.Sprintf("%.3f%c", v, scale[i])
36}
diff --git a/src/gnunet/util/id.go b/src/gnunet/util/id.go
new file mode 100644
index 0000000..41bd30e
--- /dev/null
+++ b/src/gnunet/util/id.go
@@ -0,0 +1,10 @@
1package util
2
3var (
4 _id = 0
5)
6
7func NextID() int {
8 _id += 1
9 return _id
10}
diff --git a/src/gnunet/util/msg_queue.go b/src/gnunet/util/msg_queue.go
new file mode 100644
index 0000000..a4fb2eb
--- /dev/null
+++ b/src/gnunet/util/msg_queue.go
@@ -0,0 +1,3 @@
1package util
2
3import ()
diff --git a/src/gnunet/util/rnd.go b/src/gnunet/util/rnd.go
new file mode 100644
index 0000000..d3c8b2e
--- /dev/null
+++ b/src/gnunet/util/rnd.go
@@ -0,0 +1,46 @@
1package util
2
3import (
4 "bytes"
5 "crypto/rand"
6 "encoding/binary"
7)
8
9func RndArray(b []byte) {
10 rand.Read(b)
11}
12
13func NewRndArray(size int) []byte {
14 b := make([]byte, size)
15 rand.Read(b)
16 return b
17}
18
19func RndUInt64() uint64 {
20 b := make([]byte, 8)
21 RndArray(b)
22 var v uint64
23 c := bytes.NewBuffer(b)
24 binary.Read(c, binary.BigEndian, &v)
25 return v
26}
27
28func RndInt64() int64 {
29 return int64(RndUInt64())
30}
31
32func RndUInt32() uint32 {
33 return uint32(RndUInt64())
34}
35
36func RndInt32() int32 {
37 return int32(RndUInt64())
38}
39
40func RndUInt16() uint16 {
41 return uint16(RndUInt64())
42}
43
44func RndInt16() int16 {
45 return int16(RndUInt64())
46}
diff --git a/src/gnunet/util/time.go b/src/gnunet/util/time.go
new file mode 100644
index 0000000..89109a7
--- /dev/null
+++ b/src/gnunet/util/time.go
@@ -0,0 +1,19 @@
1package util
2
3import (
4 "time"
5)
6
7func GetAbsoluteTimeNow() uint64 {
8 return getTimestamp(time.Now())
9}
10
11func GetAbsoluteTimeOffset(t time.Duration) uint64 {
12 return getTimestamp(time.Now().Add(t))
13}
14
15func getTimestamp(t time.Time) uint64 {
16 secs := t.Unix()
17 usecs := t.Nanosecond() / 1000
18 return uint64(secs*1000000) + uint64(usecs)
19}