Browse Source

Implemented signup and login users with JWT and MongoDB connection. Added runTmuxTextPeers.sh to deploy the different peers and servers in a unique console

master
arnaucode 6 years ago
parent
commit
08e3915994
14 changed files with 327 additions and 51 deletions
  1. +11
    -11
      README.md
  2. +1
    -1
      peer/blockchain.data
  3. +18
    -0
      runTmuxTestPeers.sh
  4. +0
    -0
      runXtermTestPeers.sh
  5. +3
    -1
      serverCA/blockchain.go
  6. +32
    -0
      serverCA/blockchainRESTFunctions.go
  7. +5
    -1
      serverCA/config.json
  8. +11
    -1
      serverCA/main.go
  9. +26
    -0
      serverCA/mongoOperations.go
  10. +11
    -6
      serverCA/readConfig.go
  11. +30
    -30
      serverCA/restRoutes.go
  12. +3
    -0
      serverCA/testUser.sh
  13. +49
    -0
      serverCA/tokens.go
  14. +127
    -0
      serverCA/userRESTFunctions.go

+ 11
- 11
README.md

@ -24,17 +24,17 @@ There are different types of nodes:
#### Step by step process
1. Once all the nodes of the network are running, a new user can connect to the server-ID-signer.
- The user registers a non anonymous user (using email, phone, password, etc), and performs the login with that user
- The user, locally, generates a RSA key pair (private key & public key)
- The user blinds his Public-Key with the server-ID-signer Public-Key
- The user's Public-Key blinded, is sent to the server-ID-signer
- The server-ID-signer Blind Signs the Public-Key blinded from the user, and returns it to the user
- The user unblinds the Public-Key signed by the server-ID-signer, and now has the Public-Key Blind Signed by the server-ID-signer
- The user sends the Public-Key blind signed to the p2p network
- The peers verify that the Public-Key Blind Signed is correctly signed by the server-ID-signer, if it is, they add the Public-Key to the Blockchain, inside a new block
- Then, when the user wants to login into a platform, just needs to put his Public-Key
- The platform goes to the Blockchain, to check if this Public-Key is registered in the blockchain
- The platform sends a message encrypted with the user Public-Key, and the user returns the message decrypted with the Private-Key, to verify that is the owner of that Public-Key
2. The user registers a non anonymous user (using email, phone, password, etc), and performs the login with that user
3. The user, locally, generates a RSA key pair (private key & public key)
4. The user blinds his Public-Key with the server-ID-signer Public-Key
5. The user's Public-Key blinded, is sent to the server-ID-signer
6. The server-ID-signer Blind Signs the Public-Key blinded from the user, and returns it to the user
7. The user unblinds the Public-Key signed by the server-ID-signer, and now has the Public-Key Blind Signed by the server-ID-signer
8. The user sends the Public-Key blind signed to the p2p network
9. The peers verify that the Public-Key Blind Signed is correctly signed by the server-ID-signer, if it is, they add the Public-Key to the Blockchain, inside a new block
10. Then, when the user wants to login into a platform, just needs to put his Public-Key
11. The platform goes to the Blockchain, to check if this Public-Key is registered in the blockchain
12. The platform sends a message encrypted with the user Public-Key, and the user returns the message decrypted with the Private-Key, to verify that is the owner of that Public-Key
##### RSA encryption system

+ 1
- 1
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":"","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":"","data":[{"address":"firstaddress"}],"emitter":"VOnL-15rFsUiCnRoyGFksKvWKcwNBRz5iarRem0Ilvo="}]}

+ 18
- 0
runTmuxTestPeers.sh

@ -0,0 +1,18 @@
SESSION='peersTest'
tmux new-session -d -s $SESSION
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 send-keys -t 0 'cd peer && go run *.go server 3001 3002' enter
sleep 2
tmux send-keys -t 1 "curl -X POST http://127.0.0.1:3002/register -d '{\"address\": \"firstaddress\"}'" enter
sleep 1
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 attach

runTestPeers.sh → runXtermTestPeers.sh


+ 3
- 1
serverCA/blockchain.go

@ -68,7 +68,9 @@ func reconstructBlockchainFromBlock(urlAPI string, h string) {
var err error
block, err = blockchain.getBlockByHash(h)
check(err)
if err != nil {
fmt.Println("reconstructBlockFromBlock: block with " + h + " not found. Getting genesis block")
}
if h == "" {
//no genesis block yet

+ 32
- 0
serverCA/blockchainRESTFunctions.go

@ -0,0 +1,32 @@
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type Address struct {
Address string `json:"address"` //the pubK of the user, to perform logins
}
func Index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "CA")
}
func GetPeers(w http.ResponseWriter, r *http.Request) {
getPeers()
jResp, err := json.Marshal(peersList)
check(err)
fmt.Fprintln(w, string(jResp))
}
func GetBlockchain(w http.ResponseWriter, r *http.Request) {
fmt.Print("aaaaa: ")
fmt.Println(blockchain.Blocks[len(blockchain.Blocks)-1].Hash)
reconstructBlockchainFromBlock("http://"+config.IP+":"+config.ServerRESTPort, blockchain.Blocks[len(blockchain.Blocks)-1].Hash)
jResp, err := json.Marshal(blockchain)
check(err)
fmt.Fprintln(w, string(jResp))
}

+ 5
- 1
serverCA/config.json

@ -4,5 +4,9 @@
"serverip": "127.0.0.1",
"serverport": "3000",
"serverrestport": "3002",
"webserverport": "3080"
"webserverport": "3080",
"mongodb": {
"ip": "127.0.0.1:27017",
"database": "serverCA"
}
}

+ 11
- 1
serverCA/main.go

@ -6,6 +6,8 @@ import (
"net/http"
"time"
mgo "gopkg.in/mgo.v2"
"github.com/fatih/color"
"github.com/gorilla/handlers"
)
@ -26,14 +28,22 @@ type PeersList struct {
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()

+ 26
- 0
serverCA/mongoOperations.go

@ -0,0 +1,26 @@
package main
import (
mgo "gopkg.in/mgo.v2"
)
func getSession() (*mgo.Session, error) {
session, err := mgo.Dial("mongodb://" + config.Mongodb.IP)
if err != nil {
panic(err)
}
//defer session.Close()
// Optional. Switch the session to a monotonic behavior.
session.SetMode(mgo.Monotonic, true)
// Optional. Switch the session to a monotonic behavior.
session.SetMode(mgo.Monotonic, true)
return session, err
}
func getCollection(session *mgo.Session, collection string) *mgo.Collection {
c := session.DB(config.Mongodb.Database).C(collection)
return c
}

+ 11
- 6
serverCA/readConfig.go

@ -7,12 +7,17 @@ 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"`
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"`
}
var config Config

+ 30
- 30
serverCA/restRoutes.go

@ -1,11 +1,5 @@
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type Routes []Route
var routes = Routes{
@ -27,29 +21,35 @@ var routes = Routes{
"/blockchain",
GetBlockchain,
},
}
type Address struct {
Address string `json:"address"` //the pubK of the user, to perform logins
}
func Index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "CA")
}
func GetPeers(w http.ResponseWriter, r *http.Request) {
getPeers()
jResp, err := json.Marshal(peersList)
check(err)
fmt.Fprintln(w, string(jResp))
}
func GetBlockchain(w http.ResponseWriter, r *http.Request) {
fmt.Print("aaaaa: ")
fmt.Println(blockchain.Blocks[len(blockchain.Blocks)-1].Hash)
reconstructBlockchainFromBlock("http://"+config.IP+":"+config.ServerRESTPort, blockchain.Blocks[len(blockchain.Blocks)-1].Hash)
/*
POST /signup
POST /loginuser
POST /blindsign
POST /verifysign
jResp, err := json.Marshal(blockchain)
check(err)
fmt.Fprintln(w, string(jResp))
*/
Route{
"Signup",
"POST",
"/signup",
Signup,
},
Route{
"Login",
"POST",
"/login",
Login,
},
Route{
"BlindSign",
"POST",
"/blindsign",
BlindSign,
},
Route{
"VerifySign",
"POST",
"/verifysign",
VerifySign,
},
}

+ 3
- 0
serverCA/testUser.sh

@ -0,0 +1,3 @@
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"}'

+ 49
- 0
serverCA/tokens.go

@ -0,0 +1,49 @@
package main
import (
"fmt"
"time"
jwt "github.com/dgrijalva/jwt-go"
)
const (
signingKey = "this is the secret signing key"
)
var createdToken string
func initializeToken() {
var err error
createdToken, err = newToken()
if err != nil {
fmt.Println("Creating token failed")
}
}
func newToken() (string, error) {
signingKeyB := []byte(signingKey)
// Create the token
token := jwt.New(jwt.SigningMethodHS256)
// Set some claims
claims := make(jwt.MapClaims)
claims["foo"] = "bar"
claims["exp"] = time.Now().Add(time.Hour * 72).Unix()
token.Claims = claims
// Sign and get the complete encoded token as a string
tokenString, err := token.SignedString(signingKeyB)
return tokenString, err
}
func parseToken(myToken string, myKey string) {
token, err := jwt.Parse(myToken, func(token *jwt.Token) (interface{}, error) {
return []byte(myKey), nil
})
if err == nil && token.Valid {
fmt.Println("Your token is valid. I like your style.")
} else {
fmt.Println("This token is terrible! I cannot accept this.")
}
}

+ 127
- 0
serverCA/userRESTFunctions.go

@ -0,0 +1,127 @@
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))
}

Loading…
Cancel
Save