arnaucube
arnaucube/blockchainIDsystemPublic Self-hosted repository
added serverIDsigner. At this moment performs: signup, login, blindsign
arnaucode arnaucode@gmail.com
Wed, 27 Dec 2017 16:28:54 +0100
commit

92462dc3dba9b58acae679e78eec23f3278efa0e

parent

08e3915994b8ed44b5baed70bfdf223729e1c48e

M .gitignore → .gitignore

@@ -1,1 +1,2 @@

tests +peer/blockchain.data
M README.md → README.md

@@ -17,6 +17,7 @@ - the peers of the p2p network that runs the blockchain

- 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
D peer/.gitignore

@@ -1,1 +0,0 @@

-blockchain.data
M peer/blockchain.data → peer/blockchain.data

@@ -1,1 +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="}]}+{"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="}]}
M runTmuxTestPeers.sh → 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
M serverCA/config.json → serverCA/config.json

@@ -4,9 +4,5 @@ "port": "3030",

"serverip": "127.0.0.1", "serverport": "3000", "serverrestport": "3002", - "webserverport": "3080", - "mongodb": { - "ip": "127.0.0.1:27017", - "database": "serverCA" - } + "webserverport": "3080" }
M serverCA/main.go → serverCA/main.go

@@ -6,8 +6,6 @@ "net"

"net/http" "time" - mgo "gopkg.in/mgo.v2" - "github.com/fatih/color" "github.com/gorilla/handlers" )

@@ -28,21 +26,12 @@ }

var peersList PeersList -var userCollection *mgo.Collection - func main() { color.Blue("Starting CA") //read configuration file 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()
M serverCA/readConfig.go → serverCA/readConfig.go

@@ -7,17 +7,12 @@ )

//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
M serverCA/restRoutes.go → serverCA/restRoutes.go

@@ -21,35 +21,4 @@ "GET",

"/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, - }, }
D serverCA/testUser.sh

@@ -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"}'
D serverCA/userRESTFunctions.go

@@ -1,127 +0,0 @@

-package main - -import ( - "encoding/json" - "fmt" - "net/http" - - "gopkg.in/mgo.v2/bson" -) - -type User struct { - Id bson.ObjectId `json:"id" bson:"_id,omitempty"` - Email string `json:"email"` - Password string `json:"password"` - Token string `json:"token"` -} - -func Signup(w http.ResponseWriter, r *http.Request) { - //ipFilter(w, r) - - decoder := json.NewDecoder(r.Body) - var user User - err := decoder.Decode(&user) - if err != nil { - panic(err) - } - defer r.Body.Close() - - fmt.Print("user signup: ") - fmt.Println(user) - - //save the new project to mongodb - rUser := User{} - err = userCollection.Find(bson.M{"email": user.Email}).One(&rUser) - if err != nil { - //user not exists - err = userCollection.Insert(user) //TODO find a way to get the object result when inserting in one line, without need of the two mgo petitions - err = userCollection.Find(bson.M{"email": user.Email}).One(&user) - } else { - //user exists - fmt.Fprintln(w, "User already registered") - return - } - - jResp, err := json.Marshal(user) - if err != nil { - panic(err) - } - fmt.Fprintln(w, string(jResp)) -} - -func Login(w http.ResponseWriter, r *http.Request) { - //ipFilter(w, r) - - decoder := json.NewDecoder(r.Body) - var user User - err := decoder.Decode(&user) - if err != nil { - panic(err) - } - defer r.Body.Close() - - fmt.Print("user login: ") - fmt.Println(user) - token, err := newToken() - check(err) - user.Token = token - - //save the new project to mongodb - rUser := User{} - err = userCollection.Find(bson.M{"email": user.Email}).One(&rUser) - if err != nil { - } else { - //user exists, update with the token - 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 { - panic(err) - } - fmt.Fprintln(w, string(jResp)) -} - -type Sign struct { - M string `json:"m"` - C string `json:"c"` -} - -func BlindSign(w http.ResponseWriter, r *http.Request) { - //ipFilter(w, r) - - decoder := json.NewDecoder(r.Body) - var user User - err := decoder.Decode(&user) - if err != nil { - panic(err) - } - defer r.Body.Close() - - jResp, err := json.Marshal(user) - if err != nil { - panic(err) - } - fmt.Fprintln(w, string(jResp)) -} -func VerifySign(w http.ResponseWriter, r *http.Request) { - //ipFilter(w, r) - - decoder := json.NewDecoder(r.Body) - var user User - err := decoder.Decode(&user) - if err != nil { - panic(err) - } - defer r.Body.Close() - - jResp, err := json.Marshal(user) - if err != nil { - panic(err) - } - fmt.Fprintln(w, string(jResp)) -}
A 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
A 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" + } +}
A 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) + } +}
A 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) +}
A 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) +}
A 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) +}
A 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 +}
A 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) +}
A 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 +}
A 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, + }, +}
A 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"}'
A serverIDsigner/userRESTFunctions.go

@@ -0,0 +1,170 @@

+package main + +import ( + "encoding/json" + "fmt" + "net/http" + "strconv" + "strings" + + "gopkg.in/mgo.v2/bson" + + ownrsa "./ownrsa" +) + +type User struct { + Id bson.ObjectId `json:"id" bson:"_id,omitempty"` + Email string `json:"email"` + Password string `json:"password"` + 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) { + + decoder := json.NewDecoder(r.Body) + var user User + err := decoder.Decode(&user) + if err != nil { + panic(err) + } + defer r.Body.Close() + + fmt.Print("user signup: ") + fmt.Println(user) + + //save the new project to mongodb + rUser := User{} + err = userCollection.Find(bson.M{"email": user.Email}).One(&rUser) + if err != nil { + //user not exists + err = userCollection.Insert(user) //TODO find a way to get the object result when inserting in one line, without need of the two mgo petitions + err = userCollection.Find(bson.M{"email": user.Email}).One(&user) + } else { + //user exists + fmt.Fprintln(w, "User already registered") + return + } + + jResp, err := json.Marshal(user) + if err != nil { + panic(err) + } + fmt.Fprintln(w, string(jResp)) +} + +func Login(w http.ResponseWriter, r *http.Request) { + + decoder := json.NewDecoder(r.Body) + var user User + err := decoder.Decode(&user) + if err != nil { + panic(err) + } + defer r.Body.Close() + + fmt.Print("user login: ") + fmt.Println(user) + token, err := newToken() + check(err) + user.Token = token + + //save the new project to mongodb + rUser := User{} + err = userCollection.Find(bson.M{"email": user.Email}).One(&rUser) + if err != nil { + } else { + //user exists, update with the token + err = userCollection.Update(bson.M{"_id": rUser.Id}, user) + check(err) + } + + jResp, err := json.Marshal(user) + if err != nil { + panic(err) + } + fmt.Fprintln(w, string(jResp)) +} + +type Sign struct { + M string `json:"m"` + C string `json:"c"` +} + +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 askBlindSign AskBlindSign + err := decoder.Decode(&askBlindSign) + if err != nil { + panic(err) + } + defer r.Body.Close() + + fmt.Println(askBlindSign) + askBlindSign.PubK, err = ownrsa.PubKStringToBigInt(askBlindSign.PubKString) + if err != nil { + fmt.Fprintln(w, "error") + return + } + + //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) { + decoder := json.NewDecoder(r.Body) + var petitionVerifySign PetitionVerifySign + err := decoder.Decode(&petitionVerifySign) + if err != nil { + panic(err) + } + defer r.Body.Close() + + fmt.Println(petitionVerifySign) + + //convert M to []int + var mOriginal []int + mBytes := []byte(petitionVerifySign.M) + for _, byte := range mBytes { + mOriginal = append(mOriginal, int(byte)) + } + + //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) +}