itMerge branch 'ed25519' - tordam - A library for peer discovery inside the Tor network Err parazyd.org 70 hgit clone https://git.parazyd.org/tordam URL:https://git.parazyd.org/tordam parazyd.org 70 1Log /git/tordam/log.gph parazyd.org 70 1Files /git/tordam/files.gph parazyd.org 70 1Refs /git/tordam/refs.gph parazyd.org 70 1README /git/tordam/file/README.md.gph parazyd.org 70 1LICENSE /git/tordam/file/LICENSE.gph parazyd.org 70 i--- Err parazyd.org 70 1commit 592f384bacf4c4d8c88f2d0be97ece8b00b5dec1 /git/tordam/commit/592f384bacf4c4d8c88f2d0be97ece8b00b5dec1.gph parazyd.org 70 1parent 8c81d3a726ed9475be1e68d20ad565c5f99eaaf9 /git/tordam/commit/8c81d3a726ed9475be1e68d20ad565c5f99eaaf9.gph parazyd.org 70 hAuthor: parazyd URL:mailto:parazyd@dyne.org parazyd.org 70 iDate: Thu, 1 Nov 2018 12:40:54 +0100 Err parazyd.org 70 i Err parazyd.org 70 iMerge branch 'ed25519' Err parazyd.org 70 i Err parazyd.org 70 iThis merge ports tor-dam to use elliptic curve cryptography instead of Err parazyd.org 70 iRSA. We keep no backwards compatibility with the state of the code Err parazyd.org 70 ibefore this branch is merged. The Tor hidden services are now switched Err parazyd.org 70 itto v3 and also use the ed25519 curve. Err parazyd.org 70 i Err parazyd.org 70 iThe merge also slightly changes the protocol, which is documented in Err parazyd.org 70 itthe protocol.md file. Err parazyd.org 70 i Err parazyd.org 70 iDiffstat: Err parazyd.org 70 i M README.md | 12 ------------ Err parazyd.org 70 i M cmd/dam-client/main.go | 308 +++++++++++++++---------------- Err parazyd.org 70 i M cmd/dam-dir/main.go | 49 ++++++++++--------------------- Err parazyd.org 70 i D cmd/dam-dir/main_test.go | 310 ------------------------------- Err parazyd.org 70 i M pkg/damlib/config.go | 14 +++++--------- Err parazyd.org 70 i D pkg/damlib/config_test.go | 31 ------------------------------- Err parazyd.org 70 i M pkg/damlib/crypto_25519.go | 89 +++++++++++++++++++++---------- Err parazyd.org 70 i D pkg/damlib/crypto_25519_test.go | 82 ------------------------------- Err parazyd.org 70 i D pkg/damlib/crypto_common.go | 46 ------------------------------- Err parazyd.org 70 i D pkg/damlib/crypto_common_test.go | 38 ------------------------------- Err parazyd.org 70 i D pkg/damlib/crypto_rsa.go | 197 ------------------------------- Err parazyd.org 70 i M pkg/damlib/helpers.go | 26 +++++++++++++++++++++++++- Err parazyd.org 70 i A pkg/damlib/helpers_test.go | 65 +++++++++++++++++++++++++++++++ Err parazyd.org 70 i D pkg/damlib/net_test.go | 51 ------------------------------- Err parazyd.org 70 i M pkg/damlib/redis.go | 27 +++++++++++++++++++++++++++ Err parazyd.org 70 i D pkg/damlib/tor.go | 49 ------------------------------- Err parazyd.org 70 i D pkg/damlib/tor_test.go | 36 ------------------------------- Err parazyd.org 70 i M pkg/damlib/validate.go | 122 ++++++++++--------------------- Err parazyd.org 70 i A pkg/damlib/validate_test.go | 165 +++++++++++++++++++++++++++++++ Err parazyd.org 70 i D pkg/damlib/zenroom.go | 54 ------------------------------- Err parazyd.org 70 i D pkg/damlib/zenroom.h | 103 ------------------------------- Err parazyd.org 70 i D pkg/damlib/zenroom_test.go | 49 ------------------------------- Err parazyd.org 70 i M protocol.md | 92 ++++++++++++++----------------- Err parazyd.org 70 i M python/Makefile | 4 +--- Err parazyd.org 70 i D python/damauth.py | 33 ------------------------------- Err parazyd.org 70 i M python/damhs.py | 5 +---- Err parazyd.org 70 i Err parazyd.org 70 i26 files changed, 597 insertions(+), 1460 deletions(-) Err parazyd.org 70 i--- Err parazyd.org 70 1diff --git a/README.md b/README.md /git/tordam/file/README.md.gph parazyd.org 70 it@@ -47,15 +47,3 @@ to create hidden services and retrieve hidden service descriptors. Err parazyd.org 70 i Redis is our storage backend where information about nodes is held. Err parazyd.org 70 i Err parazyd.org 70 i Working configurations are provided in the `contrib` directory. Err parazyd.org 70 i- Err parazyd.org 70 i- Err parazyd.org 70 i-#### Zenroom Err parazyd.org 70 i- Err parazyd.org 70 i-``` Err parazyd.org 70 i-https://github.com/decodeproject/zenroom Err parazyd.org 70 i-``` Err parazyd.org 70 i- Err parazyd.org 70 i-The shared library can be acquired by cloning the above repository and Err parazyd.org 70 i-running `make linux-go`, which will compile a `.so` located in Err parazyd.org 70 i-`build/go/libzenroomgo.so`. You will then need to install it on your Err parazyd.org 70 i-system to a place such as `/usr/lib/`. Err parazyd.org 70 1diff --git a/cmd/dam-client/main.go b/cmd/dam-client/main.go /git/tordam/file/cmd/dam-client/main.go.gph parazyd.org 70 it@@ -25,7 +25,6 @@ import ( Err parazyd.org 70 i "bytes" Err parazyd.org 70 i "compress/gzip" Err parazyd.org 70 i "crypto/rand" Err parazyd.org 70 i- "crypto/rsa" Err parazyd.org 70 i "encoding/base64" Err parazyd.org 70 i "encoding/json" Err parazyd.org 70 i "flag" Err parazyd.org 70 it@@ -39,42 +38,118 @@ import ( Err parazyd.org 70 i "time" Err parazyd.org 70 i Err parazyd.org 70 i lib "github.com/parazyd/tor-dam/pkg/damlib" Err parazyd.org 70 i+ "golang.org/x/crypto/ed25519" Err parazyd.org 70 i ) Err parazyd.org 70 i Err parazyd.org 70 i type msgStruct struct { Err parazyd.org 70 i Secret string Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i-func clientInit(gen bool) { Err parazyd.org 70 i- err := os.Chmod(lib.PrivKeyPath, 0600) Err parazyd.org 70 i- lib.CheckError(err) Err parazyd.org 70 i+func clientInit(gen bool) error { Err parazyd.org 70 i+ pub, priv, err := lib.GenEd25519() Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ return err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ if err := lib.SavePrivEd25519(lib.PrivKeyPath, priv); err != nil { Err parazyd.org 70 i+ return err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ if err := lib.SaveSeedEd25519(lib.SeedPath, priv.Seed()); err != nil { Err parazyd.org 70 i+ return err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ if err := os.Chmod(lib.PrivKeyPath, 0600); err != nil { Err parazyd.org 70 i+ return err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ if err := os.Chmod(lib.SeedPath, 0600); err != nil { Err parazyd.org 70 i+ return err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ onionaddr := lib.OnionFromPubkeyEd25519(pub) Err parazyd.org 70 i+ if err := ioutil.WriteFile("hostname", onionaddr, 0600); err != nil { Err parazyd.org 70 i+ return err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ if gen { Err parazyd.org 70 i+ log.Println("Our hostname is:", string(onionaddr)) Err parazyd.org 70 i+ os.Exit(0) Err parazyd.org 70 i+ } Err parazyd.org 70 i+ return nil Err parazyd.org 70 i+} Err parazyd.org 70 i Err parazyd.org 70 i- key, err := lib.GenRsa(lib.RsaBits) Err parazyd.org 70 i- lib.CheckError(err) Err parazyd.org 70 i+func fetchNodeList(epLists []string, noremote bool) ([]string, error) { Err parazyd.org 70 i+ var nodeslice, nodelist []string Err parazyd.org 70 i Err parazyd.org 70 i- err = lib.SavePrivRsa(lib.PrivKeyPath, key) Err parazyd.org 70 i- lib.CheckError(err) Err parazyd.org 70 i+ log.Println("Fetching a list of nodes.") Err parazyd.org 70 i Err parazyd.org 70 i- onionaddr, err := lib.OnionFromPubkeyRsa(key.PublicKey) Err parazyd.org 70 i- lib.CheckError(err) Err parazyd.org 70 i+ // Remote network entrypoints Err parazyd.org 70 i+ if !(noremote) { Err parazyd.org 70 i+ for _, i := range epLists { Err parazyd.org 70 i+ log.Println("Fetching", i) Err parazyd.org 70 i+ n, err := lib.HTTPDownload(i) Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ return nil, err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ nodeslice = lib.ParseDirs(nodeslice, n) Err parazyd.org 70 i+ } Err parazyd.org 70 i+ } Err parazyd.org 70 i Err parazyd.org 70 i- err = ioutil.WriteFile("hostname", onionaddr, 0644) Err parazyd.org 70 i- lib.CheckError(err) Err parazyd.org 70 i+ // Local ~/.dam/directories.txt Err parazyd.org 70 i+ if _, err := os.Stat("directories.txt"); err == nil { Err parazyd.org 70 i+ ln, err := ioutil.ReadFile("directories.txt") Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ return nil, err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ nodeslice = lib.ParseDirs(nodeslice, ln) Err parazyd.org 70 i+ } Err parazyd.org 70 i Err parazyd.org 70 i- log.Printf("Our hostname is: %s\n", string(onionaddr)) Err parazyd.org 70 i- if gen { Err parazyd.org 70 i- os.Exit(0) Err parazyd.org 70 i+ // Local nodes known to Redis Err parazyd.org 70 i+ nodes, _ := lib.RedisCli.Keys(".onion").Result() Err parazyd.org 70 i+ for _, i := range nodes { Err parazyd.org 70 i+ valid, err := lib.RedisCli.HGet(i, "valid").Result() Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ // Possible RedisCli bug, possible Redis bug. To be investigated. Err parazyd.org 70 i+ // Sometimes it returns err, but it's nil and does not say what's Err parazyd.org 70 i+ // happening exactly. Err parazyd.org 70 i+ continue Err parazyd.org 70 i+ } Err parazyd.org 70 i+ if valid == "1" { Err parazyd.org 70 i+ nodeslice = append(nodeslice, i) Err parazyd.org 70 i+ } Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ // Remove possible duplicates. Duplicates can cause race conditions and are Err parazyd.org 70 i+ // redundant to the entire logic. Err parazyd.org 70 i+ encounter := map[string]bool{} Err parazyd.org 70 i+ for i := range nodeslice { Err parazyd.org 70 i+ encounter[nodeslice[i]] = true Err parazyd.org 70 i+ } Err parazyd.org 70 i+ nodeslice = []string{} Err parazyd.org 70 i+ for key := range encounter { Err parazyd.org 70 i+ nodeslice = append(nodeslice, key) Err parazyd.org 70 i } Err parazyd.org 70 i+ Err parazyd.org 70 i+ if len(nodeslice) < 1 { Err parazyd.org 70 i+ log.Fatalln("Couldn't fetch any nodes to announce to. Exiting.") Err parazyd.org 70 i+ } else if len(nodeslice) <= 6 { Err parazyd.org 70 i+ log.Printf("Found only %d nodes.\n", len(nodeslice)) Err parazyd.org 70 i+ nodelist = nodeslice Err parazyd.org 70 i+ } else { Err parazyd.org 70 i+ log.Println("Found enough directories. Picking out 6 random ones.") Err parazyd.org 70 i+ for i := 0; i <= 5; i++ { Err parazyd.org 70 i+ n, _ := rand.Int(rand.Reader, big.NewInt(int64(len(nodeslice)))) Err parazyd.org 70 i+ nodelist = append(nodelist, nodeslice[n.Int64()]) Err parazyd.org 70 i+ nodeslice[n.Int64()] = nodeslice[len(nodeslice)-1] Err parazyd.org 70 i+ nodeslice = nodeslice[:len(nodeslice)-1] Err parazyd.org 70 i+ } Err parazyd.org 70 i+ } Err parazyd.org 70 i+ return nodelist, nil Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i-func announce(dir string, vals map[string]string, privkey *rsa.PrivateKey) (bool, error) { Err parazyd.org 70 i+func announce(node string, vals map[string]string, privkey ed25519.PrivateKey) (bool, error) { Err parazyd.org 70 i msg, err := json.Marshal(vals) Err parazyd.org 70 i if err != nil { Err parazyd.org 70 i return false, err Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i- log.Println("Announcing keypair to:", dir) Err parazyd.org 70 i- resp, err := lib.HTTPPost("http://"+dir+"/announce", msg) Err parazyd.org 70 i+ log.Println("Announcing keypair to:", node) Err parazyd.org 70 i+ resp, err := lib.HTTPPost("http://"+node+"/announce", msg) Err parazyd.org 70 i if err != nil { Err parazyd.org 70 i return false, err Err parazyd.org 70 i } Err parazyd.org 70 it@@ -82,59 +157,49 @@ func announce(dir string, vals map[string]string, privkey *rsa.PrivateKey) (bool Err parazyd.org 70 i // Parse server's reply Err parazyd.org 70 i var m msgStruct Err parazyd.org 70 i decoder := json.NewDecoder(resp.Body) Err parazyd.org 70 i- err = decoder.Decode(&m) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i+ if err := decoder.Decode(&m); err != nil { Err parazyd.org 70 i return false, err Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i if resp.StatusCode == 400 { Err parazyd.org 70 i- log.Printf("%s: Fail. Reply: %s\n", dir, m.Secret) Err parazyd.org 70 i+ log.Printf("%s fail. Reply: %s\n", node, m.Secret) Err parazyd.org 70 i return false, nil Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i if resp.StatusCode == 200 { Err parazyd.org 70 i- log.Printf("%s: Success. 1/2 handshake valid.\n", dir) Err parazyd.org 70 i- decodedSecret, err := base64.StdEncoding.DecodeString(m.Secret) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return false, err Err parazyd.org 70 i- } Err parazyd.org 70 i+ log.Printf("%s success. 1/2 handshake valid.", node) Err parazyd.org 70 i Err parazyd.org 70 i- decrypted, err := lib.DecryptMsgRsa(decodedSecret, privkey) Err parazyd.org 70 i+ sig, err := lib.SignMsgEd25519([]byte(m.Secret), privkey) Err parazyd.org 70 i if err != nil { Err parazyd.org 70 i return false, err Err parazyd.org 70 i } Err parazyd.org 70 i- Err parazyd.org 70 i- decryptedEncode := base64.StdEncoding.EncodeToString(decrypted) Err parazyd.org 70 i- Err parazyd.org 70 i- sig, err := lib.SignMsgRsa([]byte(decryptedEncode), privkey) Err parazyd.org 70 i- lib.CheckError(err) Err parazyd.org 70 i encodedSig := base64.StdEncoding.EncodeToString(sig) Err parazyd.org 70 i Err parazyd.org 70 i- vals["secret"] = decryptedEncode Err parazyd.org 70 i- vals["message"] = decryptedEncode Err parazyd.org 70 i+ vals["secret"] = m.Secret Err parazyd.org 70 i+ vals["message"] = m.Secret Err parazyd.org 70 i vals["signature"] = encodedSig Err parazyd.org 70 i+ Err parazyd.org 70 i msg, err := json.Marshal(vals) Err parazyd.org 70 i if err != nil { Err parazyd.org 70 i return false, err Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i- log.Printf("%s: Success. Sending back decrypted secret\n", dir) Err parazyd.org 70 i- resp, err := lib.HTTPPost("http://"+dir+"/announce", msg) Err parazyd.org 70 i+ log.Printf("%s: success. Sending back signed secret.\n", node) Err parazyd.org 70 i+ resp, err := lib.HTTPPost("http://"+node+"/announce", msg) Err parazyd.org 70 i if err != nil { Err parazyd.org 70 i return false, err Err parazyd.org 70 i } Err parazyd.org 70 i decoder = json.NewDecoder(resp.Body) Err parazyd.org 70 i- if err = decoder.Decode(&m); err != nil { Err parazyd.org 70 i+ if err := decoder.Decode(&m); err != nil { Err parazyd.org 70 i return false, err Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i if resp.StatusCode == 200 { Err parazyd.org 70 i- log.Printf("%s: Success. 2/2 handshake valid.\n", dir) Err parazyd.org 70 i- // TODO: To TOFU or not to TOFU? Err parazyd.org 70 i+ log.Printf("%s success. 2/2 handshake valid.\n", node) Err parazyd.org 70 i data, err := base64.StdEncoding.DecodeString(m.Secret) Err parazyd.org 70 i if err != nil { Err parazyd.org 70 i // Not a list of nodes. Err parazyd.org 70 i- log.Printf("%s: Reply: %s\n", dir, m.Secret) Err parazyd.org 70 i+ log.Printf("%s replied: %s\n", node, m.Secret) Err parazyd.org 70 i return true, nil Err parazyd.org 70 i } Err parazyd.org 70 i log.Println("Got node data. Processing...") Err parazyd.org 70 it@@ -146,7 +211,7 @@ func announce(dir string, vals map[string]string, privkey *rsa.PrivateKey) (bool Err parazyd.org 70 i return false, err Err parazyd.org 70 i } Err parazyd.org 70 i for k, v := range nodes { Err parazyd.org 70 i- log.Printf("Adding %s to redis\n", k) Err parazyd.org 70 i+ log.Printf("Adding %s to Redis.\n", k) Err parazyd.org 70 i redRet, err := lib.RedisCli.HMSet(k, v).Result() Err parazyd.org 70 i lib.CheckError(err) Err parazyd.org 70 i if redRet != "OK" { Err parazyd.org 70 it@@ -155,115 +220,43 @@ func announce(dir string, vals map[string]string, privkey *rsa.PrivateKey) (bool Err parazyd.org 70 i } Err parazyd.org 70 i return true, nil Err parazyd.org 70 i } Err parazyd.org 70 i- log.Printf("%s: Fail. Reply: %s\n", dir, m.Secret) Err parazyd.org 70 i+ log.Printf("%s fail. Reply: %s\n", node, m.Secret) Err parazyd.org 70 i return false, nil Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i return false, nil Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i-func fetchDirlist(locations []string) ([]string, error) { Err parazyd.org 70 i- var dirSlice, dirlist []string Err parazyd.org 70 i- log.Println("Grabbing a list of directories.") Err parazyd.org 70 i- Err parazyd.org 70 i- // Remote network entry points Err parazyd.org 70 i- if !(lib.Noremote) { Err parazyd.org 70 i- for _, i := range locations { Err parazyd.org 70 i- log.Println("Fetching", i) Err parazyd.org 70 i- dirs, err := lib.HTTPDownload(i) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- dirSlice = lib.ParseDirs(dirSlice, dirs) Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // Local ~/.dam/directories.txt Err parazyd.org 70 i- if _, err := os.Stat("directories.txt"); err == nil { Err parazyd.org 70 i- dirs, err := ioutil.ReadFile("directories.txt") Err parazyd.org 70 i- lib.CheckError(err) Err parazyd.org 70 i- dirSlice = lib.ParseDirs(dirSlice, dirs) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // Local nodes known to redis Err parazyd.org 70 i- nodes, err := lib.RedisCli.Keys("*.onion").Result() Err parazyd.org 70 i- lib.CheckError(err) Err parazyd.org 70 i- for _, i := range nodes { Err parazyd.org 70 i- valid, err := lib.RedisCli.HGet(i, "valid").Result() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- // Possible RedisCli bug, possible Redis bug. To be investigated. Err parazyd.org 70 i- // Sometimes it returns err, but it's nil and does not say what's Err parazyd.org 70 i- // happening exactly. Err parazyd.org 70 i- continue Err parazyd.org 70 i- } Err parazyd.org 70 i- if valid == "1" { Err parazyd.org 70 i- dirSlice = append(dirSlice, i) Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // Remove possible duplicats. Dupes can cause race conditions and are Err parazyd.org 70 i- // redundant to the whole logic. Err parazyd.org 70 i- encounter := map[string]bool{} Err parazyd.org 70 i- for j := range dirSlice { Err parazyd.org 70 i- encounter[dirSlice[j]] = true Err parazyd.org 70 i- } Err parazyd.org 70 i- dirSlice = []string{} Err parazyd.org 70 i- for key := range encounter { Err parazyd.org 70 i- dirSlice = append(dirSlice, key) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- if len(dirSlice) < 1 { Err parazyd.org 70 i- log.Fatalln("Couldn't get any directories. Exiting.") Err parazyd.org 70 i- } else if len(dirSlice) <= 6 { Err parazyd.org 70 i- log.Printf("Found only %d directories.\n", len(dirSlice)) Err parazyd.org 70 i- dirlist = dirSlice Err parazyd.org 70 i- } else { Err parazyd.org 70 i- log.Println("Found enough directories. Picking out 6 random ones.") Err parazyd.org 70 i- // Pick out 6 random directories from the retrieved list. Err parazyd.org 70 i- for k := 0; k <= 5; k++ { Err parazyd.org 70 i- n, _ := rand.Int(rand.Reader, big.NewInt(int64(len(dirSlice)))) Err parazyd.org 70 i- dirlist = append(dirlist, dirSlice[n.Int64()]) Err parazyd.org 70 i- dirSlice[n.Int64()] = dirSlice[len(dirSlice)-1] Err parazyd.org 70 i- dirSlice = dirSlice[:len(dirSlice)-1] Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- return dirlist, nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i func main() { Err parazyd.org 70 i- var d, gen bool Err parazyd.org 70 i+ var noremote, gen bool Err parazyd.org 70 i var ai int Err parazyd.org 70 i var dh string Err parazyd.org 70 i- var dirHosts []string Err parazyd.org 70 i Err parazyd.org 70 i- flag.BoolVar(&d, "d", false, "Don't fetch remote entry points.") Err parazyd.org 70 i+ flag.BoolVar(&noremote, "d", false, "Don't fetch remote entrypoints.") Err parazyd.org 70 i flag.BoolVar(&gen, "gen", false, "Only (re)generate keypairs and exit cleanly.") Err parazyd.org 70 i flag.IntVar(&ai, "ai", 5, "Announce interval in minutes.") Err parazyd.org 70 i flag.StringVar(&dh, "dh", "https://dam.decodeproject.eu/dirs.txt", Err parazyd.org 70 i- "A remote list of entry points/directories. (comma-separated)") Err parazyd.org 70 i+ "Remote lists of entrypoints. (comma-separated)") Err parazyd.org 70 i flag.Parse() Err parazyd.org 70 i Err parazyd.org 70 i- if d { Err parazyd.org 70 i- lib.Noremote = true Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // Network entry points. These files hold the lists of directories we can Err parazyd.org 70 i- // announce to. Format is "DIR:22mobp7vrb7a4gt2.onion", other lines are ignored. Err parazyd.org 70 i- dirHosts = strings.Split(dh, ",") Err parazyd.org 70 i+ // Network entrypoints. These files hold the lists of nodes we can announce Err parazyd.org 70 i+ // to initially. Format is "DIR:unlikelynamefora.onion", other lines are Err parazyd.org 70 i+ // ignored and can be used as comments or similar. Err parazyd.org 70 i+ epLists := strings.Split(dh, ",") Err parazyd.org 70 i Err parazyd.org 70 i- if _, err := os.Stat(lib.Cwd); os.IsNotExist(err) { Err parazyd.org 70 i- err := os.Mkdir(lib.Cwd, 0700) Err parazyd.org 70 i+ if _, err := os.Stat(lib.Workdir); os.IsNotExist(err) { Err parazyd.org 70 i+ err := os.Mkdir(lib.Workdir, 0700) Err parazyd.org 70 i lib.CheckError(err) Err parazyd.org 70 i } Err parazyd.org 70 i- err := os.Chdir(lib.Cwd) Err parazyd.org 70 i+ err := os.Chdir(lib.Workdir) Err parazyd.org 70 i lib.CheckError(err) Err parazyd.org 70 i Err parazyd.org 70 i if _, err = os.Stat(lib.PrivKeyPath); os.IsNotExist(err) || gen { Err parazyd.org 70 i- clientInit(gen) Err parazyd.org 70 i+ err = clientInit(gen) Err parazyd.org 70 i+ lib.CheckError(err) Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i- // Start up the hidden service Err parazyd.org 70 i- log.Println("Starting up the hidden service...") Err parazyd.org 70 i+ log.Println("Starting up the hidden service.") Err parazyd.org 70 i cmd := exec.Command("damhs.py", lib.PrivKeyPath, lib.TorPortMap) Err parazyd.org 70 i stdout, err := cmd.StdoutPipe() Err parazyd.org 70 i lib.CheckError(err) Err parazyd.org 70 it@@ -274,14 +267,14 @@ func main() { Err parazyd.org 70 i scanner := bufio.NewScanner(stdout) Err parazyd.org 70 i ok := false Err parazyd.org 70 i go func() { Err parazyd.org 70 i- // If we do not manage to publish our descriptor, we will exit. Err parazyd.org 70 i+ // If we do not manage to publish our descriptor, we shall exit. Err parazyd.org 70 i t1 := time.Now().Unix() Err parazyd.org 70 i for !(ok) { Err parazyd.org 70 i t2 := time.Now().Unix() Err parazyd.org 70 i if t2-t1 > 90 { Err parazyd.org 70 i err := cmd.Process.Kill() Err parazyd.org 70 i lib.CheckError(err) Err parazyd.org 70 i- log.Fatalln("Too much time passed. Exiting.") Err parazyd.org 70 i+ log.Fatalln("Too much time has passed for publishing descriptor.") Err parazyd.org 70 i } Err parazyd.org 70 i time.Sleep(1000 * time.Millisecond) Err parazyd.org 70 i } Err parazyd.org 70 it@@ -290,44 +283,50 @@ func main() { Err parazyd.org 70 i scanner.Scan() Err parazyd.org 70 i status := scanner.Text() Err parazyd.org 70 i if status == "OK" { Err parazyd.org 70 i- log.Println("Hidden service is now running") Err parazyd.org 70 i+ log.Println("Hidden service is now running.") Err parazyd.org 70 i ok = true Err parazyd.org 70 i } Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i+ onionaddr, err := ioutil.ReadFile("hostname") Err parazyd.org 70 i+ lib.CheckError(err) Err parazyd.org 70 i+ log.Println("Our hostname is:", string(onionaddr)) Err parazyd.org 70 i+ Err parazyd.org 70 i for { Err parazyd.org 70 i- key, err := lib.LoadRsaKeyFromFile(lib.PrivKeyPath) Err parazyd.org 70 i- lib.CheckError(err) Err parazyd.org 70 i+ log.Println("Announcing to nodes...") Err parazyd.org 70 i+ var ann = 0 // Track of successful authentications. Err parazyd.org 70 i+ var wg sync.WaitGroup Err parazyd.org 70 i+ nodes, err := fetchNodeList(epLists, noremote) Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ // No route to host, or failed download. Try later. Err parazyd.org 70 i+ log.Println("Failed to fetch any nodes. Retrying in a minute.") Err parazyd.org 70 i+ time.Sleep(60 * time.Second) Err parazyd.org 70 i+ continue Err parazyd.org 70 i+ } Err parazyd.org 70 i Err parazyd.org 70 i- sig, err := lib.SignMsgRsa([]byte(lib.PostMsg), key) Err parazyd.org 70 i+ privkey, err := lib.LoadEd25519KeyFromSeed(lib.SeedPath) Err parazyd.org 70 i lib.CheckError(err) Err parazyd.org 70 i- encodedSig := base64.StdEncoding.EncodeToString(sig) Err parazyd.org 70 i Err parazyd.org 70 i- onionAddr, err := lib.OnionFromPubkeyRsa(key.PublicKey) Err parazyd.org 70 i+ pubkey := privkey.Public().(ed25519.PublicKey) Err parazyd.org 70 i+ onionaddr := lib.OnionFromPubkeyEd25519(pubkey) Err parazyd.org 70 i+ encodedPub := base64.StdEncoding.EncodeToString([]byte(pubkey)) Err parazyd.org 70 i+ Err parazyd.org 70 i+ sig, err := lib.SignMsgEd25519([]byte(lib.PostMsg), privkey) Err parazyd.org 70 i lib.CheckError(err) Err parazyd.org 70 i+ encodedSig := base64.StdEncoding.EncodeToString(sig) Err parazyd.org 70 i Err parazyd.org 70 i nodevals := map[string]string{ Err parazyd.org 70 i- "nodetype": "node", Err parazyd.org 70 i- "address": string(onionAddr), Err parazyd.org 70 i+ "address": string(onionaddr), Err parazyd.org 70 i+ "pubkey": encodedPub, Err parazyd.org 70 i "message": lib.PostMsg, Err parazyd.org 70 i "signature": encodedSig, Err parazyd.org 70 i "secret": "", Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i- log.Println("Announcing to directories...") Err parazyd.org 70 i- var ann = 0 // Track of how many successful authentications Err parazyd.org 70 i- var wg sync.WaitGroup Err parazyd.org 70 i- dirlist, err := fetchDirlist(dirHosts) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- // No route to host, or failed dl. Try later. Err parazyd.org 70 i- log.Println("Failed to fetch directory list. Retrying in a minute.") Err parazyd.org 70 i- time.Sleep(60 * time.Second) Err parazyd.org 70 i- continue Err parazyd.org 70 i- } Err parazyd.org 70 i- for _, i := range dirlist { Err parazyd.org 70 i+ for _, i := range nodes { Err parazyd.org 70 i wg.Add(1) Err parazyd.org 70 i go func(x string) { Err parazyd.org 70 i- valid, err := announce(x, nodevals, key) Err parazyd.org 70 i+ valid, err := announce(x, nodevals, privkey) Err parazyd.org 70 i if err != nil { Err parazyd.org 70 i log.Printf("%s: %s\n", x, err.Error()) Err parazyd.org 70 i } Err parazyd.org 70 it@@ -339,15 +338,8 @@ func main() { Err parazyd.org 70 i } Err parazyd.org 70 i wg.Wait() Err parazyd.org 70 i Err parazyd.org 70 i- if ann < 1 { Err parazyd.org 70 i- log.Println("No successful authentications.") Err parazyd.org 70 i- } else { Err parazyd.org 70 i- log.Printf("Successfully authenticated with %d nodes.\n", ann) Err parazyd.org 70 i- } Err parazyd.org 70 i- log.Printf("Waiting %d min. before next announce.\n", ai) Err parazyd.org 70 i+ log.Printf("%d successful authentications.\n", ann) Err parazyd.org 70 i+ log.Printf("Waiting %d min before next announce.\n", ai) Err parazyd.org 70 i time.Sleep(time.Duration(ai) * time.Minute) Err parazyd.org 70 i } Err parazyd.org 70 i- Err parazyd.org 70 i- //err = cmd.Wait() // Hidden service Python daemon Err parazyd.org 70 i- //lib.CheckError(err) Err parazyd.org 70 i } Err parazyd.org 70 1diff --git a/cmd/dam-dir/main.go b/cmd/dam-dir/main.go /git/tordam/file/cmd/dam-dir/main.go.gph parazyd.org 70 it@@ -26,7 +26,6 @@ import ( Err parazyd.org 70 i "log" Err parazyd.org 70 i "net/http" Err parazyd.org 70 i "os" Err parazyd.org 70 i- "os/exec" Err parazyd.org 70 i "strconv" Err parazyd.org 70 i "sync" Err parazyd.org 70 i "time" Err parazyd.org 70 it@@ -38,7 +37,6 @@ import ( Err parazyd.org 70 i const ListenAddress = "127.0.0.1:49371" Err parazyd.org 70 i Err parazyd.org 70 i type nodeStruct struct { Err parazyd.org 70 i- Nodetype string Err parazyd.org 70 i Address string Err parazyd.org 70 i Message string Err parazyd.org 70 i Signature string Err parazyd.org 70 it@@ -49,23 +47,6 @@ type nodeStruct struct { Err parazyd.org 70 i Valid int64 Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i-func startRedis() { Err parazyd.org 70 i- log.Println("Starting up redis-server...") Err parazyd.org 70 i- cmd := exec.Command("redis-server", "/usr/local/share/tor-dam/redis.conf") Err parazyd.org 70 i- err := cmd.Start() Err parazyd.org 70 i- lib.CheckError(err) Err parazyd.org 70 i- Err parazyd.org 70 i- time.Sleep(500 * time.Millisecond) Err parazyd.org 70 i- Err parazyd.org 70 i- _, err = lib.RedisCli.Ping().Result() Err parazyd.org 70 i- lib.CheckError(err) Err parazyd.org 70 i- Err parazyd.org 70 i- PubSub := lib.RedisCli.Subscribe(lib.PubSubChan) Err parazyd.org 70 i- _, err = PubSub.Receive() Err parazyd.org 70 i- lib.CheckError(err) Err parazyd.org 70 i- log.Printf("Created \"%s\" channel in redis\n", lib.PubSubChan) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i func postback(rw http.ResponseWriter, data map[string]string, retCode int) error { Err parazyd.org 70 i jsonVal, err := json.Marshal(data) Err parazyd.org 70 i if err != nil { Err parazyd.org 70 it@@ -96,8 +77,7 @@ func handlePost(rw http.ResponseWriter, request *http.Request) { Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i // Bail out as soon as possible. Err parazyd.org 70 i- if len(n.Nodetype) == 0 || len(n.Address) == 0 || Err parazyd.org 70 i- len(n.Message) == 0 || len(n.Signature) == 0 { Err parazyd.org 70 i+ if len(n.Address) == 0 || len(n.Message) == 0 || len(n.Signature) == 0 { Err parazyd.org 70 i ret = map[string]string{"secret": "Invalid request format."} Err parazyd.org 70 i if err := postback(rw, ret, 400); err != nil { Err parazyd.org 70 i lib.CheckError(err) Err parazyd.org 70 it@@ -114,9 +94,9 @@ func handlePost(rw http.ResponseWriter, request *http.Request) { Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i req := map[string]string{ Err parazyd.org 70 i- "nodetype": n.Nodetype, Err parazyd.org 70 i "address": n.Address, Err parazyd.org 70 i "message": n.Message, Err parazyd.org 70 i+ "pubkey": n.Pubkey, Err parazyd.org 70 i "signature": n.Signature, Err parazyd.org 70 i "secret": n.Secret, Err parazyd.org 70 i } Err parazyd.org 70 it@@ -127,7 +107,7 @@ func handlePost(rw http.ResponseWriter, request *http.Request) { Err parazyd.org 70 i ret = map[string]string{"secret": msg} Err parazyd.org 70 i if valid { Err parazyd.org 70 i log.Printf("%s: 1/2 handshake valid.\n", n.Address) Err parazyd.org 70 i- log.Println("Sending back encrypted secret.") Err parazyd.org 70 i+ log.Println("Sending nonce.") Err parazyd.org 70 i if err := postback(rw, ret, 200); err != nil { Err parazyd.org 70 i lib.CheckError(err) Err parazyd.org 70 i } Err parazyd.org 70 it@@ -240,28 +220,31 @@ func handleElse(rw http.ResponseWriter, request *http.Request) {} Err parazyd.org 70 i Err parazyd.org 70 i func main() { Err parazyd.org 70 i var wg sync.WaitGroup Err parazyd.org 70 i- var t bool Err parazyd.org 70 i var ttl int64 Err parazyd.org 70 i+ var redconf string Err parazyd.org 70 i Err parazyd.org 70 i- flag.BoolVar(&t, "t", false, "Mark all new nodes valid initially") Err parazyd.org 70 i+ flag.BoolVar(&lib.Testnet, "t", false, "Mark all new nodes valid initially") Err parazyd.org 70 i flag.Int64Var(&ttl, "ttl", 0, "Set expiry time in minutes (TTL) for nodes") Err parazyd.org 70 i+ flag.StringVar(&redconf, "redconf", "/usr/local/share/tor-dam/redis.conf", Err parazyd.org 70 i+ "Path to redis' redis.conf.") Err parazyd.org 70 i flag.Parse() Err parazyd.org 70 i Err parazyd.org 70 i- if t { Err parazyd.org 70 i- lib.Testnet = true Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i // Chdir to our working directory. Err parazyd.org 70 i- if _, err := os.Stat(lib.Cwd); os.IsNotExist(err) { Err parazyd.org 70 i- err := os.Mkdir(lib.Cwd, 0700) Err parazyd.org 70 i+ if _, err := os.Stat(lib.Workdir); os.IsNotExist(err) { Err parazyd.org 70 i+ err := os.Mkdir(lib.Workdir, 0700) Err parazyd.org 70 i lib.CheckError(err) Err parazyd.org 70 i } Err parazyd.org 70 i- err := os.Chdir(lib.Cwd) Err parazyd.org 70 i+ err := os.Chdir(lib.Workdir) Err parazyd.org 70 i lib.CheckError(err) Err parazyd.org 70 i Err parazyd.org 70 i if _, err := lib.RedisCli.Ping().Result(); err != nil { Err parazyd.org 70 i // We assume redis is not running. Start it up. Err parazyd.org 70 i- startRedis() Err parazyd.org 70 i+ _, err := lib.StartRedis(redconf) Err parazyd.org 70 i+ lib.CheckError(err) Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ if lib.Testnet { Err parazyd.org 70 i+ log.Println("Will mark all nodes valid by default.") Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i mux := http.NewServeMux() Err parazyd.org 70 1diff --git a/cmd/dam-dir/main_test.go b/cmd/dam-dir/main_test.go /git/tordam/file/cmd/dam-dir/main_test.go.gph parazyd.org 70 it@@ -1,310 +0,0 @@ Err parazyd.org 70 i-package main Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2018 Dyne.org Foundation Err parazyd.org 70 i- * tor-dam is written and maintained by Ivan J. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This source code is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This software is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU General Public License Err parazyd.org 70 i- * along with this source code. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "encoding/base64" Err parazyd.org 70 i- "encoding/json" Err parazyd.org 70 i- "net/http" Err parazyd.org 70 i- "os" Err parazyd.org 70 i- //"os/exec" Err parazyd.org 70 i- "strings" Err parazyd.org 70 i- //"syscall" Err parazyd.org 70 i- "testing" Err parazyd.org 70 i- //"time" Err parazyd.org 70 i- Err parazyd.org 70 i- lib "github.com/parazyd/tor-dam/pkg/damlib" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-type msgStruct struct { Err parazyd.org 70 i- Secret string Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-var ValidFirst = map[string]string{ Err parazyd.org 70 i- "nodetype": "node", Err parazyd.org 70 i- "address": "22mobp7vrb7a4gt2.onion", Err parazyd.org 70 i- "message": "I am a DAM node!", Err parazyd.org 70 i- "signature": "BuB/Dv8E44CLzUX88K2Ab0lUNS9A0GSkHPtrFNNWZMihPMWN0ORhwMZBRnMJ8woPO3wSONBvEvaCXA2hvsVrUJTa+hnevQNyQXCRhdTVVuVXEpjyFzkMamxb6InrGqbsGGkEUqGMSr9aaQ85N02MMrM6T6JuyqSSssFg2xuO+P4=", Err parazyd.org 70 i- "secret": "", Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func postReq(data map[string]string) (*http.Response, error) { Err parazyd.org 70 i- msg, err := json.Marshal(data) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- resp, err := lib.HTTPPost("http://localhost:49371/announce", msg) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- return resp, nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func getRespText(resp *http.Response) (msgStruct, error) { Err parazyd.org 70 i- var m msgStruct Err parazyd.org 70 i- Err parazyd.org 70 i- decoder := json.NewDecoder(resp.Body) Err parazyd.org 70 i- err := decoder.Decode(&m) Err parazyd.org 70 i- return m, err Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func firstAnnValid() (*http.Response, error) { Err parazyd.org 70 i- resp, err := postReq(ValidFirst) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- return resp, nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func TestValidFirstHandshake(t *testing.T) { Err parazyd.org 70 i- //t.SkipNow() Err parazyd.org 70 i- resp, err := firstAnnValid() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- m, err := getRespText(resp) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if m.Secret == "Could not get a descriptor. Try later." { Err parazyd.org 70 i- t.Skipf("Server replied: %s\n", m.Secret) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- decodedSecret, err := base64.StdEncoding.DecodeString(m.Secret) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if len(decodedSecret) != 128 { Err parazyd.org 70 i- t.Fatal("decodedSecret is not of correct length.") Err parazyd.org 70 i- } Err parazyd.org 70 i- if resp.StatusCode != 200 { Err parazyd.org 70 i- t.Log(resp.StatusCode) Err parazyd.org 70 i- t.Fatal("Server did not respond with HTTP 200") Err parazyd.org 70 i- } Err parazyd.org 70 i- t.Log("Server replied:", m.Secret) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func TestValidSecondHandshake(t *testing.T) { Err parazyd.org 70 i- //t.SkipNow() Err parazyd.org 70 i- resp, err := firstAnnValid() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- m, err := getRespText(resp) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if m.Secret == "Could not get a descriptor. Try later." { Err parazyd.org 70 i- t.Skipf("Server replied: %s\n", m.Secret) Err parazyd.org 70 i- } Err parazyd.org 70 i- if resp.StatusCode != 200 { Err parazyd.org 70 i- t.Log(resp.StatusCode) Err parazyd.org 70 i- t.Fatal("Server did not respond with HTTP 200") Err parazyd.org 70 i- } Err parazyd.org 70 i- decodedSecret, err := base64.StdEncoding.DecodeString(m.Secret) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if len(decodedSecret) != 128 { Err parazyd.org 70 i- t.Fatal("decodedSecret is not of correct length.") Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // Second handshake starts here. Err parazyd.org 70 i- privkey, err := lib.LoadRsaKeyFromFile("./dam-private.key") Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- decrypted, err := lib.DecryptMsgRsa([]byte(decodedSecret), privkey) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- decryptedEncode := base64.StdEncoding.EncodeToString(decrypted) Err parazyd.org 70 i- sig, _ := lib.SignMsgRsa([]byte(decryptedEncode), privkey) Err parazyd.org 70 i- encodedSig := base64.StdEncoding.EncodeToString(sig) Err parazyd.org 70 i- Err parazyd.org 70 i- vals := ValidFirst Err parazyd.org 70 i- vals["secret"] = decryptedEncode Err parazyd.org 70 i- vals["message"] = decryptedEncode Err parazyd.org 70 i- vals["signature"] = encodedSig Err parazyd.org 70 i- Err parazyd.org 70 i- resp, err = postReq(vals) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- m, err = getRespText(resp) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if m.Secret != lib.WelcomeMsg { Err parazyd.org 70 i- t.Fatal(m.Secret) Err parazyd.org 70 i- } Err parazyd.org 70 i- t.Log("Server replied:", m.Secret) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func TestInvalidNodetypeFirst(t *testing.T) { Err parazyd.org 70 i- //t.SkipNow() Err parazyd.org 70 i- var vals = map[string]string{ Err parazyd.org 70 i- "nodetype": "foobar", // Invalid. Err parazyd.org 70 i- "address": "22mobp7vrb7a4gt2.onion", Err parazyd.org 70 i- "message": "I am a DAM node!", Err parazyd.org 70 i- "signature": "BuB/Dv8E44CLzUX88K2Ab0lUNS9A0GSkHPtrFNNWZMihPMWN0ORhwMZBRnMJ8woPO3wSONBvEvaCXA2hvsVrUJTa+hnevQNyQXCRhdTVVuVXEpjyFzkMamxb6InrGqbsGGkEUqGMSr9aaQ85N02MMrM6T6JuyqSSssFg2xuO+P4=", Err parazyd.org 70 i- "secret": "", Err parazyd.org 70 i- } Err parazyd.org 70 i- resp, err := postReq(vals) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- m, err := getRespText(resp) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if m.Secret != "Invalid nodetype." { Err parazyd.org 70 i- t.Fatal("Server replied:", m.Secret) Err parazyd.org 70 i- } Err parazyd.org 70 i- if resp.StatusCode != 400 { Err parazyd.org 70 i- t.Fatal("Server did not respond with HTTP 400") Err parazyd.org 70 i- } Err parazyd.org 70 i- t.Log("Server replied:", m.Secret) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func TestInvalidAddressFirst(t *testing.T) { Err parazyd.org 70 i- //t.SkipNow() Err parazyd.org 70 i- var vals = map[string]string{ Err parazyd.org 70 i- "nodetype": "node", Err parazyd.org 70 i- "address": "foobar.onion", // Invalid. Err parazyd.org 70 i- "message": "I am a DAM node!", Err parazyd.org 70 i- "signature": "BuB/Dv8E44CLzUX88K2Ab0lUNS9A0GSkHPtrFNNWZMihPMWN0ORhwMZBRnMJ8woPO3wSONBvEvaCXA2hvsVrUJTa+hnevQNyQXCRhdTVVuVXEpjyFzkMamxb6InrGqbsGGkEUqGMSr9aaQ85N02MMrM6T6JuyqSSssFg2xuO+P4=", Err parazyd.org 70 i- "secret": "", Err parazyd.org 70 i- } Err parazyd.org 70 i- resp, err := postReq(vals) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- m, err := getRespText(resp) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if m.Secret != "Invalid onion address." { Err parazyd.org 70 i- t.Fatal("Server replied:", m.Secret) Err parazyd.org 70 i- } Err parazyd.org 70 i- if resp.StatusCode != 400 { Err parazyd.org 70 i- t.Fatal("Server did not respond with HTTP 400") Err parazyd.org 70 i- } Err parazyd.org 70 i- t.Log("Server replied:", m.Secret) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func TestInvalidMessageFirst(t *testing.T) { Err parazyd.org 70 i- //t.SkipNow() Err parazyd.org 70 i- // Valid message and signature, but the signature did not sign this message. Err parazyd.org 70 i- var vals = map[string]string{ Err parazyd.org 70 i- "nodetype": "node", Err parazyd.org 70 i- "address": "22mobp7vrb7a4gt2.onion", Err parazyd.org 70 i- "message": "I am a MAD node!", // Not matching the below signature. Err parazyd.org 70 i- "signature": "BuB/Dv8E44CLzUX88K2Ab0lUNS9A0GSkHPtrFNNWZMihPMWN0ORhwMZBRnMJ8woPO3wSONBvEvaCXA2hvsVrUJTa+hnevQNyQXCRhdTVVuVXEpjyFzkMamxb6InrGqbsGGkEUqGMSr9aaQ85N02MMrM6T6JuyqSSssFg2xuO+P4=", Err parazyd.org 70 i- "secret": "", Err parazyd.org 70 i- } Err parazyd.org 70 i- resp, err := postReq(vals) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- m, err := getRespText(resp) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if m.Secret == "Could not get a descriptor. Try later." { Err parazyd.org 70 i- t.Skipf("Server replied: %s\n", m.Secret) Err parazyd.org 70 i- } Err parazyd.org 70 i- if m.Secret != "Signature verification failure." { Err parazyd.org 70 i- t.Fatal("Server replied:", m.Secret) Err parazyd.org 70 i- } Err parazyd.org 70 i- if resp.StatusCode != 400 { Err parazyd.org 70 i- t.Fatal("Server did not respond with HTTP 400") Err parazyd.org 70 i- } Err parazyd.org 70 i- t.Log("Server replied:", m.Secret) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func TestInvalidSignatureFirst(t *testing.T) { Err parazyd.org 70 i- //t.SkipNow() Err parazyd.org 70 i- // Invalid signature format. Err parazyd.org 70 i- var vals = map[string]string{ Err parazyd.org 70 i- "nodetype": "node", Err parazyd.org 70 i- "address": "22mobp7vrb7a4gt2.onion", Err parazyd.org 70 i- "message": "I am a DAM node!", Err parazyd.org 70 i- "signature": "ThisIsnotbasE64==", // Invalid. Err parazyd.org 70 i- "secret": "", Err parazyd.org 70 i- } Err parazyd.org 70 i- resp, err := postReq(vals) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- m, err := getRespText(resp) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if !(strings.HasPrefix(m.Secret, "illegal base64 data at input byte ")) { Err parazyd.org 70 i- t.Fatal("Server replied:", m.Secret) Err parazyd.org 70 i- } Err parazyd.org 70 i- if resp.StatusCode != 400 { Err parazyd.org 70 i- t.Fatal("Server did not respond with HTTP 400") Err parazyd.org 70 i- } Err parazyd.org 70 i- t.Log("Server replied:", m.Secret) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func TestInvalidSecond(t *testing.T) { Err parazyd.org 70 i- //t.SkipNow() Err parazyd.org 70 i- // Try to jump in the second handshake without doing the first. Err parazyd.org 70 i- // The values below are a valid second handshake, but here we test it Err parazyd.org 70 i- // without doing the first one.. Err parazyd.org 70 i- var vals = map[string]string{ Err parazyd.org 70 i- "nodetype": "node", Err parazyd.org 70 i- "address": "22mobp7vrb7a4gt2.onion", Err parazyd.org 70 i- "message": "ZShhYHYsRGNLOTZ6YUwwP3ZXPnxhQiR9UFVWfmk5TG56TEtLb04vMms+OTIrLlQ7aS4rflR3V041RG5Je0tnYw==", Err parazyd.org 70 i- "signature": "L1N+VEi3T3aZaYksAy1+0UMoYn7B3Gapfk0dJzOUxUtUYVhj84TgfYeDnADNYrt5UK9hN/lCTIhsM6zPO7mSjQI43l3dKvMIikqQDwNey/XaokyPI4/oKrMoGQnu8E8UmHmI1pFvwdO5EQQaKbi90qWNj93KB/NlTwqD9Ir4blY=", Err parazyd.org 70 i- "secret": "ZShhYHYsRGNLOTZ6YUwwP3ZXPnxhQiR9UFVWfmk5TG56TEtLb04vMms+OTIrLlQ7aS4rflR3V041RG5Je0tnYw==", Err parazyd.org 70 i- } Err parazyd.org 70 i- resp, err := postReq(vals) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- m, err := getRespText(resp) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if m.Secret != "We have not seen you before. Please authenticate properly." { Err parazyd.org 70 i- t.Fatal("Server replied:", m.Secret) Err parazyd.org 70 i- } Err parazyd.org 70 i- if resp.StatusCode != 400 { Err parazyd.org 70 i- t.Fatal("Server did not respond with HTTP 400") Err parazyd.org 70 i- } Err parazyd.org 70 i- t.Log("Server replied:", m.Secret) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func TestMain(m *testing.M) { Err parazyd.org 70 i- //cmd := exec.Command("./dam-dir") Err parazyd.org 70 i- //cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} Err parazyd.org 70 i- //cmd.Start() Err parazyd.org 70 i- //time.Sleep(1000 * time.Millisecond) Err parazyd.org 70 i- Err parazyd.org 70 i- ex := m.Run() Err parazyd.org 70 i- //syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) Err parazyd.org 70 i- os.Exit(ex) Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/pkg/damlib/config.go b/pkg/damlib/config.go /git/tordam/file/pkg/damlib/config.go.gph parazyd.org 70 it@@ -22,15 +22,15 @@ package damlib Err parazyd.org 70 i Err parazyd.org 70 i import "os" Err parazyd.org 70 i Err parazyd.org 70 i-// Cwd holds the path to the directory where we will Chdir on startup. Err parazyd.org 70 i-var Cwd = os.Getenv("HOME") + "/.dam" Err parazyd.org 70 i- Err parazyd.org 70 i-// RsaBits holds the size of our RSA private key. Tor standard is 1024. Err parazyd.org 70 i-const RsaBits = 1024 Err parazyd.org 70 i+// Workdir holds the path to the directory where we will Chdir on startup. Err parazyd.org 70 i+var Workdir = os.Getenv("HOME") + "/.dam" Err parazyd.org 70 i Err parazyd.org 70 i // PrivKeyPath holds the name of where our private key is. Err parazyd.org 70 i const PrivKeyPath = "dam-private.key" Err parazyd.org 70 i Err parazyd.org 70 i+// SeedPath holds the name of where our private key seed is. Err parazyd.org 70 i+const SeedPath = "dam-private.seed" Err parazyd.org 70 i+ Err parazyd.org 70 i // PubSubChan is the name of the pub/sub channel we're publishing to in Redis. Err parazyd.org 70 i const PubSubChan = "tordam" Err parazyd.org 70 i Err parazyd.org 70 it@@ -53,7 +53,3 @@ const DirPort = 49371 Err parazyd.org 70 i // Testnet is flipped with a flag in dam-dir and represents if all new Err parazyd.org 70 i // nodes are initially marked valid or not. Err parazyd.org 70 i var Testnet = false Err parazyd.org 70 i- Err parazyd.org 70 i-// Noremote is flipped with a flag in dam-client and disables fetching Err parazyd.org 70 i-// remote entry points (directories) if enabled. Err parazyd.org 70 i-var Noremote = false Err parazyd.org 70 1diff --git a/pkg/damlib/config_test.go b/pkg/damlib/config_test.go /git/tordam/file/pkg/damlib/config_test.go.gph parazyd.org 70 it@@ -1,31 +0,0 @@ Err parazyd.org 70 i-package damlib Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2018 Dyne.org Foundation Err parazyd.org 70 i- * tor-dam is written and maintained by Ivan J. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This source code is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This software is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU General Public License Err parazyd.org 70 i- * along with this source code. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "os" Err parazyd.org 70 i- "testing" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-func TestMain(m *testing.M) { Err parazyd.org 70 i- ex := m.Run() Err parazyd.org 70 i- os.Exit(ex) Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/pkg/damlib/crypto_25519.go b/pkg/damlib/crypto_25519.go /git/tordam/file/pkg/damlib/crypto_25519.go.gph parazyd.org 70 it@@ -21,8 +21,11 @@ package damlib Err parazyd.org 70 i */ Err parazyd.org 70 i Err parazyd.org 70 i import ( Err parazyd.org 70 i+ "crypto" Err parazyd.org 70 i "crypto/rand" Err parazyd.org 70 i+ "crypto/sha512" Err parazyd.org 70 i "encoding/base32" Err parazyd.org 70 i+ "encoding/base64" Err parazyd.org 70 i "io/ioutil" Err parazyd.org 70 i "log" Err parazyd.org 70 i "strings" Err parazyd.org 70 it@@ -34,34 +37,66 @@ import ( Err parazyd.org 70 i // GenEd25519 generates an ed25519 keypair. Returns error on failure. Err parazyd.org 70 i func GenEd25519() (ed25519.PublicKey, ed25519.PrivateKey, error) { Err parazyd.org 70 i log.Println("Generating ed25519 keypair...") Err parazyd.org 70 i- rng := rand.Reader Err parazyd.org 70 i- pk, sk, err := ed25519.GenerateKey(rng) Err parazyd.org 70 i+ Err parazyd.org 70 i+ pk, sk, err := ed25519.GenerateKey(rand.Reader) Err parazyd.org 70 i if err != nil { Err parazyd.org 70 i return nil, nil, err Err parazyd.org 70 i } Err parazyd.org 70 i return pk, sk, nil Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i-// SavePubEd25519 writes a ed25519.PublicKey type to a given string filename. Err parazyd.org 70 i-// Returns error upon failure. Err parazyd.org 70 i-func SavePubEd25519(filename string, key ed25519.PublicKey) error { Err parazyd.org 70 i- log.Println("Writing ed25519 public key to", filename) Err parazyd.org 70 i- const pkprefix = "== ed25519v1-public: type0 ==" Err parazyd.org 70 i- var pub []byte Err parazyd.org 70 i- pub = append(pub, []byte(pkprefix)...) Err parazyd.org 70 i- pub = append(pub, []byte(key)...) Err parazyd.org 70 i- return ioutil.WriteFile(filename, pub, 0600) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i // SavePrivEd25519 writes a ed25519.PrivateKey type to a given string filename. Err parazyd.org 70 i-// Returns error upon failure. Err parazyd.org 70 i+// Expands ed25519.PrivateKey to (a || RH) form, writing base64. Returns error Err parazyd.org 70 i+// upon failure. Err parazyd.org 70 i func SavePrivEd25519(filename string, key ed25519.PrivateKey) error { Err parazyd.org 70 i log.Println("Writing ed25519 private key to", filename) Err parazyd.org 70 i- const skprefix = "== ed25519v1-secret: type0 ==" Err parazyd.org 70 i- var sec []byte Err parazyd.org 70 i- sec = append(sec, []byte(skprefix)...) Err parazyd.org 70 i- sec = append(sec, []byte(key)...) Err parazyd.org 70 i- return ioutil.WriteFile(filename, sec, 0600) Err parazyd.org 70 i+ Err parazyd.org 70 i+ h := sha512.Sum512(key[:32]) Err parazyd.org 70 i+ // Set bits so that h[:32] is a private scalar "a". Err parazyd.org 70 i+ h[0] &= 248 Err parazyd.org 70 i+ h[31] &= 127 Err parazyd.org 70 i+ h[31] |= 64 Err parazyd.org 70 i+ // Since h[32:] is RH, h is now (a || RH) Err parazyd.org 70 i+ encoded := base64.StdEncoding.EncodeToString(h[:]) Err parazyd.org 70 i+ return ioutil.WriteFile(filename, []byte(encoded), 0600) Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+// SaveSeedEd25519 saves the ed25519 private key seed to a given string filename Err parazyd.org 70 i+// for later reuse. Returns error upon failure. Err parazyd.org 70 i+func SaveSeedEd25519(filename string, key ed25519.PrivateKey) error { Err parazyd.org 70 i+ log.Println("Writing ed25519 private key seed to", filename) Err parazyd.org 70 i+ Err parazyd.org 70 i+ encoded := base64.StdEncoding.EncodeToString(key.Seed()) Err parazyd.org 70 i+ return ioutil.WriteFile(filename, []byte(encoded), 0600) Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+// LoadEd25519KeyFromSeed loads a key from a given seed file and returns Err parazyd.org 70 i+// ed25519.PrivateKey. Otherwise, on failure, it returns error. Err parazyd.org 70 i+func LoadEd25519KeyFromSeed(filename string) (ed25519.PrivateKey, error) { Err parazyd.org 70 i+ log.Println("Loading ed25519 private key from seed in", filename) Err parazyd.org 70 i+ Err parazyd.org 70 i+ data, err := ioutil.ReadFile(filename) Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ return nil, err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ decoded, err := base64.StdEncoding.DecodeString(string(data)) Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ return nil, err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ return ed25519.NewKeyFromSeed(decoded), nil Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+// SignMsgEd25519 signs a message using ed25519. Returns the signature in the Err parazyd.org 70 i+// form of []byte, or returns an error if it fails. Err parazyd.org 70 i+func SignMsgEd25519(message []byte, key ed25519.PrivateKey) ([]byte, error) { Err parazyd.org 70 i+ log.Println("Signing message...") Err parazyd.org 70 i+ Err parazyd.org 70 i+ sig, err := key.Sign(rand.Reader, message, crypto.Hash(0)) Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ return nil, err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ return sig, nil Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i // OnionFromPubkeyEd25519 generates a valid onion address from a given ed25519 Err parazyd.org 70 it@@ -83,21 +118,19 @@ func SavePrivEd25519(filename string, key ed25519.PrivateKey) error { Err parazyd.org 70 i // - ".onion checksum" is a constant string Err parazyd.org 70 i // - CHECKSUM is truncated to two bytes before inserting it in onion_address Err parazyd.org 70 i func OnionFromPubkeyEd25519(pubkey ed25519.PublicKey) []byte { Err parazyd.org 70 i- const hashConst = ".onion checksum" Err parazyd.org 70 i- const versConst = '\x03' Err parazyd.org 70 i+ const salt = ".onion checksum" Err parazyd.org 70 i+ const version = byte(0x03) Err parazyd.org 70 i Err parazyd.org 70 i- var h []byte Err parazyd.org 70 i- h = append(h, []byte(hashConst)...) Err parazyd.org 70 i- h = append(h, []byte(pubkey)...) Err parazyd.org 70 i- h = append(h, byte(versConst)) Err parazyd.org 70 i+ h := []byte(salt) Err parazyd.org 70 i+ h = append(h, pubkey...) Err parazyd.org 70 i+ h = append(h, version) Err parazyd.org 70 i Err parazyd.org 70 i csum := sha3.Sum256(h) Err parazyd.org 70 i checksum := csum[:2] Err parazyd.org 70 i Err parazyd.org 70 i- var enc []byte Err parazyd.org 70 i- enc = append(enc, []byte(pubkey)...) Err parazyd.org 70 i+ enc := pubkey[:] Err parazyd.org 70 i enc = append(enc, checksum...) Err parazyd.org 70 i- enc = append(enc, byte(versConst)) Err parazyd.org 70 i+ enc = append(enc, version) Err parazyd.org 70 i Err parazyd.org 70 i encoded := base32.StdEncoding.EncodeToString(enc) Err parazyd.org 70 i return []byte(strings.ToLower(encoded) + ".onion") Err parazyd.org 70 1diff --git a/pkg/damlib/crypto_25519_test.go b/pkg/damlib/crypto_25519_test.go /git/tordam/file/pkg/damlib/crypto_25519_test.go.gph parazyd.org 70 it@@ -1,82 +0,0 @@ Err parazyd.org 70 i-package damlib Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2018 Dyne.org Foundation Err parazyd.org 70 i- * tor-dam is written and maintained by Ivan J. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This source code is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This software is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU General Public License Err parazyd.org 70 i- * along with this source code. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "os" Err parazyd.org 70 i- "testing" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-func TestGenEd25519(t *testing.T) { Err parazyd.org 70 i- _, _, err := GenEd25519() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal("Failed generating ed25519 key:", err.Error()) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- t.Log("Successfully generated ed25519 keypair.") Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func TestSavePubEd25519(t *testing.T) { Err parazyd.org 70 i- pk, _, err := GenEd25519() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal("Failed generating ed25519 key:", err.Error()) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- err = SavePubEd25519("/tmp/ed25519pub.test", pk) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal("Failed saving pubkey:", err.Error()) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- os.Remove("/tmp/ed25519pub.test") Err parazyd.org 70 i- t.Log("Success saving ed25519 pubkey") Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func TestSavePrivEd25519(t *testing.T) { Err parazyd.org 70 i- _, sk, err := GenEd25519() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal("Failed generating ed25519 key:", err.Error()) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- err = SavePrivEd25519("/tmp/ed25519priv.test", sk) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal("Failed saving privkey:", err.Error()) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- os.Remove("/tmp/ed25519priv.test") Err parazyd.org 70 i- t.Log("Success saving ed25519 privkey") Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func TestOnionFromPubkeyEd25519(t *testing.T) { Err parazyd.org 70 i- pk, _, err := GenEd25519() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal("Failed generating ed25519 key:", err.Error()) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- res := OnionFromPubkeyEd25519(pk) Err parazyd.org 70 i- valid := ValidateOnionAddress(string(res)) Err parazyd.org 70 i- Err parazyd.org 70 i- t.Log("Got:", string(res)) Err parazyd.org 70 i- Err parazyd.org 70 i- if !valid { Err parazyd.org 70 i- t.Fatal("Address is invalid.") Err parazyd.org 70 i- } Err parazyd.org 70 i- t.Log("Address is valid") Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/pkg/damlib/crypto_common.go b/pkg/damlib/crypto_common.go /git/tordam/file/pkg/damlib/crypto_common.go.gph parazyd.org 70 it@@ -1,46 +0,0 @@ Err parazyd.org 70 i-package damlib Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2018 Dyne.org Foundation Err parazyd.org 70 i- * tor-dam is written and maintained by Ivan J. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This source code is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This software is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU General Public License Err parazyd.org 70 i- * along with this source code. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "crypto/rand" Err parazyd.org 70 i- "math/big" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-// GenRandomASCII generates a random ASCII string of a given length. Err parazyd.org 70 i-// Takes length int as argument, and returns a string of that length on success Err parazyd.org 70 i-// and error on failure. Err parazyd.org 70 i-func GenRandomASCII(length int) (string, error) { Err parazyd.org 70 i- var res string Err parazyd.org 70 i- for { Err parazyd.org 70 i- if len(res) >= length { Err parazyd.org 70 i- return res, nil Err parazyd.org 70 i- } Err parazyd.org 70 i- num, err := rand.Int(rand.Reader, big.NewInt(int64(127))) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return "", err Err parazyd.org 70 i- } Err parazyd.org 70 i- n := num.Int64() Err parazyd.org 70 i- if n > 32 && n < 127 { Err parazyd.org 70 i- res += string(n) Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/pkg/damlib/crypto_common_test.go b/pkg/damlib/crypto_common_test.go /git/tordam/file/pkg/damlib/crypto_common_test.go.gph parazyd.org 70 it@@ -1,38 +0,0 @@ Err parazyd.org 70 i-package damlib Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2018 Dyne.org Foundation Err parazyd.org 70 i- * tor-dam is written and maintained by Ivan J. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This source code is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This software is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU General Public License Err parazyd.org 70 i- * along with this source code. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "testing" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-func TestGenRandomASCII(t *testing.T) { Err parazyd.org 70 i- res, err := GenRandomASCII(18) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal("Failed making random string:", err.Error()) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- if len(res) != 18 { Err parazyd.org 70 i- t.Fatal("String is of incorrect length: 18 !=", len(res)) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- t.Log("Got:", res) Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/pkg/damlib/crypto_rsa.go b/pkg/damlib/crypto_rsa.go /git/tordam/file/pkg/damlib/crypto_rsa.go.gph parazyd.org 70 it@@ -1,197 +0,0 @@ Err parazyd.org 70 i-package damlib Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2018 Dyne.org Foundation Err parazyd.org 70 i- * tor-dam is written and maintained by Ivan J. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This source code is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This software is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU General Public License Err parazyd.org 70 i- * along with this source code. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "crypto" Err parazyd.org 70 i- "crypto/rand" Err parazyd.org 70 i- "crypto/rsa" Err parazyd.org 70 i- "crypto/sha1" Err parazyd.org 70 i- "crypto/sha512" Err parazyd.org 70 i- "crypto/x509" Err parazyd.org 70 i- "encoding/asn1" Err parazyd.org 70 i- "encoding/base32" Err parazyd.org 70 i- "encoding/pem" Err parazyd.org 70 i- "errors" Err parazyd.org 70 i- "io/ioutil" Err parazyd.org 70 i- "log" Err parazyd.org 70 i- "os" Err parazyd.org 70 i- "strings" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-// GenRsa generates a private RSA keypair of a given bitSize int and returns it Err parazyd.org 70 i-// as rsa.PrivateKey. Err parazyd.org 70 i-func GenRsa(bitSize int) (*rsa.PrivateKey, error) { Err parazyd.org 70 i- log.Printf("Generating %d-bit RSA keypair...\n", bitSize) Err parazyd.org 70 i- rng := rand.Reader Err parazyd.org 70 i- key, err := rsa.GenerateKey(rng, bitSize) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- return key, nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-// SavePubRsa saves a given RSA public key to a given filename. Err parazyd.org 70 i-// SavePubRsa takes the filename to write as a string, and the key as Err parazyd.org 70 i-// rsa.PublicKey. It returns an error on failure, otherwise: nil Err parazyd.org 70 i-func SavePubRsa(filename string, pubkey rsa.PublicKey) error { Err parazyd.org 70 i- log.Println("Writing RSA pubkey to", filename) Err parazyd.org 70 i- outfile, err := os.Create(filename) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return err Err parazyd.org 70 i- } Err parazyd.org 70 i- defer outfile.Close() Err parazyd.org 70 i- asn1Bytes, err := asn1.Marshal(pubkey) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return err Err parazyd.org 70 i- } Err parazyd.org 70 i- var pemkey = &pem.Block{ Err parazyd.org 70 i- Type: "RSA PUBLIC KEY", Err parazyd.org 70 i- Bytes: asn1Bytes, Err parazyd.org 70 i- } Err parazyd.org 70 i- if err = pem.Encode(outfile, pemkey); err != nil { Err parazyd.org 70 i- return err Err parazyd.org 70 i- } Err parazyd.org 70 i- return outfile.Chmod(0400) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-// SavePrivRsa saves a given RSA private key to a given filename. Err parazyd.org 70 i-// SavePrivRsa takes the filename to write as a string, and the key as Err parazyd.org 70 i-// *rsa.PrivateKey. It returns an error on failure, otherwise: nil Err parazyd.org 70 i-func SavePrivRsa(filename string, privkey *rsa.PrivateKey) error { Err parazyd.org 70 i- log.Printf("Writing private key to %s\n", filename) Err parazyd.org 70 i- outfile, err := os.Create(filename) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return err Err parazyd.org 70 i- } Err parazyd.org 70 i- defer outfile.Close() Err parazyd.org 70 i- var pemkey = &pem.Block{ Err parazyd.org 70 i- Type: "RSA PRIVATE KEY", Err parazyd.org 70 i- Bytes: x509.MarshalPKCS1PrivateKey(privkey), Err parazyd.org 70 i- } Err parazyd.org 70 i- if err = pem.Encode(outfile, pemkey); err != nil { Err parazyd.org 70 i- return err Err parazyd.org 70 i- } Err parazyd.org 70 i- return outfile.Chmod(0400) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-// LoadRsaKeyFromFile loads a RSA private key from a given filename. Err parazyd.org 70 i-// LoadRsaKeyFromFile takes a string filename and tries to read from it, parsing Err parazyd.org 70 i-// the private RSA key. It will return a *rsa.PrivateKey on success, and error Err parazyd.org 70 i-// on fail. Err parazyd.org 70 i-func LoadRsaKeyFromFile(filename string) (*rsa.PrivateKey, error) { Err parazyd.org 70 i- log.Println("Loading RSA private key from", filename) Err parazyd.org 70 i- dat, err := ioutil.ReadFile(filename) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- block, _ := pem.Decode(dat) Err parazyd.org 70 i- if block == nil { Err parazyd.org 70 i- return nil, errors.New("failed to parse PEM block containing the key") Err parazyd.org 70 i- } Err parazyd.org 70 i- priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- return priv, nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-// SignMsgRsa signs a given []byte message using a given RSA private key. Err parazyd.org 70 i-// It will return the signature as a slice of bytes on success, and error on Err parazyd.org 70 i-// failure. Err parazyd.org 70 i-func SignMsgRsa(message []byte, privkey *rsa.PrivateKey) ([]byte, error) { Err parazyd.org 70 i- log.Println("Signing message...") Err parazyd.org 70 i- rng := rand.Reader Err parazyd.org 70 i- hashed := sha512.Sum512(message) Err parazyd.org 70 i- sig, err := rsa.SignPKCS1v15(rng, privkey, crypto.SHA512, hashed[:]) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- return sig, nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-// EncryptMsgRsa encrypts a given []byte message using a given RSA public key. Err parazyd.org 70 i-// Returns the encrypted message as a slice of bytes on success, and error on Err parazyd.org 70 i-// failure. Err parazyd.org 70 i-func EncryptMsgRsa(message []byte, pubkey *rsa.PublicKey) ([]byte, error) { Err parazyd.org 70 i- log.Println("Encrypting message...") Err parazyd.org 70 i- rng := rand.Reader Err parazyd.org 70 i- msg, err := rsa.EncryptPKCS1v15(rng, pubkey, message) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- return msg, nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-// DecryptMsgRsa decrypts a given []byte message using a given RSA private key. Err parazyd.org 70 i-// Returns the decrypted message as a slice of bytes on success, and error on Err parazyd.org 70 i-// failure. Err parazyd.org 70 i-func DecryptMsgRsa(message []byte, privkey *rsa.PrivateKey) ([]byte, error) { Err parazyd.org 70 i- log.Println("Decrypting message...") Err parazyd.org 70 i- rng := rand.Reader Err parazyd.org 70 i- msg, err := rsa.DecryptPKCS1v15(rng, privkey, message) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- return msg, nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-// VerifyMsgRsa verifies a message and signature against a given RSA pubkey. Err parazyd.org 70 i-// Returns a boolean value and error depending on whether it has failed or not. Err parazyd.org 70 i-func VerifyMsgRsa(message []byte, signature []byte, pubkey *rsa.PublicKey) (bool, error) { Err parazyd.org 70 i- log.Println("Verifying message signature") Err parazyd.org 70 i- hashed := sha512.Sum512(message) Err parazyd.org 70 i- if err := rsa.VerifyPKCS1v15(pubkey, crypto.SHA512, hashed[:], signature); err != nil { Err parazyd.org 70 i- return false, err Err parazyd.org 70 i- } Err parazyd.org 70 i- return true, nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-// OnionFromPubkeyRsa generates a valid onion address from a given RSA pubkey. Err parazyd.org 70 i-// Returns the onion address as a slice of bytes on success and error on Err parazyd.org 70 i-// failure. Err parazyd.org 70 i-func OnionFromPubkeyRsa(pubkey rsa.PublicKey) ([]byte, error) { Err parazyd.org 70 i- asn1Bytes, err := asn1.Marshal(pubkey) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- hashed := sha1.New() Err parazyd.org 70 i- if _, err = hashed.Write(asn1Bytes); err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- encoded := strings.ToLower(base32.StdEncoding.EncodeToString(hashed.Sum(nil)))[:16] Err parazyd.org 70 i- encoded += ".onion" Err parazyd.org 70 i- Err parazyd.org 70 i- return []byte(encoded), nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-// ParsePubkeyRsa parses a []byte form of a RSA public key and returns it as Err parazyd.org 70 i-// *rsa.PublicKey on success. Otherwise, error. Err parazyd.org 70 i-func ParsePubkeyRsa(pubkey []byte) (*rsa.PublicKey, error) { Err parazyd.org 70 i- var pub rsa.PublicKey Err parazyd.org 70 i- var ret *rsa.PublicKey Err parazyd.org 70 i- block, _ := pem.Decode(pubkey) Err parazyd.org 70 i- if _, err := asn1.Unmarshal(block.Bytes, &pub); err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- ret = &pub Err parazyd.org 70 i- return ret, nil Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/pkg/damlib/helpers.go b/pkg/damlib/helpers.go /git/tordam/file/pkg/damlib/helpers.go.gph parazyd.org 70 it@@ -23,8 +23,10 @@ package damlib Err parazyd.org 70 i import ( Err parazyd.org 70 i "bytes" Err parazyd.org 70 i "compress/gzip" Err parazyd.org 70 i+ "crypto/rand" Err parazyd.org 70 i "encoding/base64" Err parazyd.org 70 i "log" Err parazyd.org 70 i+ "math/big" Err parazyd.org 70 i "strings" Err parazyd.org 70 i ) Err parazyd.org 70 i Err parazyd.org 70 it@@ -73,9 +75,31 @@ func ParseDirs(sl []string, data []byte) []string { Err parazyd.org 70 i if strings.HasPrefix(j, "DIR:") { Err parazyd.org 70 i t := strings.Split(j, "DIR:") Err parazyd.org 70 i if !(StringInSlice(t[1], sl)) { Err parazyd.org 70 i- sl = append(sl, t[1]) Err parazyd.org 70 i+ if ValidateOnionAddress(t[1]) { Err parazyd.org 70 i+ sl = append(sl, t[1]) Err parazyd.org 70 i+ } Err parazyd.org 70 i } Err parazyd.org 70 i } Err parazyd.org 70 i } Err parazyd.org 70 i return sl Err parazyd.org 70 i } Err parazyd.org 70 i+ Err parazyd.org 70 i+// GenRandomASCII generates a random ASCII string of a given length. Err parazyd.org 70 i+// Takes length int as argument, and returns a string of that length on success Err parazyd.org 70 i+// and error on failure. Err parazyd.org 70 i+func GenRandomASCII(length int) (string, error) { Err parazyd.org 70 i+ var res string Err parazyd.org 70 i+ for { Err parazyd.org 70 i+ if len(res) >= length { Err parazyd.org 70 i+ return res, nil Err parazyd.org 70 i+ } Err parazyd.org 70 i+ num, err := rand.Int(rand.Reader, big.NewInt(int64(127))) Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ return "", err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ n := num.Int64() Err parazyd.org 70 i+ if n > 32 && n < 127 { Err parazyd.org 70 i+ res += string(n) Err parazyd.org 70 i+ } Err parazyd.org 70 i+ } Err parazyd.org 70 i+} Err parazyd.org 70 1diff --git a/pkg/damlib/helpers_test.go b/pkg/damlib/helpers_test.go /git/tordam/file/pkg/damlib/helpers_test.go.gph parazyd.org 70 it@@ -0,0 +1,65 @@ Err parazyd.org 70 i+package damlib Err parazyd.org 70 i+ Err parazyd.org 70 i+/* Err parazyd.org 70 i+ * Copyright (c) 2018 Dyne.org Foundation Err parazyd.org 70 i+ * tor-dam is written and maintained by Ivan J. Err parazyd.org 70 i+ * Err parazyd.org 70 i+ * This file is part of tor-dam Err parazyd.org 70 i+ * Err parazyd.org 70 i+ * This source code is free software: you can redistribute it and/or modify Err parazyd.org 70 i+ * it under the terms of the GNU General Public License as published by Err parazyd.org 70 i+ * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i+ * (at your option) any later version. Err parazyd.org 70 i+ * Err parazyd.org 70 i+ * This software is distributed in the hope that it will be useful, Err parazyd.org 70 i+ * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i+ * GNU General Public License for more details. Err parazyd.org 70 i+ * Err parazyd.org 70 i+ * You should have received a copy of the GNU General Public License Err parazyd.org 70 i+ * along with this source code. If not, see . Err parazyd.org 70 i+ */ Err parazyd.org 70 i+ Err parazyd.org 70 i+import ( Err parazyd.org 70 i+ "testing" Err parazyd.org 70 i+) Err parazyd.org 70 i+ Err parazyd.org 70 i+func TestStringInSlice(t *testing.T) { Err parazyd.org 70 i+ sl := []string{"foo", "bar", "baz"} Err parazyd.org 70 i+ if !(StringInSlice("bar", sl)) { Err parazyd.org 70 i+ t.Fatal("\"bar\" should be in the slice.") Err parazyd.org 70 i+ } Err parazyd.org 70 i+ if StringInSlice("kek", sl) { Err parazyd.org 70 i+ t.Fatal("\"kek\" should not be in the slice.") Err parazyd.org 70 i+ } Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+func TestGzipEncode(t *testing.T) { Err parazyd.org 70 i+ data := "Compress this string" Err parazyd.org 70 i+ if _, err := GzipEncode([]byte(data)); err != nil { Err parazyd.org 70 i+ t.Fatal(err) Err parazyd.org 70 i+ } Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+func TestParseDirs(t *testing.T) { Err parazyd.org 70 i+ var sl []string Err parazyd.org 70 i+ data := `DIR:gphjf5g3d5ywehwrd7cv3czymtdc6ha67bqplxwbspx7tioxt7gxqiid.onion Err parazyd.org 70 i+# Some random data Err parazyd.org 70 i+DIR:vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd.onion` Err parazyd.org 70 i+ Err parazyd.org 70 i+ sl = ParseDirs(sl, []byte(data)) Err parazyd.org 70 i+ Err parazyd.org 70 i+ if len(sl) != 2 { Err parazyd.org 70 i+ t.Fatal("Length of slice is not 2.") Err parazyd.org 70 i+ } Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+func TestGenRandomASCII(t *testing.T) { Err parazyd.org 70 i+ res, err := GenRandomASCII(64) Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ t.Fatal(err) Err parazyd.org 70 i+ } Err parazyd.org 70 i+ if len(res) != 64 { Err parazyd.org 70 i+ t.Fatal("Length of ASCII string is not 64.") Err parazyd.org 70 i+ } Err parazyd.org 70 i+} Err parazyd.org 70 1diff --git a/pkg/damlib/net_test.go b/pkg/damlib/net_test.go /git/tordam/file/pkg/damlib/net_test.go.gph parazyd.org 70 it@@ -1,51 +0,0 @@ Err parazyd.org 70 i-package damlib Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2018 Dyne.org Foundation Err parazyd.org 70 i- * tor-dam is written and maintained by Ivan J. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This source code is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This software is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU General Public License Err parazyd.org 70 i- * along with this source code. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "io/ioutil" Err parazyd.org 70 i- "testing" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-func TestHTTPPost(t *testing.T) { Err parazyd.org 70 i- data := []byte("foobar") Err parazyd.org 70 i- Err parazyd.org 70 i- resp, err := HTTPPost("https://requestb.in/ykdug2yk", data) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal("Unable to HTTPPost:", err.Error()) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- res, err := ioutil.ReadAll(resp.Body) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal("Unable to read response:", err.Error()) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- t.Log("Got:", string(res)) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func TestHTTPDownload(t *testing.T) { Err parazyd.org 70 i- data, err := HTTPDownload("https://requestb.in/ykdug2yk") Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- t.Fatal("Unable to HTTPDownload:", err.Error()) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- t.Log("Got:", string(data)) Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/pkg/damlib/redis.go b/pkg/damlib/redis.go /git/tordam/file/pkg/damlib/redis.go.gph parazyd.org 70 it@@ -22,6 +22,9 @@ package damlib Err parazyd.org 70 i Err parazyd.org 70 i import ( Err parazyd.org 70 i "fmt" Err parazyd.org 70 i+ "log" Err parazyd.org 70 i+ "os/exec" Err parazyd.org 70 i+ "time" Err parazyd.org 70 i Err parazyd.org 70 i "github.com/go-redis/redis" Err parazyd.org 70 i ) Err parazyd.org 70 it@@ -36,6 +39,30 @@ var RedisCli = redis.NewClient(&redis.Options{ Err parazyd.org 70 i DB: 0, Err parazyd.org 70 i }) Err parazyd.org 70 i Err parazyd.org 70 i+// StartRedis is the function that will start up the Redis server. Takes the Err parazyd.org 70 i+// path to a configuration file as an argument and returns error upon failure. Err parazyd.org 70 i+func StartRedis(conf string) (*exec.Cmd, error) { Err parazyd.org 70 i+ log.Println("Starting up redis-server...") Err parazyd.org 70 i+ cmd := exec.Command("redis-server", conf) Err parazyd.org 70 i+ err := cmd.Start() Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ return cmd, err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ time.Sleep(500 * time.Millisecond) Err parazyd.org 70 i+ if _, err := RedisCli.Ping().Result(); err != nil { Err parazyd.org 70 i+ return cmd, err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ PubSub := RedisCli.Subscribe(PubSubChan) Err parazyd.org 70 i+ if _, err := PubSub.Receive(); err != nil { Err parazyd.org 70 i+ return cmd, err Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ log.Printf("Created \"%s\" channel in Redis.\n", PubSubChan) Err parazyd.org 70 i+ return cmd, nil Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i // PublishToRedis is a function that publishes a node's status to Redis. Err parazyd.org 70 i // This is used for Gource visualization. Err parazyd.org 70 i func PublishToRedis(mt, address string) { Err parazyd.org 70 1diff --git a/pkg/damlib/tor.go b/pkg/damlib/tor.go /git/tordam/file/pkg/damlib/tor.go.gph parazyd.org 70 it@@ -1,49 +0,0 @@ Err parazyd.org 70 i-package damlib Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2018 Dyne.org Foundation Err parazyd.org 70 i- * tor-dam is written and maintained by Ivan J. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This source code is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This software is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU General Public License Err parazyd.org 70 i- * along with this source code. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "bytes" Err parazyd.org 70 i- "log" Err parazyd.org 70 i- "os/exec" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-// FetchHSPubkey fetches a hidden service's RSA pubkey by running an external Err parazyd.org 70 i-// program, giving it an onion address. It returns the retrieved public key as a Err parazyd.org 70 i-// string. Err parazyd.org 70 i-func FetchHSPubkey(addr string) string { Err parazyd.org 70 i- var outb, errb bytes.Buffer Err parazyd.org 70 i- Err parazyd.org 70 i- log.Println("Fetching pubkey for:", addr) Err parazyd.org 70 i- Err parazyd.org 70 i- cmd := exec.Command("damauth.py", addr) Err parazyd.org 70 i- cmd.Stdout = &outb Err parazyd.org 70 i- cmd.Stderr = &errb Err parazyd.org 70 i- err := cmd.Start() Err parazyd.org 70 i- CheckError(err) Err parazyd.org 70 i- Err parazyd.org 70 i- if err = cmd.Wait(); err != nil { Err parazyd.org 70 i- log.Println("Could not fetch descriptor:", err) Err parazyd.org 70 i- return "" Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- return outb.String() Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/pkg/damlib/tor_test.go b/pkg/damlib/tor_test.go /git/tordam/file/pkg/damlib/tor_test.go.gph parazyd.org 70 it@@ -1,36 +0,0 @@ Err parazyd.org 70 i-package damlib Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2018 Dyne.org Foundation Err parazyd.org 70 i- * tor-dam is written and maintained by Ivan J. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This source code is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This software is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU General Public License Err parazyd.org 70 i- * along with this source code. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "strings" Err parazyd.org 70 i- "testing" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-func TestFetchHSPubkey(t *testing.T) { Err parazyd.org 70 i- pubkey := FetchHSPubkey("facebookcorewwwi.onion") Err parazyd.org 70 i- Err parazyd.org 70 i- if !strings.HasPrefix(pubkey, "-----BEGIN") { Err parazyd.org 70 i- t.Fatal("Did not get a public key.") Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- t.Log("Got:", pubkey) Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/pkg/damlib/validate.go b/pkg/damlib/validate.go /git/tordam/file/pkg/damlib/validate.go.gph parazyd.org 70 it@@ -22,21 +22,18 @@ package damlib Err parazyd.org 70 i Err parazyd.org 70 i import ( Err parazyd.org 70 i "encoding/base64" Err parazyd.org 70 i- "errors" Err parazyd.org 70 i "log" Err parazyd.org 70 i "regexp" Err parazyd.org 70 i- "strings" Err parazyd.org 70 i "time" Err parazyd.org 70 i+ Err parazyd.org 70 i+ "golang.org/x/crypto/ed25519" Err parazyd.org 70 i ) Err parazyd.org 70 i Err parazyd.org 70 i // ValidateOnionAddress matches a string against a regular expression matching Err parazyd.org 70 i // a Tor hidden service address. Returns true on success and false on failure. Err parazyd.org 70 i func ValidateOnionAddress(addr string) bool { Err parazyd.org 70 i- re, _ := regexp.Compile(`^[a-z2-7](?:.{55}|.{15})\.onion`) Err parazyd.org 70 i- if len(re.FindString(addr)) == 22 || len(re.FindString(addr)) == 62 { Err parazyd.org 70 i- return true Err parazyd.org 70 i- } Err parazyd.org 70 i- return false Err parazyd.org 70 i+ re, _ := regexp.Compile(`^[a-z2-7](?:.{55})\.onion`) Err parazyd.org 70 i+ return len(re.FindString(addr)) == 62 Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i // sanityCheck performs basic sanity checks against the incoming request. Err parazyd.org 70 it@@ -50,17 +47,6 @@ func sanityCheck(req map[string]string, handshake int) (bool, string) { Err parazyd.org 70 i return false, err.Error() Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i- // TODO: When a node wants to promote itself from something it already was, Err parazyd.org 70 i- // what to do? Err parazyd.org 70 i- switch req["nodetype"] { Err parazyd.org 70 i- case "node": Err parazyd.org 70 i- log.Printf("%s is a node.", req["address"]) Err parazyd.org 70 i- case "directory": Err parazyd.org 70 i- log.Printf("%s is a directory.", req["address"]) Err parazyd.org 70 i- default: Err parazyd.org 70 i- return false, "Invalid nodetype." Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i if handshake == 2 { Err parazyd.org 70 i if _, err := base64.StdEncoding.DecodeString(req["message"]); err != nil { Err parazyd.org 70 i return false, err.Error() Err parazyd.org 70 it@@ -72,69 +58,49 @@ func sanityCheck(req map[string]string, handshake int) (bool, string) { Err parazyd.org 70 i return true, "" Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i-// ValidateFirstHandshake validates the first incoming handshake. Err parazyd.org 70 i-// It first calls sanityCheck to validate it's actually working with proper Err parazyd.org 70 i-// data. Err parazyd.org 70 i-// Next, it will look if the node is already found in redis. If so, it will Err parazyd.org 70 i-// fetch its public hey from redis, otherwise it will run an external program to Err parazyd.org 70 i-// fetch the node's public key from a Tor HSDir. If that program fails, so will Err parazyd.org 70 i-// the function. Err parazyd.org 70 i-// Once the public key is retrieved, it will validate the received message Err parazyd.org 70 i-// signature against that key. If all is well, we consider the request valid. Err parazyd.org 70 i-// Continuing, a random ASCII string will be generated and encrypted with the Err parazyd.org 70 i-// retrieved public key. All this data will be written into redis, and finally Err parazyd.org 70 i-// the encrypted (and base64 encoded) secret will be returned along with a true Err parazyd.org 70 i-// boolean value. Err parazyd.org 70 i-// On any failure, the function will return false, and produce an according Err parazyd.org 70 i-// string which is to be considered as an error message. Err parazyd.org 70 i+// ValidateFirstHandshake validates the first incoming handshake. It first calls Err parazyd.org 70 i+// sanityCheck to validate it's actually working with proper data. Next, it will Err parazyd.org 70 i+// look if the node is already found in redis. If so, it will fetch its public Err parazyd.org 70 i+// hey from redis, otherwise it will take it from the initial request from the Err parazyd.org 70 i+// incoming node. Once the public key is retrieved, it will validate the Err parazyd.org 70 i+// received message signature against that key. If all is well, we consider the Err parazyd.org 70 i+// request valid. Continuing, a random ASCII string will be generated and Err parazyd.org 70 i+// encrypted with the retrieved public key. All this data will be written into Err parazyd.org 70 i+// redis, and finally the encrypted (and base64 encoded) secret will be returned Err parazyd.org 70 i+// along with a true boolean value. On any failure, the function will return Err parazyd.org 70 i+// false, and produce an according string which is to be considered as an error Err parazyd.org 70 i+// message. Err parazyd.org 70 i func ValidateFirstHandshake(req map[string]string) (bool, string) { Err parazyd.org 70 i if sane, what := sanityCheck(req, 1); !(sane) { Err parazyd.org 70 i return false, what Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i // Get the public key. Err parazyd.org 70 i- var pub string Err parazyd.org 70 i+ var pubstr string Err parazyd.org 70 i+ var pubkey ed25519.PublicKey Err parazyd.org 70 i // Check if we have seen this node already. Err parazyd.org 70 i ex, err := RedisCli.Exists(req["address"]).Result() Err parazyd.org 70 i CheckError(err) Err parazyd.org 70 i if ex == 1 { Err parazyd.org 70 i // We saw it so we should have the public key in redis. Err parazyd.org 70 i // If we do not, that is an internal error. Err parazyd.org 70 i- pub, err = RedisCli.HGet(req["address"], "pubkey").Result() Err parazyd.org 70 i+ pubstr, err = RedisCli.HGet(req["address"], "pubkey").Result() Err parazyd.org 70 i CheckError(err) Err parazyd.org 70 i- // FIXME: Do a smarter check Err parazyd.org 70 i- if len(pub) < 20 { Err parazyd.org 70 i- CheckError(errors.New("Invalid data fetched from redis when requesting pubkey")) Err parazyd.org 70 i- } Err parazyd.org 70 i } else { Err parazyd.org 70 i- // We fetch it from a HSDir Err parazyd.org 70 i- cnt := 0 Err parazyd.org 70 i- for { // We try until we have it. Err parazyd.org 70 i- cnt++ Err parazyd.org 70 i- if cnt > 10 { Err parazyd.org 70 i- // We probably can't get a good HSDir. The client shall retry Err parazyd.org 70 i- // later on. Err parazyd.org 70 i- return false, "Could not get a descriptor. Try later." Err parazyd.org 70 i- } Err parazyd.org 70 i- pub = FetchHSPubkey(req["address"]) Err parazyd.org 70 i- if strings.HasPrefix(pub, "-----BEGIN RSA PUBLIC KEY-----") && Err parazyd.org 70 i- strings.HasSuffix(pub, "-----END RSA PUBLIC KEY-----") { Err parazyd.org 70 i- log.Println("Got descriptor!") Err parazyd.org 70 i- break Err parazyd.org 70 i- } Err parazyd.org 70 i- time.Sleep(2000 * time.Millisecond) Err parazyd.org 70 i- } Err parazyd.org 70 i+ // We take it from the announce. Err parazyd.org 70 i+ pubstr = req["pubkey"] Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i // Validate signature. Err parazyd.org 70 i msg := []byte(req["message"]) Err parazyd.org 70 i- decSig, _ := base64.StdEncoding.DecodeString(req["signature"]) Err parazyd.org 70 i- sig := decSig Err parazyd.org 70 i- pubkey, err := ParsePubkeyRsa([]byte(pub)) // pubkey is their public key in *rsa.PublicKey type Err parazyd.org 70 i+ sig, _ := base64.StdEncoding.DecodeString(req["signature"]) Err parazyd.org 70 i+ deckey, err := base64.StdEncoding.DecodeString(pubstr) Err parazyd.org 70 i CheckError(err) Err parazyd.org 70 i- if val, _ := VerifyMsgRsa(msg, sig, pubkey); !(val) { Err parazyd.org 70 i- log.Println("crypto/rsa: verification failure") Err parazyd.org 70 i- return false, "Signature verification failure." Err parazyd.org 70 i+ pubkey = ed25519.PublicKey(deckey) Err parazyd.org 70 i+ Err parazyd.org 70 i+ if !(ed25519.Verify(pubkey, msg, sig)) { Err parazyd.org 70 i+ log.Println("crypto/ed25519: Signature verification failure.") Err parazyd.org 70 i+ return false, "Signature verification vailure." Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i // The request is valid at this point. Err parazyd.org 70 it@@ -145,7 +111,6 @@ func ValidateFirstHandshake(req map[string]string) (bool, string) { Err parazyd.org 70 i encodedSecret := base64.StdEncoding.EncodeToString([]byte(randString)) Err parazyd.org 70 i Err parazyd.org 70 i var info = map[string]interface{}{ Err parazyd.org 70 i- "nodetype": req["nodetype"], Err parazyd.org 70 i "address": req["address"], Err parazyd.org 70 i "message": encodedSecret, Err parazyd.org 70 i "signature": req["signature"], Err parazyd.org 70 it@@ -153,7 +118,7 @@ func ValidateFirstHandshake(req map[string]string) (bool, string) { Err parazyd.org 70 i "lastseen": time.Now().Unix(), Err parazyd.org 70 i } // Can not cast, need this for HMSet Err parazyd.org 70 i if ex != 1 { // We did not have this node in redis. Err parazyd.org 70 i- info["pubkey"] = pub Err parazyd.org 70 i+ info["pubkey"] = pubstr Err parazyd.org 70 i info["firstseen"] = time.Now().Unix() Err parazyd.org 70 i if Testnet { Err parazyd.org 70 i info["valid"] = 1 Err parazyd.org 70 it@@ -170,11 +135,7 @@ func ValidateFirstHandshake(req map[string]string) (bool, string) { Err parazyd.org 70 i return false, "Internal server error" Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i- encryptedSecret, err := EncryptMsgRsa([]byte(randString), pubkey) Err parazyd.org 70 i- CheckError(err) Err parazyd.org 70 i- Err parazyd.org 70 i- encryptedEncodedSecret := base64.StdEncoding.EncodeToString(encryptedSecret) Err parazyd.org 70 i- return true, encryptedEncodedSecret Err parazyd.org 70 i+ return true, encodedSecret Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i // ValidateSecondHandshake validates the second part of the handshake. Err parazyd.org 70 it@@ -183,7 +144,7 @@ func ValidateFirstHandshake(req map[string]string) (bool, string) { Err parazyd.org 70 i // Next, the according public key will be retrieved from redis. If no key is Err parazyd.org 70 i // found, we will consider the handshake invalid. Err parazyd.org 70 i // Now the decrypted secret that was sent to us will be compared with what we Err parazyd.org 70 i-// have saved before. Upon proving they are the same, the RSA signature will now Err parazyd.org 70 i+// have saved before. Upon proving they are the same, the signature will now Err parazyd.org 70 i // be validated. If all is well, we consider the request valid. Err parazyd.org 70 i // Further on, we will generate a new random ASCII string and save it in redis Err parazyd.org 70 i // to prevent further reuse of the already known string. Upon success, the Err parazyd.org 70 it@@ -196,19 +157,16 @@ func ValidateSecondHandshake(req map[string]string) (bool, string) { Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i // Get the public key. Err parazyd.org 70 i- var pub string Err parazyd.org 70 i+ var pubstr string Err parazyd.org 70 i+ var pubkey ed25519.PublicKey Err parazyd.org 70 i // Check if we have seen this node already. Err parazyd.org 70 i ex, err := RedisCli.Exists(req["address"]).Result() Err parazyd.org 70 i CheckError(err) Err parazyd.org 70 i if ex == 1 { Err parazyd.org 70 i // We saw it so we should have the public key in redis. Err parazyd.org 70 i // If we do not, that is an internal error. Err parazyd.org 70 i- pub, err = RedisCli.HGet(req["address"], "pubkey").Result() Err parazyd.org 70 i+ pubstr, err = RedisCli.HGet(req["address"], "pubkey").Result() Err parazyd.org 70 i CheckError(err) Err parazyd.org 70 i- // FIXME: Do a smarter check Err parazyd.org 70 i- if len(pub) < 20 { Err parazyd.org 70 i- CheckError(errors.New("Invalid data fetched from redis when requesting pubkey")) Err parazyd.org 70 i- } Err parazyd.org 70 i } else { Err parazyd.org 70 i log.Printf("%s tried to jump in 2/2 handshake before doing the first.\n", req["address"]) Err parazyd.org 70 i return false, "We have not seen you before. Please authenticate properly." Err parazyd.org 70 it@@ -224,12 +182,13 @@ func ValidateSecondHandshake(req map[string]string) (bool, string) { Err parazyd.org 70 i Err parazyd.org 70 i // Validate signature. Err parazyd.org 70 i msg := []byte(req["message"]) Err parazyd.org 70 i- decSig, _ := base64.StdEncoding.DecodeString(req["signature"]) Err parazyd.org 70 i- sig := decSig Err parazyd.org 70 i- pubkey, err := ParsePubkeyRsa([]byte(pub)) // pubkey is their public key in *rsa.PublicKey type Err parazyd.org 70 i+ sig, _ := base64.StdEncoding.DecodeString(req["signature"]) Err parazyd.org 70 i+ deckey, err := base64.StdEncoding.DecodeString(pubstr) Err parazyd.org 70 i CheckError(err) Err parazyd.org 70 i- if val, _ := VerifyMsgRsa(msg, sig, pubkey); !(val) { Err parazyd.org 70 i- log.Printf("%s: Signature verification failure\n", req["address"]) Err parazyd.org 70 i+ pubkey = ed25519.PublicKey(deckey) Err parazyd.org 70 i+ Err parazyd.org 70 i+ if !(ed25519.Verify(pubkey, msg, sig)) { Err parazyd.org 70 i+ log.Println("crypto/ed25519: Signature verification failure") Err parazyd.org 70 i return false, "Signature verification failure." Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 it@@ -241,7 +200,6 @@ func ValidateSecondHandshake(req map[string]string) (bool, string) { Err parazyd.org 70 i encodedSecret := base64.StdEncoding.EncodeToString([]byte(randString)) Err parazyd.org 70 i Err parazyd.org 70 i var info = map[string]interface{}{ Err parazyd.org 70 i- "nodetype": req["nodetype"], Err parazyd.org 70 i "address": req["address"], Err parazyd.org 70 i "message": encodedSecret, Err parazyd.org 70 i "signature": req["signature"], Err parazyd.org 70 1diff --git a/pkg/damlib/validate_test.go b/pkg/damlib/validate_test.go /git/tordam/file/pkg/damlib/validate_test.go.gph parazyd.org 70 it@@ -0,0 +1,165 @@ Err parazyd.org 70 i+package damlib Err parazyd.org 70 i+ Err parazyd.org 70 i+/* Err parazyd.org 70 i+ * Copyright (c) 2018 Dyne.org Foundation Err parazyd.org 70 i+ * tor-dam is written and maintained by Ivan J. Err parazyd.org 70 i+ * Err parazyd.org 70 i+ * This file is part of tor-dam Err parazyd.org 70 i+ * Err parazyd.org 70 i+ * This source code is free software: you can redistribute it and/or modify Err parazyd.org 70 i+ * it under the terms of the GNU General Public License as published by Err parazyd.org 70 i+ * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i+ * (at your option) any later version. Err parazyd.org 70 i+ * Err parazyd.org 70 i+ * This software is distributed in the hope that it will be useful, Err parazyd.org 70 i+ * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i+ * GNU General Public License for more details. Err parazyd.org 70 i+ * Err parazyd.org 70 i+ * You should have received a copy of the GNU General Public License Err parazyd.org 70 i+ * along with this source code. If not, see . Err parazyd.org 70 i+ */ Err parazyd.org 70 i+ Err parazyd.org 70 i+import ( Err parazyd.org 70 i+ "encoding/base64" Err parazyd.org 70 i+ "testing" Err parazyd.org 70 i+) Err parazyd.org 70 i+ Err parazyd.org 70 i+func TestValidateOnionAddress(t *testing.T) { Err parazyd.org 70 i+ if !(ValidateOnionAddress("gphjf5g3d5ywehwrd7cv3czymtdc6ha67bqplxwbspx7tioxt7gxqiid.onion")) { Err parazyd.org 70 i+ t.Fatal("Validating a valid address failed.") Err parazyd.org 70 i+ } Err parazyd.org 70 i+ if ValidateOnionAddress("gphjf5g3d5ywe1wd.onion") { Err parazyd.org 70 i+ t.Fatal("Validating an invalid address succeeded.") Err parazyd.org 70 i+ } Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+func TestValidValidateFirstHandshake(t *testing.T) { Err parazyd.org 70 i+ req := map[string]string{ Err parazyd.org 70 i+ "address": "gphjf5g3d5ywehwrd7cv3czymtdc6ha67bqplxwbspx7tioxt7gxqiid.onion", Err parazyd.org 70 i+ "pubkey": "M86S9NsfcWIe0R/FXYs4ZMYvHB74YPXewZPv+aHXn80=", Err parazyd.org 70 i+ "message": "I am a DAM node!", Err parazyd.org 70 i+ "signature": "CWqptO9ZRIvYMIHd3XHXaVny+W23P8FGkfbn5lvUqeJbDcY3G8+B4G8iCCIQiZkxkMofe6RbstHn3L1x88c3AA==", Err parazyd.org 70 i+ "secret": "", Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ cmd, _ := StartRedis("../../contrib/redis.conf") Err parazyd.org 70 i+ valid, _ := ValidateFirstHandshake(req) Err parazyd.org 70 i+ if !(valid) { Err parazyd.org 70 i+ t.Fatal("Failed to validate first handshake.") Err parazyd.org 70 i+ } Err parazyd.org 70 i+ cmd.Process.Kill() Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+func TestInvalidValidateFirstHandshake(t *testing.T) { Err parazyd.org 70 i+ // Invalid message for this signature. Err parazyd.org 70 i+ req := map[string]string{ Err parazyd.org 70 i+ "address": "gphjf5g3d5ywehwrd7cv3czymtdc6ha67bqplxwbspx7tioxt7gxqiid.onion", Err parazyd.org 70 i+ "pubkey": "M86S9NsfcWIe0R/FXYs4ZMYvHB74YPXewZPv+aHXn80=", Err parazyd.org 70 i+ "message": "I am a bad DAM node!", Err parazyd.org 70 i+ "signature": "CWqptO9ZRIvYMIHd3XHXaVny+W23P8FGkfbn5lvUqeJbDcY3G8+B4G8iCCIQiZkxkMofe6RbstHn3L1x88c3AA==", Err parazyd.org 70 i+ "secret": "", Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ cmd, _ := StartRedis("../../contrib/redis.conf") Err parazyd.org 70 i+ valid, _ := ValidateFirstHandshake(req) Err parazyd.org 70 i+ if valid { Err parazyd.org 70 i+ t.Fatal("Invalid request passed as valid.") Err parazyd.org 70 i+ } Err parazyd.org 70 i+ cmd.Process.Kill() Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+func TestValidValidateSecondHandshake(t *testing.T) { Err parazyd.org 70 i+ cmd, _ := StartRedis("../../contrib/redis.conf") Err parazyd.org 70 i+ Err parazyd.org 70 i+ pk, sk, _ := GenEd25519() Err parazyd.org 70 i+ onionaddr := OnionFromPubkeyEd25519(pk) Err parazyd.org 70 i+ Err parazyd.org 70 i+ sig, err := SignMsgEd25519([]byte("I am a DAM node!"), sk) Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ t.Fatal(err) Err parazyd.org 70 i+ } Err parazyd.org 70 i+ encodedSig := base64.StdEncoding.EncodeToString(sig) Err parazyd.org 70 i+ encodedPub := base64.StdEncoding.EncodeToString([]byte(pk)) Err parazyd.org 70 i+ Err parazyd.org 70 i+ req := map[string]string{ Err parazyd.org 70 i+ "address": string(onionaddr), Err parazyd.org 70 i+ "pubkey": encodedPub, Err parazyd.org 70 i+ "message": "I am a DAM node!", Err parazyd.org 70 i+ "signature": encodedSig, Err parazyd.org 70 i+ "secret": "", Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ valid, secret := ValidateFirstHandshake(req) Err parazyd.org 70 i+ if !(valid) { Err parazyd.org 70 i+ t.Fatal("Failed on first handshake.") Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ sig, err = SignMsgEd25519([]byte(secret), sk) Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ t.Fatal(err) Err parazyd.org 70 i+ } Err parazyd.org 70 i+ encodedSig = base64.StdEncoding.EncodeToString(sig) Err parazyd.org 70 i+ req = map[string]string{ Err parazyd.org 70 i+ "address": string(onionaddr), Err parazyd.org 70 i+ "pubkey": encodedPub, Err parazyd.org 70 i+ "message": secret, Err parazyd.org 70 i+ "signature": encodedSig, Err parazyd.org 70 i+ "secret": secret, Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ valid, _ = ValidateSecondHandshake(req) Err parazyd.org 70 i+ if !(valid) { Err parazyd.org 70 i+ t.Fatal("Failed to validate second handshake.") Err parazyd.org 70 i+ } Err parazyd.org 70 i+ cmd.Process.Kill() Err parazyd.org 70 i+} Err parazyd.org 70 i+ Err parazyd.org 70 i+func TestInValidValidateSecondHandshake(t *testing.T) { Err parazyd.org 70 i+ cmd, _ := StartRedis("../../contrib/redis.conf") Err parazyd.org 70 i+ Err parazyd.org 70 i+ pk, sk, _ := GenEd25519() Err parazyd.org 70 i+ onionaddr := OnionFromPubkeyEd25519(pk) Err parazyd.org 70 i+ Err parazyd.org 70 i+ sig, err := SignMsgEd25519([]byte("I am a DAM node!"), sk) Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ t.Fatal(err) Err parazyd.org 70 i+ } Err parazyd.org 70 i+ encodedSig := base64.StdEncoding.EncodeToString(sig) Err parazyd.org 70 i+ encodedPub := base64.StdEncoding.EncodeToString([]byte(pk)) Err parazyd.org 70 i+ Err parazyd.org 70 i+ req := map[string]string{ Err parazyd.org 70 i+ "address": string(onionaddr), Err parazyd.org 70 i+ "pubkey": encodedPub, Err parazyd.org 70 i+ "message": "I am a DAM node!", Err parazyd.org 70 i+ "signature": encodedSig, Err parazyd.org 70 i+ "secret": "", Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ valid, secret := ValidateFirstHandshake(req) Err parazyd.org 70 i+ if !(valid) { Err parazyd.org 70 i+ t.Fatal("Failed on first handshake.") Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ sig, err = SignMsgEd25519([]byte(secret), sk) Err parazyd.org 70 i+ if err != nil { Err parazyd.org 70 i+ t.Fatal(err) Err parazyd.org 70 i+ } Err parazyd.org 70 i+ encodedSig = base64.StdEncoding.EncodeToString(sig) Err parazyd.org 70 i+ Err parazyd.org 70 i+ secret = "We're malicious!" Err parazyd.org 70 i+ Err parazyd.org 70 i+ req = map[string]string{ Err parazyd.org 70 i+ "address": string(onionaddr), Err parazyd.org 70 i+ "pubkey": encodedPub, Err parazyd.org 70 i+ "message": secret, Err parazyd.org 70 i+ "signature": encodedSig, Err parazyd.org 70 i+ "secret": secret, Err parazyd.org 70 i+ } Err parazyd.org 70 i+ Err parazyd.org 70 i+ valid, _ = ValidateSecondHandshake(req) Err parazyd.org 70 i+ if !(valid) { Err parazyd.org 70 i+ t.Fatal("Failed to validate second handshake.") Err parazyd.org 70 i+ } Err parazyd.org 70 i+ cmd.Process.Kill() Err parazyd.org 70 i+} Err parazyd.org 70 1diff --git a/pkg/damlib/zenroom.go b/pkg/damlib/zenroom.go /git/tordam/file/pkg/damlib/zenroom.go.gph parazyd.org 70 it@@ -1,54 +0,0 @@ Err parazyd.org 70 i-package damlib Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2018 Dyne.org Foundation Err parazyd.org 70 i- * tor-dam is written and maintained by Ivan J. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This source code is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This software is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU General Public License Err parazyd.org 70 i- * along with this source code. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-// #cgo LDFLAGS: -lzenroomgo Err parazyd.org 70 i-// Err parazyd.org 70 i-// #include Err parazyd.org 70 i-// #include "zenroom.h" Err parazyd.org 70 i-import "C" Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "bytes" Err parazyd.org 70 i- "unsafe" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-// ZenroomExec is Zenroom's simple API call. Err parazyd.org 70 i-func ZenroomExec(script, conf, keys, data string, verbosity int) int { Err parazyd.org 70 i- return int(C.zenroom_exec(C.CString(script), C.CString(conf), Err parazyd.org 70 i- C.CString(keys), C.CString(data), C.int(verbosity))) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-// ZenroomExecToBuf is Zenroom's simple API call with buffers. It will return Err parazyd.org 70 i-// stdout and stderr. Err parazyd.org 70 i-func ZenroomExecToBuf(script, conf, keys, data string, verbosity int) (int, []byte, []byte) { Err parazyd.org 70 i- //var bufsize = 1024 * 8 Err parazyd.org 70 i- var bufsize = 1024 Err parazyd.org 70 i- Err parazyd.org 70 i- outbuf := make([]byte, bufsize) Err parazyd.org 70 i- errbuf := make([]byte, bufsize) Err parazyd.org 70 i- Err parazyd.org 70 i- return int(C.zenroom_exec_tobuf(C.CString(script), C.CString(conf), Err parazyd.org 70 i- C.CString(keys), C.CString(data), C.int(verbosity), Err parazyd.org 70 i- (*C.char)(unsafe.Pointer(&outbuf[0])), C.size_t(bufsize), Err parazyd.org 70 i- (*C.char)(unsafe.Pointer(&errbuf[0])), C.size_t(bufsize))), Err parazyd.org 70 i- bytes.Trim(outbuf, "\x00"), bytes.Trim(errbuf, "\x00") Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/pkg/damlib/zenroom.h b/pkg/damlib/zenroom.h /git/tordam/file/pkg/damlib/zenroom.h.gph parazyd.org 70 it@@ -1,103 +0,0 @@ Err parazyd.org 70 i-/* Zenroom (DECODE project) Err parazyd.org 70 i- * Err parazyd.org 70 i- * (c) Copyright 2017-2018 Dyne.org foundation Err parazyd.org 70 i- * designed, written and maintained by Denis Roio Err parazyd.org 70 i- * Err parazyd.org 70 i- * This source code is free software; you can redistribute it and/or Err parazyd.org 70 i- * modify it under the terms of the GNU Public License as published Err parazyd.org 70 i- * by the Free Software Foundation; either version 3 of the License, Err parazyd.org 70 i- * or (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This source code is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Err parazyd.org 70 i- * Please refer to the GNU Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU Public License along Err parazyd.org 70 i- * with this source code; if not, write to: Free Software Foundation, Err parazyd.org 70 i- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-#ifndef __ZENROOM_H__ Err parazyd.org 70 i-#define __ZENROOM_H__ Err parazyd.org 70 i- Err parazyd.org 70 i-///////////////////////////////////////// Err parazyd.org 70 i-// high level api: one simple call Err parazyd.org 70 i- Err parazyd.org 70 i-int zenroom_exec(char *script, char *conf, char *keys, Err parazyd.org 70 i- char *data, int verbosity); Err parazyd.org 70 i- Err parazyd.org 70 i-// in case buffers should be used instead of stdout/err file Err parazyd.org 70 i-// descriptors, this call defines where to print out the output and Err parazyd.org 70 i-// the maximum sizes allowed for it. Output is NULL terminated. Err parazyd.org 70 i-int zenroom_exec_tobuf(char *script, char *conf, char *keys, Err parazyd.org 70 i- char *data, int verbosity, Err parazyd.org 70 i- char *stdout_buf, size_t stdout_len, Err parazyd.org 70 i- char *stderr_buf, size_t stderr_len); Err parazyd.org 70 i- Err parazyd.org 70 i-// to obtain the Abstract Syntax Tree (AST) of a script Err parazyd.org 70 i-// (output is in metalua formatted as JSON) Err parazyd.org 70 i-int zenroom_parse_ast(char *script, int verbosity, Err parazyd.org 70 i- char *stdout_buf, size_t stdout_len, Err parazyd.org 70 i- char *stderr_buf, size_t stderr_len); Err parazyd.org 70 i- Err parazyd.org 70 i-void set_debug(int lev); Err parazyd.org 70 i- Err parazyd.org 70 i-//////////////////////////////////////// Err parazyd.org 70 i- Err parazyd.org 70 i- Err parazyd.org 70 i-// lower level api: init (exec_line*) teardown Err parazyd.org 70 i- Err parazyd.org 70 i-// heap initialised by the memory manager Err parazyd.org 70 i-typedef struct { Err parazyd.org 70 i- void* (*malloc)(size_t size); Err parazyd.org 70 i- void* (*realloc)(void *ptr, size_t size); Err parazyd.org 70 i- void (*free)(void *ptr); Err parazyd.org 70 i- void* (*sys_malloc)(size_t size); Err parazyd.org 70 i- void* (*sys_realloc)(void *ptr, size_t size); Err parazyd.org 70 i- void (*sys_free)(void *ptr); Err parazyd.org 70 i- char *heap; Err parazyd.org 70 i- size_t heap_size; Err parazyd.org 70 i-} zen_mem_t; Err parazyd.org 70 i- Err parazyd.org 70 i-// zenroom context, also available as "_Z" global in lua space Err parazyd.org 70 i-// contents are opaque in lua and available only as lightuserdata Err parazyd.org 70 i-typedef struct { Err parazyd.org 70 i- void *lua; // (lua_State*) Err parazyd.org 70 i- zen_mem_t *mem; // memory manager heap Err parazyd.org 70 i- Err parazyd.org 70 i- char *stdout_buf; Err parazyd.org 70 i- size_t stdout_len; Err parazyd.org 70 i- size_t stdout_pos; Err parazyd.org 70 i- char *stderr_buf; Err parazyd.org 70 i- size_t stderr_len; Err parazyd.org 70 i- size_t stderr_pos; Err parazyd.org 70 i- Err parazyd.org 70 i- int errorlevel; Err parazyd.org 70 i- void *userdata; // anything passed at init (reserved for caller) Err parazyd.org 70 i-} zenroom_t; Err parazyd.org 70 i- Err parazyd.org 70 i- Err parazyd.org 70 i-zenroom_t *zen_init(const char *conf, char *keys, char *data); Err parazyd.org 70 i-int zen_exec_script(zenroom_t *Z, const char *script); Err parazyd.org 70 i-void zen_teardown(zenroom_t *zenroom); Err parazyd.org 70 i- Err parazyd.org 70 i-#define UMM_HEAP (64*1024) // 64KiB (masked with 0x7fff) Err parazyd.org 70 i-#define MAX_FILE (64*1024) // load max 64KiB files Err parazyd.org 70 i-#ifndef MAX_STRING Err parazyd.org 70 i-#define MAX_STRING 4097 // max 4KiB strings Err parazyd.org 70 i-#endif Err parazyd.org 70 i-#define MAX_OCTET 2049 // max 2KiB octets Err parazyd.org 70 i- Err parazyd.org 70 i-#define LUA_BASELIBNAME "_G" Err parazyd.org 70 i- Err parazyd.org 70 i-#define ZEN_BITS 8 Err parazyd.org 70 i-#ifndef SIZE_MAX Err parazyd.org 70 i-#if ZEN_BITS == 32 Err parazyd.org 70 i-#define SIZE_MAX 4294967296 Err parazyd.org 70 i-#elif ZEN_BITS == 8 Err parazyd.org 70 i-#define SIZE_MAX 65536 Err parazyd.org 70 i-#endif Err parazyd.org 70 i-#endif Err parazyd.org 70 i- Err parazyd.org 70 i-#endif Err parazyd.org 70 1diff --git a/pkg/damlib/zenroom_test.go b/pkg/damlib/zenroom_test.go /git/tordam/file/pkg/damlib/zenroom_test.go.gph parazyd.org 70 it@@ -1,49 +0,0 @@ Err parazyd.org 70 i-package damlib Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2018 Dyne.org Foundation Err parazyd.org 70 i- * tor-dam is written and maintained by Ivan J. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This source code is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This software is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU General Public License Err parazyd.org 70 i- * along with this source code. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "testing" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-func TestZenroomExec(t *testing.T) { Err parazyd.org 70 i- ret := ZenroomExec(`print ("hello")`, "", "", "", 1) Err parazyd.org 70 i- if ret != 0 { Err parazyd.org 70 i- t.Fatal("ZenroomExec returned:", ret) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- t.Log("ZenroomExec returned:", ret) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func TestZenroomExecToBuf(t *testing.T) { Err parazyd.org 70 i- ret, stdout, _ := ZenroomExecToBuf(`print ("hello")`, "", "", "", 1) Err parazyd.org 70 i- if ret != 0 { Err parazyd.org 70 i- t.Fatal("ZenroomExec returned:", ret) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- if string(stdout) != "hello" { Err parazyd.org 70 i- t.Log("ZenroomExecToBuf stdout is not 'hello'") Err parazyd.org 70 i- t.Log("Stdout is rather", string(stdout)) Err parazyd.org 70 i- t.Fatal("ZenroomExecToBuf returned:", ret) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- t.Log("ZenroomExecToBuf returned:", ret) Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/protocol.md b/protocol.md /git/tordam/file/protocol.md.gph parazyd.org 70 it@@ -7,33 +7,32 @@ Abstract Err parazyd.org 70 i * Every node has a HTTP API allowing to list other nodes and announce Err parazyd.org 70 i new ones. Err parazyd.org 70 i * They keep propagating to all valid nodes they know. Err parazyd.org 70 i-* Announcing implies the need of knowledge of at least one or two nodes. Err parazyd.org 70 i+* Announcing implies the need of knowledge of at least one node. Err parazyd.org 70 i * It is possible to make this random enough once there are at least 6 Err parazyd.org 70 i nodes in the network. Err parazyd.org 70 i * A node announces itself to others by sending a JSON-formatted HTTP Err parazyd.org 70 i POST request to one or more active node. Err parazyd.org 70 i * Once the POST request is received, the node will validate the Err parazyd.org 70 i- request and return a secret encrypted with the requester's public Err parazyd.org 70 i- key. Err parazyd.org 70 i- * The requester will try to decrypt this secret, and return it plain Err parazyd.org 70 i- back to the node it's announcing to, along with a cryptographic Err parazyd.org 70 i- signature, so the node can confirm the requester is in actual Err parazyd.org 70 i- possession of the private key. Err parazyd.org 70 i+ request and return a random string (nonce) back to the requester for Err parazyd.org 70 i+ them to sign with their cryptographic key. Err parazyd.org 70 i+ * The requester will try to sign this nonce and return it back to the Err parazyd.org 70 i+ node it's announcing to, so the node can confirm the requester is in Err parazyd.org 70 i+ actual posession of the private key. Err parazyd.org 70 i * Tor DAM **does not validate** if a node is malicious or not. This is a Err parazyd.org 70 i- layer that has to be established on top. Tor DAM is just the entry Err parazyd.org 70 i- point into the network. Err parazyd.org 70 i+ layer that has to be established with external software. Err parazyd.org 70 i Err parazyd.org 70 i Err parazyd.org 70 i Protocol Err parazyd.org 70 i -------- Err parazyd.org 70 i Err parazyd.org 70 i A node announcing itself has to do a JSON-formatted HTTP POST request to Err parazyd.org 70 i-one or more active nodes with the format explained below. N.B. The Err parazyd.org 70 i+one or more active nodes with the format explained below. **N.B.** The Err parazyd.org 70 i strings shown in this document might not be valid, but they represent a Err parazyd.org 70 i correct example. Err parazyd.org 70 i Err parazyd.org 70 i-* `type` reflects the type of the node Err parazyd.org 70 i-* `address` holds the address of the Tor hidden service Err parazyd.org 70 i+* `address` holds the address of the Tor hidden service. Err parazyd.org 70 i+* `pubkey` is the base64 encoded ed25519 public key of the Tor hidden Err parazyd.org 70 i+ service. Err parazyd.org 70 i * `message` is the message that has to be signed using the private key Err parazyd.org 70 i of this same hidden service. Err parazyd.org 70 i * `signature` is the base64 encoded signature of the above message. Err parazyd.org 70 it@@ -43,58 +42,48 @@ correct example. Err parazyd.org 70 i Err parazyd.org 70 i ``` Err parazyd.org 70 i { Err parazyd.org 70 i- "type": "node", Err parazyd.org 70 i- "address": "22mobp7vrb7a4gt2.onion", Err parazyd.org 70 i- "message": "I am a DAM node!", Err parazyd.org 70 i- "signature": "BuB/Dv8E44CLzUX88K2Ab0lUNS9A0GSkHPtrFNNWZMihPMWN0ORhwMZBRnMJ8woPO3wSONBvEvaCXA2hvsVrUJTa+hnevQNyQXCRhdTVVuVXEpjyFzkMamxb6InrGqbsGGkEUqGMSr9aaQ85N02MMrM6T6JuyqSSssFg2xuO+P4=", Err parazyd.org 70 i+ "address": "gphjf5g3d5ywehwrd7cv3czymtdc6ha67bqplxwbspx7tioxt7gxqiid.onion", Err parazyd.org 70 i+ "pubkey": "M86S9NsfcWIe0R/FXYs4ZMYvHB74YPXewZPv+aHXn80=", Err parazyd.org 70 i+ "message" "I am a DAM node!", Err parazyd.org 70 i+ "signature": "CWqptO9ZRIvYMIHd3XHXaVny+W23P8FGkfbn5lvUqeJbDcY3G8+B4G8iCCIQiZkxkMofe6RbstHn3L1x88c3AA==", Err parazyd.org 70 i "secret": "" Err parazyd.org 70 i } Err parazyd.org 70 i ``` Err parazyd.org 70 i Err parazyd.org 70 i-Sending this as a POST request to a node will make it ask for the public Err parazyd.org 70 i-key of the given address from a HSDir in the Tor network. It will Err parazyd.org 70 i-retrieve the public key and try to validate the signature that was made. Err parazyd.org 70 i-Validating this, we assume that the requester is in possession of the Err parazyd.org 70 i-private key. Err parazyd.org 70 i- Err parazyd.org 70 i-Following up, the node shall generate a cryptographically secure random Err parazyd.org 70 i-string and encrypt it using the before acquired public key. It will then Err parazyd.org 70 i-be encoded using base64 and sent back to the client: Err parazyd.org 70 i+Sending this as a POST request to a node will make it verify the Err parazyd.org 70 i+signature, and following that, the node will generate a Err parazyd.org 70 i+cryptographically secure random string, encode it using base64 and Err parazyd.org 70 i+return it back to the client for them to sign: Err parazyd.org 70 i Err parazyd.org 70 i Err parazyd.org 70 i ``` Err parazyd.org 70 i { Err parazyd.org 70 i- "secret": "eP07xSZWlDdK4+AL0WUkIA3OnVTc3sEgu4MUqGr43TUXaJLfAILvWxKihPxytumBmdJ4LC45LsrdDuhmUSmZZMJxxiLmB4Gf3zoWa1DmStdc147VsGpexY05jaJUZlbmG0kkTFdPmdcKNbis5xfRn8Duo1e5bOPj41lIopwiil0=" Err parazyd.org 70 i+ "secret": "NmtDOEsrLGI8eCk1TyxOfXcwRV5lI0Y5fnhbXlAhV1dGfTl8K2JAYEQrU2lAJ2UuJ2kjQF15Q30+SWVXTkFnXw==" Err parazyd.org 70 i } Err parazyd.org 70 i ``` Err parazyd.org 70 i Err parazyd.org 70 i-The client will try to decode and decrypt this secret, and send it back Err parazyd.org 70 i-to the node to complete its part of the handshake. The POST request this Err parazyd.org 70 i-time will contain the following data: Err parazyd.org 70 i-* `type` reflects the type of the node Err parazyd.org 70 i-* `address` holds the address of the Tor hidden service Err parazyd.org 70 i-* `message` is the decrypted and base64 encoded secret that the server Err parazyd.org 70 i- had just sent us. Err parazyd.org 70 i-* `signature` is the base64 encoded signature of the above secret. Err parazyd.org 70 i-* `secret` is a copy of `message` here. Err parazyd.org 70 i+The client will try to decode and sign this secret. Then it will be Err parazyd.org 70 i+reencoded using base64 and sent back for verification to complete its Err parazyd.org 70 i+part of the handshake. The POST request this time will contain the Err parazyd.org 70 i+following data: Err parazyd.org 70 i Err parazyd.org 70 i Err parazyd.org 70 i ``` Err parazyd.org 70 i { Err parazyd.org 70 i- "type": "node", Err parazyd.org 70 i- "address": "22mobp7vrb7a4gt2.onion", Err parazyd.org 70 i- "message": "ZShhYHYsRGNLOTZ6YUwwP3ZXPnxhQiR9UFVWfmk5TG56TEtLb04vMms+OTIrLlQ7aS4rflR3V041RG5Je0tnYw==", Err parazyd.org 70 i- "signature": "L1N+VEi3T3aZaYksAy1+0UMoYn7B3Gapfk0dJzOUxUtUYVhj84TgfYeDnADNYrt5UK9hN/lCTIhsM6zPO7mSjQI43l3dKvMIikqQDwNey/XaokyPI4/oKrMoGQnu8E8UmHmI1pFvwdO5EQQaKbi90qWNj93KB/NlTwqD9Ir4blY=", Err parazyd.org 70 i- "secret": "ZShhYHYsRGNLOTZ6YUwwP3ZXPnxhQiR9UFVWfmk5TG56TEtLb04vMms+OTIrLlQ7aS4rflR3V041RG5Je0tnYw==" Err parazyd.org 70 i+ "address": "gphjf5g3d5ywehwrd7cv3czymtdc6ha67bqplxwbspx7tioxt7gxqiid.onion", Err parazyd.org 70 i+ "pubkey": "M86S9NsfcWIe0R/FXYs4ZMYvHB74YPXewZPv+aHXn80=", Err parazyd.org 70 i+ "message": "NFU5PXU4LT4xVy5NW303IWo1SD0odSohOHEvPThoemM3LHdcW3NVcm1TU3RAPGM8Pi1UUXpKIipWWnlTUk5kIg==", Err parazyd.org 70 i+ "signature": "1cocZey3KpuRDfRrKcI3tc4hhJpwfXU3BC3o3VE8wkkCpCFJ5Xl3wl58GLSVS4BdbDAFrf+KFpjtDLhOuSMYAw==", Err parazyd.org 70 i+ "secret": "NFU5PXU4LT4xVy5NW303IWo1SD0odSohOHEvPThoemM3LHdcW3NVcm1TU3RAPGM8Pi1UUXpKIipWWnlTUk5kIg==" Err parazyd.org 70 i } Err parazyd.org 70 i ``` Err parazyd.org 70 i Err parazyd.org 70 i-The node will verify the received plain secret against what it has Err parazyd.org 70 i-encrypted to validate. If the comparison yields no errors, we assume Err parazyd.org 70 i-that the requester is actually in possession of the private key. If the Err parazyd.org 70 i-node is not valid in our database, we will complete the handshake by Err parazyd.org 70 i-welcoming the client into the network: Err parazyd.org 70 i Err parazyd.org 70 i+The node will verify the received secret against the public key it has Err parazyd.org 70 i+archived already. If the verification yields no errors, we assume that Err parazyd.org 70 i+the requester is actually in possession of the private key. If the node Err parazyd.org 70 i+is not valid in our database, we will complete the handshake by Err parazyd.org 70 i+welcoming the client into the network: Err parazyd.org 70 i Err parazyd.org 70 i ``` Err parazyd.org 70 i { Err parazyd.org 70 it@@ -102,13 +91,14 @@ welcoming the client into the network: Err parazyd.org 70 i } Err parazyd.org 70 i ``` Err parazyd.org 70 i Err parazyd.org 70 i-Further on, the node will append useful metadata to the struct. We will Err parazyd.org 70 i+ Err parazyd.org 70 i+Further on, the node will append useful metadata to the struct. We will Err parazyd.org 70 i add the encoded public key, timestamps of when the client was first seen Err parazyd.org 70 i-and last seen, and a field to indicate if the node is valid. The latter Err parazyd.org 70 i-is not to be handled by Tor DAM, but rather the upper layer, which Err parazyd.org 70 i+and last seen, and a field to indicate if the node is valid. The latter Err parazyd.org 70 i+is not to be handled by Tor DAM, but rather an upper layer, which Err parazyd.org 70 i actually has consensus handling. Err parazyd.org 70 i Err parazyd.org 70 i-If the node is valid in another node's database, the remote node will Err parazyd.org 70 i-then propagate back all the valid nodes it knows (including itself) back Err parazyd.org 70 i+If a requesting/announcing node is valid in another node's database, the Err parazyd.org 70 i+remote node will then propagate back all the valid nodes it knows back Err parazyd.org 70 i to the client in a gzipped and base64 encoded JSON struct. The client Err parazyd.org 70 i-will then handle this and update its own database accordingly. Err parazyd.org 70 i+will then process this and update its own database accordingly. Err parazyd.org 70 1diff --git a/python/Makefile b/python/Makefile /git/tordam/file/python/Makefile.gph parazyd.org 70 it@@ -2,9 +2,7 @@ Err parazyd.org 70 i Err parazyd.org 70 i PREFIX ?= /usr/local Err parazyd.org 70 i Err parazyd.org 70 i-BIN =\ Err parazyd.org 70 i- damhs.py \ Err parazyd.org 70 i- damauth.py Err parazyd.org 70 i+BIN = damhs.py Err parazyd.org 70 i Err parazyd.org 70 i all: Err parazyd.org 70 i @echo 'Run "make install" to install to $(DESTDIR)$(PREFIX)/bin' Err parazyd.org 70 1diff --git a/python/damauth.py b/python/damauth.py /git/tordam/file/python/damauth.py.gph parazyd.org 70 it@@ -1,33 +0,0 @@ Err parazyd.org 70 i-#!/usr/bin/env python3 Err parazyd.org 70 i-# Copyright (c) 2017-2018 Dyne.org Foundation Err parazyd.org 70 i-# tor-dam is writen and maintained by Ivan J. Err parazyd.org 70 i-# Err parazyd.org 70 i-# This file is part of tor-dam Err parazyd.org 70 i-# Err parazyd.org 70 i-# This source code is free software: you can redistribute it and/or modify Err parazyd.org 70 i-# it under the terms of the GNU General Public License as published by Err parazyd.org 70 i-# the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i-# (at your option) any later version. Err parazyd.org 70 i-# Err parazyd.org 70 i-# This software is distributed in the hope that it will be useful, Err parazyd.org 70 i-# but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i-# GNU General Public License for more details. Err parazyd.org 70 i-# Err parazyd.org 70 i-# You should have received a copy of the GNU General Public License Err parazyd.org 70 i-# along with this source code. If not, see . Err parazyd.org 70 i- Err parazyd.org 70 i-""" Err parazyd.org 70 i-Retrieves and prints a hidden service's public key to stdout. Err parazyd.org 70 i- Err parazyd.org 70 i-Usage: damauth.py Err parazyd.org 70 i-""" Err parazyd.org 70 i- Err parazyd.org 70 i-from sys import argv, stdout Err parazyd.org 70 i-from stem.control import Controller Err parazyd.org 70 i- Err parazyd.org 70 i- Err parazyd.org 70 i-with Controller.from_port() as ctl: Err parazyd.org 70 i- ctl.authenticate(password='topkek') Err parazyd.org 70 i- stdout.write(ctl.get_hidden_service_descriptor(argv[1]).permanent_key) Err parazyd.org 70 i- stdout.flush() Err parazyd.org 70 1diff --git a/python/damhs.py b/python/damhs.py /git/tordam/file/python/damhs.py.gph parazyd.org 70 it@@ -54,11 +54,8 @@ def main(): Err parazyd.org 70 i portmap[int(tup[0])] = int(tup[1]) Err parazyd.org 70 i Err parazyd.org 70 i keyfile = argv[1] Err parazyd.org 70 i- ktype = 'RSA1024' # ED25519-V3 Err parazyd.org 70 i+ ktype = 'ED25519-V3' Err parazyd.org 70 i kcont = open(keyfile).read() Err parazyd.org 70 i- kcont = kcont.replace('\n', '') Err parazyd.org 70 i- kcont = kcont.replace('-----BEGIN RSA PRIVATE KEY-----', '') Err parazyd.org 70 i- kcont = kcont.replace('-----END RSA PRIVATE KEY-----', '') Err parazyd.org 70 i Err parazyd.org 70 i service = start_hs(ctl=ctl, ktype=ktype, kcont=kcont, portmap=portmap) Err parazyd.org 70 i Err parazyd.org 70 .