diff --git a/.gitignore b/.gitignore index 2b29f27..70532f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ tests +peer/blockchain.data diff --git a/README.md b/README.md index ea2773f..18c30ea 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ There are different types of nodes: - serverCA - Is a REST server that has been certified (is the Certified Authority) to validate the peers that will be able to participate of the blockchain. - Have the webapp (frontend) to validate peers through a GUI interface + - The GUI frontend webapp allows also to view the current peers of the network and the blocks of the blockchain - server-ID-signer - The server where the user creates a non anonymous account - Also is the server that blind signs the Anonymous ID of the users diff --git a/peer/.gitignore b/peer/.gitignore deleted file mode 100644 index 629cafa..0000000 --- a/peer/.gitignore +++ /dev/null @@ -1 +0,0 @@ -blockchain.data diff --git a/peer/blockchain.data b/peer/blockchain.data index 59a2bea..935e448 100644 --- a/peer/blockchain.data +++ b/peer/blockchain.data @@ -1 +1 @@ -{"genesisblock":"YKWAWY6GM5xrLhYrfi6hAmPmsECUH83n7xVcgaguLF4=","lastupdate":"0001-01-01T00:00:00Z","blocks":[{"hash":"YKWAWY6GM5xrLhYrfi6hAmPmsECUH83n7xVcgaguLF4=","height":0,"date":"2017-11-29T10:42:55.112675187+01:00","previoushash":"","nexthash":"cSN48a9BwgJQZdz2NwBRPJqCtC4Qtv-l-RYeGl9eBZs=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"cSN48a9BwgJQZdz2NwBRPJqCtC4Qtv-l-RYeGl9eBZs=","height":1,"date":"2017-11-29T23:07:43.169204719+01:00","previoushash":"YKWAWY6GM5xrLhYrfi6hAmPmsECUH83n7xVcgaguLF4=","nexthash":"Ql0MH8WVaCOXzRWmR5xUyAQXaQ5Ovt6PoN3HrkHmYmk=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"Ql0MH8WVaCOXzRWmR5xUyAQXaQ5Ovt6PoN3HrkHmYmk=","height":2,"date":"2017-12-26T14:38:41.446523607+01:00","previoushash":"cSN48a9BwgJQZdz2NwBRPJqCtC4Qtv-l-RYeGl9eBZs=","nexthash":"64bzp4j5jJjCcvKYcsytJOKD5dFyMHUjtNY1S5TD8Sk=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"64bzp4j5jJjCcvKYcsytJOKD5dFyMHUjtNY1S5TD8Sk=","height":3,"date":"2017-12-26T18:05:05.541862456+01:00","previoushash":"Ql0MH8WVaCOXzRWmR5xUyAQXaQ5Ovt6PoN3HrkHmYmk=","nexthash":"N-w5F0pRA0kpZx7JDS3RPBedUSq1Kyk13Pc1guhY7Ws=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"N-w5F0pRA0kpZx7JDS3RPBedUSq1Kyk13Pc1guhY7Ws=","height":4,"date":"2017-12-26T18:06:13.953399725+01:00","previoushash":"64bzp4j5jJjCcvKYcsytJOKD5dFyMHUjtNY1S5TD8Sk=","nexthash":"45Otq5P8WR97T4SxvaFk_0icNdUcIzO-mTjn6wrxJd4=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"45Otq5P8WR97T4SxvaFk_0icNdUcIzO-mTjn6wrxJd4=","height":5,"date":"2017-12-26T18:06:57.93092362+01:00","previoushash":"N-w5F0pRA0kpZx7JDS3RPBedUSq1Kyk13Pc1guhY7Ws=","nexthash":"","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="}]} \ No newline at end of file +{"genesisblock":"YKWAWY6GM5xrLhYrfi6hAmPmsECUH83n7xVcgaguLF4=","lastupdate":"0001-01-01T00:00:00Z","blocks":[{"hash":"YKWAWY6GM5xrLhYrfi6hAmPmsECUH83n7xVcgaguLF4=","height":0,"date":"2017-11-29T10:42:55.112675187+01:00","previoushash":"","nexthash":"cSN48a9BwgJQZdz2NwBRPJqCtC4Qtv-l-RYeGl9eBZs=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"cSN48a9BwgJQZdz2NwBRPJqCtC4Qtv-l-RYeGl9eBZs=","height":1,"date":"2017-11-29T23:07:43.169204719+01:00","previoushash":"YKWAWY6GM5xrLhYrfi6hAmPmsECUH83n7xVcgaguLF4=","nexthash":"Ql0MH8WVaCOXzRWmR5xUyAQXaQ5Ovt6PoN3HrkHmYmk=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"Ql0MH8WVaCOXzRWmR5xUyAQXaQ5Ovt6PoN3HrkHmYmk=","height":2,"date":"2017-12-26T14:38:41.446523607+01:00","previoushash":"cSN48a9BwgJQZdz2NwBRPJqCtC4Qtv-l-RYeGl9eBZs=","nexthash":"64bzp4j5jJjCcvKYcsytJOKD5dFyMHUjtNY1S5TD8Sk=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"64bzp4j5jJjCcvKYcsytJOKD5dFyMHUjtNY1S5TD8Sk=","height":3,"date":"2017-12-26T18:05:05.541862456+01:00","previoushash":"Ql0MH8WVaCOXzRWmR5xUyAQXaQ5Ovt6PoN3HrkHmYmk=","nexthash":"N-w5F0pRA0kpZx7JDS3RPBedUSq1Kyk13Pc1guhY7Ws=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"N-w5F0pRA0kpZx7JDS3RPBedUSq1Kyk13Pc1guhY7Ws=","height":4,"date":"2017-12-26T18:06:13.953399725+01:00","previoushash":"64bzp4j5jJjCcvKYcsytJOKD5dFyMHUjtNY1S5TD8Sk=","nexthash":"45Otq5P8WR97T4SxvaFk_0icNdUcIzO-mTjn6wrxJd4=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"45Otq5P8WR97T4SxvaFk_0icNdUcIzO-mTjn6wrxJd4=","height":5,"date":"2017-12-26T18:06:57.93092362+01:00","previoushash":"N-w5F0pRA0kpZx7JDS3RPBedUSq1Kyk13Pc1guhY7Ws=","nexthash":"xnXIWKAsIHTOwzWDJe-5daa_5bOSPTLbsG5Ft49g3XA=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"xnXIWKAsIHTOwzWDJe-5daa_5bOSPTLbsG5Ft49g3XA=","height":6,"date":"2017-12-26T20:11:10.182353841+01:00","previoushash":"45Otq5P8WR97T4SxvaFk_0icNdUcIzO-mTjn6wrxJd4=","nexthash":"U-Yz_cpPe6Cm4U9zMunLWH2s5hvUFLHJn7_u_3680Cs=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"U-Yz_cpPe6Cm4U9zMunLWH2s5hvUFLHJn7_u_3680Cs=","height":7,"date":"2017-12-26T21:08:30.923107227+01:00","previoushash":"xnXIWKAsIHTOwzWDJe-5daa_5bOSPTLbsG5Ft49g3XA=","nexthash":"zlsDiXG2raTI2tear0LtIQV72BtHTXLzQGV623_CUDc=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"zlsDiXG2raTI2tear0LtIQV72BtHTXLzQGV623_CUDc=","height":8,"date":"2017-12-26T21:08:45.373348196+01:00","previoushash":"U-Yz_cpPe6Cm4U9zMunLWH2s5hvUFLHJn7_u_3680Cs=","nexthash":"MordV-LXcl8AfW5gVq1wHxLHr3EZn7KhWcRJDEamVbA=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"MordV-LXcl8AfW5gVq1wHxLHr3EZn7KhWcRJDEamVbA=","height":9,"date":"2017-12-26T21:08:59.694290728+01:00","previoushash":"zlsDiXG2raTI2tear0LtIQV72BtHTXLzQGV623_CUDc=","nexthash":"gRhKt8ZRKbDFLr-rSEnipo3QI3loQwTjkNoK0G96Z-w=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"gRhKt8ZRKbDFLr-rSEnipo3QI3loQwTjkNoK0G96Z-w=","height":10,"date":"2017-12-26T21:12:18.832944058+01:00","previoushash":"MordV-LXcl8AfW5gVq1wHxLHr3EZn7KhWcRJDEamVbA=","nexthash":"NQMu54PaN9Ph9Qh2VJb9q6hHbENPYfS62YVkjTs0F1k=","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="},{"hash":"NQMu54PaN9Ph9Qh2VJb9q6hHbENPYfS62YVkjTs0F1k=","height":11,"date":"2017-12-26T21:12:40.460894962+01:00","previoushash":"gRhKt8ZRKbDFLr-rSEnipo3QI3loQwTjkNoK0G96Z-w=","nexthash":"","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="}]} \ No newline at end of file diff --git a/runTmuxTestPeers.sh b/runTmuxTestPeers.sh index bdee0d0..a345037 100644 --- a/runTmuxTestPeers.sh +++ b/runTmuxTestPeers.sh @@ -5,6 +5,7 @@ tmux split-window -d -t 0 -v tmux split-window -d -t 0 -h tmux split-window -d -t 0 -v tmux split-window -d -t 2 -v +tmux split-window -d -t 4 -h tmux send-keys -t 0 'cd peer && go run *.go server 3001 3002' enter sleep 2 @@ -14,5 +15,6 @@ tmux send-keys -t 1 'cd peer && go run *.go client 3003 3004' enter tmux send-keys -t 2 'cd peer && go run *.go client 3005 3006' enter tmux send-keys -t 3 'cd peer && go run *.go client 3007 3008' enter tmux send-keys -t 4 'cd serverCA && go run *.go' enter +tmux send-keys -t 5 'cd serverIDsigner && go run *.go' enter tmux attach diff --git a/serverCA/config.json b/serverCA/config.json index c46ba7c..740f974 100755 --- a/serverCA/config.json +++ b/serverCA/config.json @@ -4,9 +4,5 @@ "serverip": "127.0.0.1", "serverport": "3000", "serverrestport": "3002", - "webserverport": "3080", - "mongodb": { - "ip": "127.0.0.1:27017", - "database": "serverCA" - } + "webserverport": "3080" } diff --git a/serverCA/main.go b/serverCA/main.go index 937e7df..cbb4a57 100644 --- a/serverCA/main.go +++ b/serverCA/main.go @@ -6,8 +6,6 @@ import ( "net/http" "time" - mgo "gopkg.in/mgo.v2" - "github.com/fatih/color" "github.com/gorilla/handlers" ) @@ -28,8 +26,6 @@ type PeersList struct { var peersList PeersList -var userCollection *mgo.Collection - func main() { color.Blue("Starting CA") @@ -37,13 +33,6 @@ func main() { readConfig("config.json") reconstructBlockchainFromBlock("http://"+config.IP+":"+config.ServerRESTPort, "") - initializeToken() - - //mongodb - session, err := getSession() - check(err) - userCollection = getCollection(session, "users") - //run thw webserver go webserver() diff --git a/serverCA/readConfig.go b/serverCA/readConfig.go index 399d711..8856597 100755 --- a/serverCA/readConfig.go +++ b/serverCA/readConfig.go @@ -7,17 +7,12 @@ import ( //Config reads the config type Config struct { - IP string `json:"ip"` - Port string `json:"port"` - ServerIP string `json:"serverip"` - ServerPort string `json:"serverport"` - ServerRESTPort string `json:"serverrestport"` - WebServerPort string `json:"webserverport"` - Mongodb MongoConfig `json:"mongodb"` -} -type MongoConfig struct { - IP string `json:"ip"` - Database string `json:"database"` + IP string `json:"ip"` + Port string `json:"port"` + ServerIP string `json:"serverip"` + ServerPort string `json:"serverport"` + ServerRESTPort string `json:"serverrestport"` + WebServerPort string `json:"webserverport"` } var config Config diff --git a/serverCA/restRoutes.go b/serverCA/restRoutes.go index c892019..be8d0bf 100755 --- a/serverCA/restRoutes.go +++ b/serverCA/restRoutes.go @@ -21,35 +21,4 @@ var routes = Routes{ "/blockchain", GetBlockchain, }, - /* - POST /signup - POST /loginuser - POST /blindsign - POST /verifysign - - */ - Route{ - "Signup", - "POST", - "/signup", - Signup, - }, - Route{ - "Login", - "POST", - "/login", - Login, - }, - Route{ - "BlindSign", - "POST", - "/blindsign", - BlindSign, - }, - Route{ - "VerifySign", - "POST", - "/verifysign", - VerifySign, - }, } diff --git a/serverCA/testUser.sh b/serverCA/testUser.sh deleted file mode 100644 index 33cb99e..0000000 --- a/serverCA/testUser.sh +++ /dev/null @@ -1,3 +0,0 @@ -curl -X POST http://127.0.0.1:3030/signup -d '{"email": "user1@e.com", "password": "user1"}' - -curl -X POST http://127.0.0.1:3030/login -d '{"email": "user1@e.com", "password": "user1"}' diff --git a/serverIDsigner/README.md b/serverIDsigner/README.md new file mode 100644 index 0000000..3fc8892 --- /dev/null +++ b/serverIDsigner/README.md @@ -0,0 +1,5 @@ +# serverIDsign + +- The server where the user creates a non anonymous account +- Also is the server that blind signs the Anonymous ID of the users +- Have the webapp (frontend) to interact through a GUI interface diff --git a/serverIDsigner/config.json b/serverIDsigner/config.json new file mode 100755 index 0000000..331503e --- /dev/null +++ b/serverIDsigner/config.json @@ -0,0 +1,9 @@ +{ + "ip": "127.0.0.1", + "port": "3130", + "webserverport": "3180", + "mongodb": { + "ip": "127.0.0.1:27017", + "database": "serverIDsigner" + } +} diff --git a/serverIDsigner/errors.go b/serverIDsigner/errors.go new file mode 100755 index 0000000..b3cf6b2 --- /dev/null +++ b/serverIDsigner/errors.go @@ -0,0 +1,15 @@ +package main + +import ( + "log" + "runtime" +) + +func check(err error) { + if err != nil { + _, fn, line, _ := runtime.Caller(1) + log.Println(line) + log.Println(fn) + log.Println(err) + } +} diff --git a/serverIDsigner/log.go b/serverIDsigner/log.go new file mode 100755 index 0000000..e8f391a --- /dev/null +++ b/serverIDsigner/log.go @@ -0,0 +1,24 @@ +package main + +import ( + "io" + "log" + "os" + "strings" + "time" +) + +func savelog() { + timeS := time.Now().String() + _ = os.Mkdir("logs", os.ModePerm) + //next 3 lines are to avoid windows filesystem errors + timeS = strings.Replace(timeS, " ", "_", -1) + timeS = strings.Replace(timeS, ".", "-", -1) + timeS = strings.Replace(timeS, ":", "-", -1) + logFile, err := os.OpenFile("logs/log-"+timeS+".log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) + if err != nil { + panic(err) + } + mw := io.MultiWriter(os.Stdout, logFile) + log.SetOutput(mw) +} diff --git a/serverIDsigner/main.go b/serverIDsigner/main.go new file mode 100644 index 0000000..7af700f --- /dev/null +++ b/serverIDsigner/main.go @@ -0,0 +1,58 @@ +package main + +import ( + "fmt" + "log" + "net/http" + + mgo "gopkg.in/mgo.v2" + + "github.com/fatih/color" + "github.com/gorilla/handlers" + + ownrsa "./ownrsa" +) + +var userCollection *mgo.Collection + +var serverRsa ownrsa.RSA + +func main() { + color.Blue("Starting serverIDsigner") + + //read configuration file + readConfig("config.json") + + initializeToken() + + //initialize RSA + serverRsa = ownrsa.GenerateKeyPair() + color.Blue("Public Key:") + fmt.Println(serverRsa.PubK) + color.Green("Private Key:") + fmt.Println(serverRsa.PrivK) + + //mongodb + session, err := getSession() + check(err) + userCollection = getCollection(session, "users") + + //run thw webserver + go webserver() + + //run API + log.Println("api server running") + log.Print("port: ") + log.Println(config.Port) + router := NewRouter() + headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Access-Control-Allow-Origin"}) + originsOk := handlers.AllowedOrigins([]string{"*"}) + methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"}) + log.Fatal(http.ListenAndServe(":"+config.Port, handlers.CORS(originsOk, headersOk, methodsOk)(router))) +} + +func webserver() { + log.Println("webserver in port " + config.WebServerPort) + http.Handle("/", http.FileServer(http.Dir("./webapp"))) + http.ListenAndServe(":"+config.WebServerPort, nil) +} diff --git a/serverCA/mongoOperations.go b/serverIDsigner/mongoOperations.go similarity index 100% rename from serverCA/mongoOperations.go rename to serverIDsigner/mongoOperations.go diff --git a/serverIDsigner/ownrsa/prime.go b/serverIDsigner/ownrsa/prime.go new file mode 100644 index 0000000..e5d214b --- /dev/null +++ b/serverIDsigner/ownrsa/prime.go @@ -0,0 +1,54 @@ +package ownrsa + +import "math/rand" + +func randInt(min int, max int) int { + r := rand.Intn(max-min) + min + return r +} +func randPrime(min int, max int) int { + primes := sieveOfEratosthenes(max) + + randN := rand.Intn(len(primes)-0) + 0 + + return primes[randN] + +} + +// return list of primes less than N +func sieveOfEratosthenes(N int) (primes []int) { + b := make([]bool, N) + for i := 2; i < N; i++ { + if b[i] == true { + continue + } + primes = append(primes, i) + for k := i * i; k < N; k += i { + b[k] = true + } + } + return +} + +func gcd(a, b int) int { + var bgcd func(a, b, res int) int + + bgcd = func(a, b, res int) int { + switch { + case a == b: + return res * a + case a%2 == 0 && b%2 == 0: + return bgcd(a/2, b/2, 2*res) + case a%2 == 0: + return bgcd(a/2, b, res) + case b%2 == 0: + return bgcd(a, b/2, res) + case a > b: + return bgcd(a-b, b, res) + default: + return bgcd(a, b-a, res) + } + } + + return bgcd(a, b, 1) +} diff --git a/serverIDsigner/ownrsa/rsa.go b/serverIDsigner/ownrsa/rsa.go new file mode 100644 index 0000000..a1e5127 --- /dev/null +++ b/serverIDsigner/ownrsa/rsa.go @@ -0,0 +1,183 @@ +package ownrsa + +import ( + "errors" + "fmt" + "math/big" + "math/rand" + "time" +) + +type RSAPublicKey struct { + E *big.Int `json:"e"` + N *big.Int `json:"n"` +} +type RSAPublicKeyString struct { + E string `json:"e"` + N string `json:"n"` +} +type RSAPrivateKey struct { + D *big.Int `json:"d"` + N *big.Int `json:"n"` +} + +type RSA struct { + PubK RSAPublicKey + PrivK RSAPrivateKey +} + +const maxPrime = 500 +const minPrime = 100 + +func GenerateKeyPair() RSA { + + rand.Seed(time.Now().Unix()) + p := randPrime(minPrime, maxPrime) + q := randPrime(minPrime, maxPrime) + fmt.Print("p:") + fmt.Println(p) + fmt.Print("q:") + fmt.Println(q) + + n := p * q + phi := (p - 1) * (q - 1) + e := 65537 + var pubK RSAPublicKey + pubK.E = big.NewInt(int64(e)) + pubK.N = big.NewInt(int64(n)) + + d := new(big.Int).ModInverse(big.NewInt(int64(e)), big.NewInt(int64(phi))) + + var privK RSAPrivateKey + privK.D = d + privK.N = big.NewInt(int64(n)) + + var rsa RSA + rsa.PubK = pubK + rsa.PrivK = privK + return rsa +} +func Encrypt(m string, pubK RSAPublicKey) []int { + var c []int + mBytes := []byte(m) + for _, byte := range mBytes { + c = append(c, EncryptInt(int(byte), pubK)) + } + return c +} +func Decrypt(c []int, privK RSAPrivateKey) string { + var m string + var mBytes []byte + for _, indC := range c { + mBytes = append(mBytes, byte(DecryptInt(indC, privK))) + } + m = string(mBytes) + return m +} + +func EncryptBigInt(bigint *big.Int, pubK RSAPublicKey) *big.Int { + Me := new(big.Int).Exp(bigint, pubK.E, nil) + c := new(big.Int).Mod(Me, pubK.N) + return c +} +func DecryptBigInt(bigint *big.Int, privK RSAPrivateKey) *big.Int { + Cd := new(big.Int).Exp(bigint, privK.D, nil) + m := new(big.Int).Mod(Cd, privK.N) + return m +} + +func EncryptInt(char int, pubK RSAPublicKey) int { + charBig := big.NewInt(int64(char)) + Me := charBig.Exp(charBig, pubK.E, nil) + c := Me.Mod(Me, pubK.N) + return int(c.Int64()) +} +func DecryptInt(val int, privK RSAPrivateKey) int { + valBig := big.NewInt(int64(val)) + Cd := valBig.Exp(valBig, privK.D, nil) + m := Cd.Mod(Cd, privK.N) + return int(m.Int64()) +} + +func Blind(m []int, r int, pubK RSAPublicKey, privK RSAPrivateKey) []int { + var mBlinded []int + rBigInt := big.NewInt(int64(r)) + for i := 0; i < len(m); i++ { + mBigInt := big.NewInt(int64(m[i])) + rE := new(big.Int).Exp(rBigInt, pubK.E, nil) + mrE := new(big.Int).Mul(mBigInt, rE) + mrEmodN := new(big.Int).Mod(mrE, privK.N) + mBlinded = append(mBlinded, int(mrEmodN.Int64())) + } + return mBlinded +} + +func BlindSign(m []int, pubK RSAPublicKey, privK RSAPrivateKey) []int { + var r []int + for i := 0; i < len(m); i++ { + mBigInt := big.NewInt(int64(m[i])) + sigma := new(big.Int).Exp(mBigInt, privK.D, pubK.N) + r = append(r, int(sigma.Int64())) + } + return r +} +func Unblind(blindsigned []int, r int, pubK RSAPublicKey) []int { + var mSigned []int + rBigInt := big.NewInt(int64(r)) + for i := 0; i < len(blindsigned); i++ { + bsBigInt := big.NewInt(int64(blindsigned[i])) + //r1 := new(big.Int).Exp(rBigInt, big.NewInt(int64(-1)), nil) + r1 := new(big.Int).ModInverse(rBigInt, pubK.N) + bsr := new(big.Int).Mul(bsBigInt, r1) + sig := new(big.Int).Mod(bsr, pubK.N) + mSigned = append(mSigned, int(sig.Int64())) + } + return mSigned +} +func Verify(msg []int, mSigned []int, pubK RSAPublicKey) bool { + if len(msg) != len(mSigned) { + return false + } + var mSignedDecrypted []int + for _, ms := range mSigned { + msBig := big.NewInt(int64(ms)) + //decrypt the mSigned with pubK + Cd := new(big.Int).Exp(msBig, pubK.E, nil) + m := new(big.Int).Mod(Cd, pubK.N) + mSignedDecrypted = append(mSignedDecrypted, int(m.Int64())) + } + fmt.Print("msg signed decrypted: ") + fmt.Println(mSignedDecrypted) + r := true + //check if the mSignedDecrypted == msg + for i := 0; i < len(msg); i++ { + if msg[i] != mSignedDecrypted[i] { + r = false + } + } + return r +} + +func HomomorphicMultiplication(c1 int, c2 int, pubK RSAPublicKey) int { + c1BigInt := big.NewInt(int64(c1)) + c2BigInt := big.NewInt(int64(c2)) + c1c2 := new(big.Int).Mul(c1BigInt, c2BigInt) + n2 := new(big.Int).Mul(pubK.N, pubK.N) + d := new(big.Int).Mod(c1c2, n2) + r := int(d.Int64()) + return r +} + +func PubKStringToBigInt(kS RSAPublicKeyString) (RSAPublicKey, error) { + var k RSAPublicKey + var ok bool + k.E, ok = new(big.Int).SetString(kS.E, 10) + if !ok { + return k, errors.New("error parsing big int E") + } + k.N, ok = new(big.Int).SetString(kS.N, 10) + if !ok { + return k, errors.New("error parsing big int N") + } + return k, nil +} diff --git a/serverIDsigner/readConfig.go b/serverIDsigner/readConfig.go new file mode 100755 index 0000000..b4edf67 --- /dev/null +++ b/serverIDsigner/readConfig.go @@ -0,0 +1,27 @@ +package main + +import ( + "encoding/json" + "io/ioutil" +) + +//Config reads the config +type Config struct { + IP string `json:"ip"` + Port string `json:"port"` + WebServerPort string `json:"webserverport"` + Mongodb MongoConfig `json:"mongodb"` +} +type MongoConfig struct { + IP string `json:"ip"` + Database string `json:"database"` +} + +var config Config + +func readConfig(path string) { + file, err := ioutil.ReadFile(path) + check(err) + content := string(file) + json.Unmarshal([]byte(content), &config) +} diff --git a/serverIDsigner/restConfig.go b/serverIDsigner/restConfig.go new file mode 100755 index 0000000..36a332e --- /dev/null +++ b/serverIDsigner/restConfig.go @@ -0,0 +1,47 @@ +package main + +import ( + "log" + "net/http" + "time" + + "github.com/gorilla/mux" +) + +type Route struct { + Name string + Method string + Pattern string + HandlerFunc http.HandlerFunc +} + +func Logger(inner http.Handler, name string) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + start := time.Now() + + inner.ServeHTTP(w, r) + + log.Printf( + "%s\t%s\t%s\t%s", + r.Method, + r.RequestURI, + name, + time.Since(start), + ) + }) +} +func NewRouter() *mux.Router { + router := mux.NewRouter().StrictSlash(true) + for _, route := range routes { + var handler http.Handler + handler = route.HandlerFunc + handler = Logger(handler, route.Name) + + router. + Methods(route.Method). + Path(route.Pattern). + Name(route.Name). + Handler(handler) + } + return router +} diff --git a/serverIDsigner/restRoutes.go b/serverIDsigner/restRoutes.go new file mode 100755 index 0000000..ddbfeef --- /dev/null +++ b/serverIDsigner/restRoutes.go @@ -0,0 +1,36 @@ +package main + +type Routes []Route + +var routes = Routes{ + Route{ + "Index", + "GET", + "/", + Index, + }, + Route{ + "Signup", + "POST", + "/signup", + Signup, + }, + Route{ + "Login", + "POST", + "/login", + Login, + }, + Route{ + "BlindSign", + "POST", + "/blindsign", + BlindSign, + }, + Route{ + "VerifySign", + "POST", + "/verifysign", + VerifySign, + }, +} diff --git a/serverIDsigner/testUser.sh b/serverIDsigner/testUser.sh new file mode 100644 index 0000000..01b1ef7 --- /dev/null +++ b/serverIDsigner/testUser.sh @@ -0,0 +1,20 @@ +echo "" +echo "sending the signup, response:" +curl -X POST http://127.0.0.1:3130/signup -d '{"email": "user1@e.com", "password": "user1"}' + +echo "" +echo "sending the login, response:" +curl -X POST http://127.0.0.1:3130/login -d '{"email": "user1@e.com", "password": "user1"}' + + +echo "" +echo "send pubK and m to blind sign" +echo "json to send to the serverIDsigner:" +echo '{"pubKstring": {"e": "65537", "n": "139093"}, "m": "hola"}' +echo "serverIDsigner response:" +BLINDSIGNED=$(curl -X POST http://127.0.0.1:3130/blindsign -d '{"pubKstring": {"e": "65537", "n": "139093"}, "m": "hola"}') +echo "$BLINDSIGNED" + +echo "" +echo "send blindsigned to the serverIDsigner to verify" +curl -X POST http://127.0.0.1:3130/verifysign -d '{"m": "hola", "mSigned": "131898 40373 107552 34687"}' diff --git a/serverCA/tokens.go b/serverIDsigner/tokens.go similarity index 100% rename from serverCA/tokens.go rename to serverIDsigner/tokens.go diff --git a/serverCA/userRESTFunctions.go b/serverIDsigner/userRESTFunctions.go similarity index 55% rename from serverCA/userRESTFunctions.go rename to serverIDsigner/userRESTFunctions.go index 59a7518..d9142fc 100644 --- a/serverCA/userRESTFunctions.go +++ b/serverIDsigner/userRESTFunctions.go @@ -4,8 +4,12 @@ import ( "encoding/json" "fmt" "net/http" + "strconv" + "strings" "gopkg.in/mgo.v2/bson" + + ownrsa "./ownrsa" ) type User struct { @@ -15,8 +19,12 @@ type User struct { Token string `json:"token"` } +func Index(w http.ResponseWriter, r *http.Request) { + //TODO return the public key, to allow others verifign signed strings by this server + fmt.Fprintln(w, "serverIDsigner") +} + func Signup(w http.ResponseWriter, r *http.Request) { - //ipFilter(w, r) decoder := json.NewDecoder(r.Body) var user User @@ -50,7 +58,6 @@ func Signup(w http.ResponseWriter, r *http.Request) { } func Login(w http.ResponseWriter, r *http.Request) { - //ipFilter(w, r) decoder := json.NewDecoder(r.Body) var user User @@ -75,9 +82,6 @@ func Login(w http.ResponseWriter, r *http.Request) { err = userCollection.Update(bson.M{"_id": rUser.Id}, user) check(err) } - //generate the token - //add the token to the user - //save the user with the new token jResp, err := json.Marshal(user) if err != nil { @@ -91,37 +95,76 @@ type Sign struct { C string `json:"c"` } -func BlindSign(w http.ResponseWriter, r *http.Request) { - //ipFilter(w, r) +type AskBlindSign struct { + PubKString ownrsa.RSAPublicKeyString `json:"pubKstring"` + PubK ownrsa.RSAPublicKey `json:"pubK"` + M string `json:"m"` +} +func BlindSign(w http.ResponseWriter, r *http.Request) { + fmt.Println(r.Body) decoder := json.NewDecoder(r.Body) - var user User - err := decoder.Decode(&user) + var askBlindSign AskBlindSign + err := decoder.Decode(&askBlindSign) if err != nil { panic(err) } defer r.Body.Close() - jResp, err := json.Marshal(user) + fmt.Println(askBlindSign) + askBlindSign.PubK, err = ownrsa.PubKStringToBigInt(askBlindSign.PubKString) if err != nil { - panic(err) + fmt.Fprintln(w, "error") + return } - fmt.Fprintln(w, string(jResp)) + + //convert msg to []int + var m []int + mBytes := []byte(askBlindSign.M) + for _, byte := range mBytes { + m = append(m, int(byte)) + } + + sigma := ownrsa.BlindSign(m, askBlindSign.PubK, serverRsa.PrivK) //here the privK will be the CA privK, not the m emmiter's one. The pubK is the user's one + fmt.Print("Sigma': ") + fmt.Println(sigma) + + fmt.Fprintln(w, sigma) +} + +type PetitionVerifySign struct { + M string `json:"m"` + MSigned string `json:"mSigned"` } -func VerifySign(w http.ResponseWriter, r *http.Request) { - //ipFilter(w, r) +func VerifySign(w http.ResponseWriter, r *http.Request) { decoder := json.NewDecoder(r.Body) - var user User - err := decoder.Decode(&user) + var petitionVerifySign PetitionVerifySign + err := decoder.Decode(&petitionVerifySign) if err != nil { panic(err) } defer r.Body.Close() - jResp, err := json.Marshal(user) - if err != nil { - panic(err) + fmt.Println(petitionVerifySign) + + //convert M to []int + var mOriginal []int + mBytes := []byte(petitionVerifySign.M) + for _, byte := range mBytes { + mOriginal = append(mOriginal, int(byte)) } - fmt.Fprintln(w, string(jResp)) + + //convert MSigned to []int + var mSignedInts []int + mSignedString := strings.Split(petitionVerifySign.MSigned, " ") + for _, s := range mSignedString { + i, err := strconv.Atoi(s) + check(err) + mSignedInts = append(mSignedInts, i) + } + + verified := ownrsa.Verify(mOriginal, mSignedInts, serverRsa.PubK) + + fmt.Fprintln(w, verified) }