tor-dam

tor distributed announce mechanism (not a dht)
git clone https://git.parazyd.org/tor-dam
Log | Files | Refs | README | LICENSE

commit 6de85d612c0f0f7bca2642690771dbaf81415fb1
parent 2deec861ff5a514e499f9c0d3b05a5aa639bc1e0
Author: parazyd <parazyd@dyne.org>
Date:   Fri,  8 Dec 2017 02:28:26 +0100

Sort directory structure to something conventional

Diffstat:
Acmd/dam-client/main.go | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acmd/dam-dir/main.go | 176+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ddam/dam.go | 101-------------------------------------------------------------------------------
Dddir/ddir.go | 176-------------------------------------------------------------------------------
Rlib/crypto.go -> pkg/lib/crypto.go | 0
Rlib/helpers.go -> pkg/lib/helpers.go | 0
Rddir/dirauth.py -> python/dirauth.py | 0
7 files changed, 277 insertions(+), 277 deletions(-)

diff --git a/cmd/dam-client/main.go b/cmd/dam-client/main.go @@ -0,0 +1,101 @@ +package main + +// See LICENSE file for copyright and license details. + +import ( + "encoding/base64" + "encoding/json" + "log" + "os" + + "github.com/parazyd/tor-dam/pkg/lib" +) + +// Bits hold the size of our RSA private key. Tor standard is 1024. +const Bits = 1024 + +// Privpath holds the path of where our private key is. +const Privpath = "private.key" + +// Pubpath holds the path of where our public key is. +//const Pubpath = "public.key" + +// Postmsg holds the message we are signing with our private key. +const Postmsg = "I am a DECODE node!" + +type msgStruct struct { + Secret string +} + +func main() { + if _, err := os.Stat("private.key"); os.IsNotExist(err) { + key := lib.GenRsa(Bits) + lib.SavePriv(Privpath, key) + //lib.SavePub(Pubpath, key.PublicKey) + } + + key, err := lib.LoadKeyFromFile(Privpath) + lib.CheckError(err) + + sig := lib.SignMsg([]byte(Postmsg), key) + encodedSig := base64.StdEncoding.EncodeToString(sig) + + vals := map[string]string{ + "nodetype": "node", + "address": lib.OnionFromPubkey(key.PublicKey), + "message": Postmsg, + "signature": encodedSig, + "secret": "", + } + + log.Println("Announcing keypair for:", vals["address"]) + + jsonVal, err := json.Marshal(vals) + lib.CheckError(err) + + log.Println("Sending request") + resp := lib.HTTPPost("http://localhost:8080/announce", jsonVal) + + // TODO: Handle the secret decryption and returning it back decrypted to the + // directory. Note to self: start saving state on ddir's side. + + // Parse server's reply + var m msgStruct + decoder := json.NewDecoder(resp.Body) + err = decoder.Decode(&m) + lib.CheckError(err) + + if resp.StatusCode == 500 { + log.Println("Unsuccessful reply from directory.") + log.Fatalln("Server replied:", m.Secret) + } + + if resp.StatusCode == 200 { + log.Println("Successful reply from directory.") + decodedSecret, err := base64.StdEncoding.DecodeString(m.Secret) + lib.CheckError(err) + + decrypted, err := lib.DecryptMsg([]byte(decodedSecret), key) + lib.CheckError(err) + + decryptedEncode := base64.StdEncoding.EncodeToString(decrypted) + + vals["secret"] = decryptedEncode + jsonVal, err := json.Marshal(vals) + lib.CheckError(err) + + log.Println("Sending back decrypted secret.") + resp = lib.HTTPPost("http://localhost:8080/announce", jsonVal) + decoder = json.NewDecoder(resp.Body) + err = decoder.Decode(&m) + lib.CheckError(err) + + if resp.StatusCode == 200 { + log.Println("Successfully authenticated!") + log.Println("Server replied:", m.Secret) + } else { + log.Println("Unsuccessful reply from directory.") + log.Fatalln("Server replied:", m.Secret) + } + } +} diff --git a/cmd/dam-dir/main.go b/cmd/dam-dir/main.go @@ -0,0 +1,176 @@ +package main + +// See LICENSE file for copyright and license details. + +import ( + "encoding/base64" + "encoding/json" + "log" + "net/http" + "sync" + "time" + + "github.com/go-redis/redis" + "github.com/parazyd/tor-dam/pkg/lib" +) + +// ListenAddress controls where our HTTP API daemon is listening. +const ListenAddress = "127.0.0.1:8080" + +// RedisAddress points us to our Redis instance. +const RedisAddress = "127.0.0.1:6379" + +// RedisCli is our global Redis client +var RedisCli = redis.NewClient(&redis.Options{ + Addr: RedisAddress, + Password: "", + DB: 0, +}) + +type nodeStruct struct { + Nodetype string + Address string + Message string + Signature string + Secret string + Pubkey string + Firstseen int64 + Lastseen int64 + Valid int64 +} + +func handlePost(rw http.ResponseWriter, request *http.Request) { + decoder := json.NewDecoder(request.Body) + + var n nodeStruct + err := decoder.Decode(&n) + lib.CheckError(err) + + decSig, err := base64.StdEncoding.DecodeString(n.Signature) + lib.CheckError(err) + + req := map[string]string{ + "nodetype": n.Nodetype, + "address": n.Address, + "message": n.Message, + "signature": string(decSig), + "secret": n.Secret, + } + + pkey, valid := lib.ValidateReq(req) + if !(valid) && pkey == nil { + log.Fatalln("Request is not valid.") + } else if !(valid) && pkey != nil { + // We couldn't get a descriptor. + ret := map[string]string{ + "secret": string(pkey), + } + jsonVal, err := json.Marshal(ret) + lib.CheckError(err) + rw.Header().Set("Content-Type", "application/json") + rw.WriteHeader(500) + rw.Write(jsonVal) + return + } + + pubkey, err := lib.ParsePubkey(pkey) + lib.CheckError(err) + + n.Pubkey = string(pkey) + now := time.Now() + n.Firstseen = now.Unix() + n.Lastseen = now.Unix() + + if len(req["secret"]) != 88 { + // Client did not send a decrypted secret. + randString, err := lib.GenRandomASCII(64) + lib.CheckError(err) + + // FIXME: delete this line after debug mode + log.Println("Secret:", randString) + + secret, err := lib.EncryptMsg([]byte(randString), pubkey) + lib.CheckError(err) + + encodedSecret := base64.StdEncoding.EncodeToString(secret) + ret := map[string]string{ + "secret": encodedSecret, + } + jsonVal, err := json.Marshal(ret) + lib.CheckError(err) + + // TODO: We probably _do_ want to allow the keyholder to + // reannounce itself, so let's not handle this yet. + //ex := RedisCli.Exists(n.Address) + + // Save the node into redis + info := map[string]interface{}{ + "nodetype": n.Nodetype, + "address": n.Address, + "message": n.Message, + "signature": n.Signature, + "secret": base64.StdEncoding.EncodeToString([]byte(randString)), + "pubkey": n.Pubkey, + "firstseen": n.Firstseen, + "lastseen": n.Lastseen, + "valid": 0, // This should be 1 after the node is not considered malicious + } + log.Println("Writing into Redis") + redRet, err := RedisCli.HMSet(n.Address, info).Result() + lib.CheckError(err) + + if redRet == "OK" { + log.Println("Returning encrypted secret to caller.") + rw.Header().Set("Content-Type", "application/json") + rw.WriteHeader(http.StatusOK) + rw.Write(jsonVal) + return + } + } + + if len(req["secret"]) == 88 { + // Client sent a decrypted secret. + //decodedSec, err := base64.StdEncoding.DecodeString(req["secret"]) + //lib.CheckError(err) + + var correct = false + localSec, err := RedisCli.HGet(n.Address, "secret").Result() + lib.CheckError(err) + + if localSec == req["secret"] { + log.Println("Secrets match!") + correct = true + } + + if correct { + log.Printf("Welcoming %s to the network\n", n.Address) + ret := map[string]string{ + "secret": "Welcome to the DECODE network!", + } + n.Valid = 0 + + jsonVal, err := json.Marshal(ret) + lib.CheckError(err) + + rw.Header().Set("Content-Type", "application/json") + rw.WriteHeader(http.StatusOK) + rw.Write(jsonVal) + return + } + } +} + +func main() { + var wg sync.WaitGroup + + _, err := RedisCli.Ping().Result() + lib.CheckError(err) + + http.HandleFunc("/announce", handlePost) + + wg.Add(1) + go http.ListenAndServe(ListenAddress, nil) + log.Println("Listening on", ListenAddress) + + wg.Wait() +} diff --git a/dam/dam.go b/dam/dam.go @@ -1,101 +0,0 @@ -package main - -// See LICENSE file for copyright and license details. - -import ( - "encoding/base64" - "encoding/json" - "log" - "os" - - "github.com/parazyd/tor-dam/lib" -) - -// Bits hold the size of our RSA private key. Tor standard is 1024. -const Bits = 1024 - -// Privpath holds the path of where our private key is. -const Privpath = "private.key" - -// Pubpath holds the path of where our public key is. -//const Pubpath = "public.key" - -// Postmsg holds the message we are signing with our private key. -const Postmsg = "I am a DECODE node!" - -type msgStruct struct { - Secret string -} - -func main() { - if _, err := os.Stat("private.key"); os.IsNotExist(err) { - key := lib.GenRsa(Bits) - lib.SavePriv(Privpath, key) - //lib.SavePub(Pubpath, key.PublicKey) - } - - key, err := lib.LoadKeyFromFile(Privpath) - lib.CheckError(err) - - sig := lib.SignMsg([]byte(Postmsg), key) - encodedSig := base64.StdEncoding.EncodeToString(sig) - - vals := map[string]string{ - "nodetype": "node", - "address": lib.OnionFromPubkey(key.PublicKey), - "message": Postmsg, - "signature": encodedSig, - "secret": "", - } - - log.Println("Announcing keypair for:", vals["address"]) - - jsonVal, err := json.Marshal(vals) - lib.CheckError(err) - - log.Println("Sending request") - resp := lib.HTTPPost("http://localhost:8080/announce", jsonVal) - - // TODO: Handle the secret decryption and returning it back decrypted to the - // directory. Note to self: start saving state on ddir's side. - - // Parse server's reply - var m msgStruct - decoder := json.NewDecoder(resp.Body) - err = decoder.Decode(&m) - lib.CheckError(err) - - if resp.StatusCode == 500 { - log.Println("Unsuccessful reply from directory.") - log.Fatalln("Server replied:", m.Secret) - } - - if resp.StatusCode == 200 { - log.Println("Successful reply from directory.") - decodedSecret, err := base64.StdEncoding.DecodeString(m.Secret) - lib.CheckError(err) - - decrypted, err := lib.DecryptMsg([]byte(decodedSecret), key) - lib.CheckError(err) - - decryptedEncode := base64.StdEncoding.EncodeToString(decrypted) - - vals["secret"] = decryptedEncode - jsonVal, err := json.Marshal(vals) - lib.CheckError(err) - - log.Println("Sending back decrypted secret.") - resp = lib.HTTPPost("http://localhost:8080/announce", jsonVal) - decoder = json.NewDecoder(resp.Body) - err = decoder.Decode(&m) - lib.CheckError(err) - - if resp.StatusCode == 200 { - log.Println("Successfully authenticated!") - log.Println("Server replied:", m.Secret) - } else { - log.Println("Unsuccessful reply from directory.") - log.Fatalln("Server replied:", m.Secret) - } - } -} diff --git a/ddir/ddir.go b/ddir/ddir.go @@ -1,176 +0,0 @@ -package main - -// See LICENSE file for copyright and license details. - -import ( - "encoding/base64" - "encoding/json" - "log" - "net/http" - "sync" - "time" - - "github.com/go-redis/redis" - "github.com/parazyd/tor-dam/lib" -) - -// ListenAddress controls where our HTTP API daemon is listening. -const ListenAddress = "127.0.0.1:8080" - -// RedisAddress points us to our Redis instance. -const RedisAddress = "127.0.0.1:6379" - -// RedisCli is our global Redis client -var RedisCli = redis.NewClient(&redis.Options{ - Addr: RedisAddress, - Password: "", - DB: 0, -}) - -type nodeStruct struct { - Nodetype string - Address string - Message string - Signature string - Secret string - Pubkey string - Firstseen int64 - Lastseen int64 - Valid int64 -} - -func handlePost(rw http.ResponseWriter, request *http.Request) { - decoder := json.NewDecoder(request.Body) - - var n nodeStruct - err := decoder.Decode(&n) - lib.CheckError(err) - - decSig, err := base64.StdEncoding.DecodeString(n.Signature) - lib.CheckError(err) - - req := map[string]string{ - "nodetype": n.Nodetype, - "address": n.Address, - "message": n.Message, - "signature": string(decSig), - "secret": n.Secret, - } - - pkey, valid := lib.ValidateReq(req) - if !(valid) && pkey == nil { - log.Fatalln("Request is not valid.") - } else if !(valid) && pkey != nil { - // We couldn't get a descriptor. - ret := map[string]string{ - "secret": string(pkey), - } - jsonVal, err := json.Marshal(ret) - lib.CheckError(err) - rw.Header().Set("Content-Type", "application/json") - rw.WriteHeader(500) - rw.Write(jsonVal) - return - } - - pubkey, err := lib.ParsePubkey(pkey) - lib.CheckError(err) - - n.Pubkey = string(pkey) - now := time.Now() - n.Firstseen = now.Unix() - n.Lastseen = now.Unix() - - if len(req["secret"]) != 88 { - // Client did not send a decrypted secret. - randString, err := lib.GenRandomASCII(64) - lib.CheckError(err) - - // FIXME: delete this line after debug mode - log.Println("Secret:", randString) - - secret, err := lib.EncryptMsg([]byte(randString), pubkey) - lib.CheckError(err) - - encodedSecret := base64.StdEncoding.EncodeToString(secret) - ret := map[string]string{ - "secret": encodedSecret, - } - jsonVal, err := json.Marshal(ret) - lib.CheckError(err) - - // TODO: We probably _do_ want to allow the keyholder to - // reannounce itself, so let's not handle this yet. - //ex := RedisCli.Exists(n.Address) - - // Save the node into redis - info := map[string]interface{}{ - "nodetype": n.Nodetype, - "address": n.Address, - "message": n.Message, - "signature": n.Signature, - "secret": base64.StdEncoding.EncodeToString([]byte(randString)), - "pubkey": n.Pubkey, - "firstseen": n.Firstseen, - "lastseen": n.Lastseen, - "valid": 0, // This should be 1 after the node is not considered malicious - } - log.Println("Writing into Redis") - redRet, err := RedisCli.HMSet(n.Address, info).Result() - lib.CheckError(err) - - if redRet == "OK" { - log.Println("Returning encrypted secret to caller.") - rw.Header().Set("Content-Type", "application/json") - rw.WriteHeader(http.StatusOK) - rw.Write(jsonVal) - return - } - } - - if len(req["secret"]) == 88 { - // Client sent a decrypted secret. - //decodedSec, err := base64.StdEncoding.DecodeString(req["secret"]) - //lib.CheckError(err) - - var correct = false - localSec, err := RedisCli.HGet(n.Address, "secret").Result() - lib.CheckError(err) - - if localSec == req["secret"] { - log.Println("Secrets match!") - correct = true - } - - if correct { - log.Printf("Welcoming %s to the network\n", n.Address) - ret := map[string]string{ - "secret": "Welcome to the DECODE network!", - } - n.Valid = 0 - - jsonVal, err := json.Marshal(ret) - lib.CheckError(err) - - rw.Header().Set("Content-Type", "application/json") - rw.WriteHeader(http.StatusOK) - rw.Write(jsonVal) - return - } - } -} - -func main() { - var wg sync.WaitGroup - - _, err := RedisCli.Ping().Result() - lib.CheckError(err) - - http.HandleFunc("/announce", handlePost) - - wg.Add(1) - go http.ListenAndServe(ListenAddress, nil) - log.Println("Listening on", ListenAddress) - - wg.Wait() -} diff --git a/lib/crypto.go b/pkg/lib/crypto.go diff --git a/lib/helpers.go b/pkg/lib/helpers.go diff --git a/ddir/dirauth.py b/python/dirauth.py