Browse Source

updated ethereum smart contract. Implemented backend of the login library example

master
arnaucode 6 years ago
parent
commit
55594e3b45
24 changed files with 632 additions and 26 deletions
  1. BIN
      clientApp/GUI/img/darkID-logo01_transparent.png
  2. +19
    -18
      clientApp/GUI/views/id/id.html
  3. +1
    -1
      clientApp/GUI/views/login/login.js
  4. +18
    -2
      clientApp/GUI/views/signup/signup.js
  5. +4
    -1
      clientApp/main.go
  6. +3
    -0
      darkID-library-login-example/.gitignore
  7. +1
    -0
      darkID-library-login-example/README.md
  8. +75
    -0
      darkID-library-login-example/RESTfunctions.go
  9. +3
    -0
      darkID-library-login-example/config.json
  10. +15
    -0
      darkID-library-login-example/errors.go
  11. +12
    -0
      darkID-library-login-example/hash.go
  12. +183
    -0
      darkID-library-login-example/keys.go
  13. +24
    -0
      darkID-library-login-example/log.go
  14. +46
    -0
      darkID-library-login-example/main.go
  15. +20
    -0
      darkID-library-login-example/readConfig.go
  16. +47
    -0
      darkID-library-login-example/restConfig.go
  17. +24
    -0
      darkID-library-login-example/restRoutes.go
  18. +20
    -0
      darkID-library-login-example/testUser.sh
  19. +49
    -0
      darkID-library-login-example/tokens.go
  20. +1
    -1
      eth/darkID_contract.sol
  21. +1
    -0
      eth/darkID_contract_sol_DarkID.abi
  22. +1
    -0
      eth/darkID_contract_sol_DarkID.bin
  23. +52
    -0
      eth/instructions.md
  24. +13
    -3
      serverIDsigner/RESTfunctions.go

BIN
clientApp/GUI/img/darkID-logo01_transparent.png

Before After
Width: 1279  |  Height: 1279  |  Size: 223 KiB

+ 19
- 18
clientApp/GUI/views/id/id.html

@ -21,29 +21,30 @@
placeholder="Enter here the proof-of-decrypt..."
></textarea>
</div>
<h5 ng-show="decryptData.m">PoD:</h5>
{{decryptData.m}}
<div ng-click="decrypt()" ng-show="id.blockchainref" class="btn btn-raised pull-right c_o_pink300">
Proof of decrypt
</div>
</div>
</div>
<br><br><br><br><br>
<hr>
<div class="row">
<h5>Testing only:</h5>
<div class="row">
<textarea style="color:#000000;width:100%;" rows="4"
ng-model="encryptData.m"
placeholder="Enter here the unencrypted..."
></textarea>
</div>
<textarea style="backgroud:grey;color:#000000;width:100%;" rows="4"
ng-model="encryptData.c"
placeholder="Encrypted data..."
></textarea>
<div ng-click="encrypt()" ng-show="id.blockchainref" class="btn btn-raised pull-right c_o_orange300">
Encrypt
<br><br><br><br><br>
<hr>
<h5>Testing only:</h5>
<div class="row">
<textarea style="color:#000000;width:100%;" rows="4"
ng-model="encryptData.m"
placeholder="Enter here the unencrypted..."
></textarea>
</div>
<div class="row">
<textarea style="backgroud:grey;color:#000000;width:100%;" rows="4"
ng-model="encryptData.c"
placeholder="Encrypted data..."
></textarea>
</div>
<div ng-click="encrypt()" ng-show="id.blockchainref" class="btn btn-raised pull-right c_o_orange300">
Encrypt
</div>
</div>
</div>
</div>

+ 1
- 1
clientApp/GUI/views/login/login.js

@ -49,7 +49,7 @@ angular.module('app.login', ['ngRoute'])
window.location.reload();
} else {
console.log("login failed");
toastr.error('Login failed');
toastr.error('Login failed, ' + data.data);
}

+ 18
- 2
clientApp/GUI/views/signup/signup.js

@ -9,11 +9,27 @@ angular.module('app.signup', ['ngRoute'])
});
}])
.controller('SignupCtrl', function($scope, $http, $routeParams) {
.controller('SignupCtrl', function($scope, $http, $routeParams, $rootScope) {
$scope.user = {};
$scope.doSignup = function() {
$scope.signup = function() {
console.log('Doing signup', $scope.user);
$http({
url: $rootScope.server + 'signup',
method: "POST",
headers: {
"Content-Type": undefined
},
data: $scope.user
})
.then(function(data) {
console.log("data: ");
console.log(data.data);
window.location="/";
},
function(data) {
console.log(data);
});
};
});

+ 4
- 1
clientApp/main.go

@ -38,5 +38,8 @@ func main() {
}
func GUI() {
//here, run electron app
//here, run webserver
log.Println("webserver in port " + "8080")
http.Handle("/", http.FileServer(http.Dir("./web")))
http.ListenAndServe(":"+"8080", nil)
}

+ 3
- 0
darkID-library-login-example/.gitignore

@ -0,0 +1,3 @@
keys.json
keys
web

+ 1
- 0
darkID-library-login-example/README.md

@ -0,0 +1 @@
# darkID-login-library-example

+ 75
- 0
darkID-library-login-example/RESTfunctions.go

@ -0,0 +1,75 @@
package main
import (
"encoding/json"
"fmt"
"net/http"
"github.com/cryptoballot/rsablind"
"github.com/fatih/color"
"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 Index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "clientApp")
}
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)
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 key Key
err := decoder.Decode(&key)
if err != nil {
panic(err)
}
defer r.Body.Close()
//TODO check if the user password exists in the database
fmt.Print("key login: ")
fmt.Println(key)
token, err := newToken()
check(err)
//validate if the pubK darkID is in the blockchain
//verify that the darkID is signed
if err := rsablind.VerifyBlindSignature(key.ServerVerifier, key.Hashed, key.UnblindedSig); err != nil {
fmt.Println(err)
} else {
color.Green("blind signature verified")
}
/*jResp, err := json.Marshal(token)
if err != nil {
panic(err)
}*/
fmt.Fprintln(w, string(token))
}

+ 3
- 0
darkID-library-login-example/config.json

@ -0,0 +1,3 @@
{
"port": "5000"
}

+ 15
- 0
darkID-library-login-example/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)
}
}

+ 12
- 0
darkID-library-login-example/hash.go

@ -0,0 +1,12 @@
package main
import (
"crypto/sha256"
"encoding/base64"
)
func hash(s string) string {
h := sha256.New()
h.Write([]byte(s))
return base64.URLEncoding.EncodeToString(h.Sum(nil))
}

+ 183
- 0
darkID-library-login-example/keys.go

@ -0,0 +1,183 @@
package main
import (
"crypto/rsa"
"crypto/x509"
"encoding/asn1"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"os"
"time"
"github.com/fatih/color"
)
type Key struct {
ID string `json:"id"`
PrivK string `json:"privK"` //path of the PrivK file
PubK string `json:"pubK"` //path of the PubK file
Date time.Time `json:"date"`
Hashed []byte `json:"hashed"`
UnblindedSig []byte `json:"unblindedsig"`
Verified bool `json:"verified"`
ServerVerifier *rsa.PublicKey `json:"serververifier"`
SignerID string `json:"signerid"`
BlockchainRef string `json:"blockchainref"`
}
func ExportRsaPrivateKeyAsPemStr(privkey *rsa.PrivateKey) string {
privkey_bytes := x509.MarshalPKCS1PrivateKey(privkey)
privkey_pem := pem.EncodeToMemory(
&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privkey_bytes,
},
)
return string(privkey_pem)
}
func ParseRsaPrivateKeyFromPemStr(privPEM string) (*rsa.PrivateKey, error) {
block, _ := pem.Decode([]byte(privPEM))
if block == nil {
return nil, errors.New("failed to parse PEM block containing the key")
}
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return priv, nil
}
func ExportRsaPublicKeyAsPemStr(pubkey rsa.PublicKey) (string, error) {
asn1Bytes, err := asn1.Marshal(pubkey)
check(err)
pubkey_pem := pem.EncodeToMemory(
&pem.Block{
Type: "PUBLIC KEY",
Bytes: asn1Bytes,
},
)
color.Red("pubkey_pem")
fmt.Println(pubkey_pem)
return string(pubkey_pem), nil
}
func ParseRsaPublicKeyFromPemStr(pubPEM string) (pub rsa.PublicKey, err error) {
pemBlock, _ := pem.Decode([]byte(pubPEM))
_, err = asn1.Unmarshal(pemBlock.Bytes, &pub)
return
}
func savePEMKey(fileName string, key *rsa.PrivateKey) {
outFile, err := os.Create(fileName)
check(err)
defer outFile.Close()
var privateKey = &pem.Block{
Type: "PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(key),
}
err = pem.Encode(outFile, privateKey)
check(err)
}
func savePublicPEMKey(fileName string, pubkey rsa.PublicKey) {
asn1Bytes, err := asn1.Marshal(pubkey)
check(err)
var pemkey = &pem.Block{
Type: "PUBLIC KEY",
Bytes: asn1Bytes,
}
pemfile, err := os.Create(fileName)
check(err)
defer pemfile.Close()
err = pem.Encode(pemfile, pemkey)
check(err)
}
func openPEMKey(path string) (key *rsa.PrivateKey, err error) {
b, err := ioutil.ReadFile(path)
if err != nil {
fmt.Print(err)
}
key, err = ParseRsaPrivateKeyFromPemStr(string(b))
return
}
func openPublicPEMKey(path string) (key rsa.PublicKey, err error) {
b, err := ioutil.ReadFile(path)
if err != nil {
fmt.Print(err)
}
key, err = ParseRsaPublicKeyFromPemStr(string(b))
return
}
func readKeys() []Key {
path := keysDir + "/keys.json"
var keys []Key
file, err := ioutil.ReadFile(path)
check(err)
content := string(file)
json.Unmarshal([]byte(content), &keys)
return keys
}
func saveKeys(keys []Key) {
jsonKeys, err := json.Marshal(keys)
check(err)
err = ioutil.WriteFile(keysDir+"/keys.json", jsonKeys, 0644)
check(err)
}
func saveKey(k Key) {
fmt.Println(k)
keys := readKeys()
for i, key := range keys {
if key.ID == k.ID {
keys[i] = k
}
}
saveKeys(keys)
}
func getKeyByKeyID(keyID string) (k Key) {
keys := readKeys()
for _, key := range keys {
if key.ID == keyID {
k = key
}
}
return k
}
func removeKey(keyID string, originalKeys []Key) (keys []Key) {
for _, key := range originalKeys {
if key.ID != keyID {
keys = append(keys, key)
}
}
return
}
/*
func getServerPubK(url string) ownrsa.RSAPublicKey {
r, err := http.Get(url + "/")
check(err)
fmt.Println(r)
decoder := json.NewDecoder(r.Body)
//var sigmaString string
var pubK ownrsa.RSAPublicKey
err = decoder.Decode(&pubK)
if err != nil {
panic(err)
}
defer r.Body.Close()
color.Blue("received server pubK:")
fmt.Println(pubK)
return pubK
}
*/

+ 24
- 0
darkID-library-login-example/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)
}

+ 46
- 0
darkID-library-login-example/main.go

@ -0,0 +1,46 @@
package main
import (
"fmt"
"log"
"net/http"
"github.com/fatih/color"
"github.com/gorilla/handlers"
)
const keysDir = "keys"
const keysize = 2048
const hashize = 1536
func main() {
color.Blue("Starting darkID-libarary-login-example")
readConfig("config.json")
fmt.Println(config)
/*//create keys directory
_ = os.Mkdir(keysDir, os.ModePerm)*/
initializeToken()
//run thw webserver
go GUI()
//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 GUI() {
//here, run webserver
log.Println("webserver in port " + "8080")
http.Handle("/", http.FileServer(http.Dir("./web")))
http.ListenAndServe(":"+"8080", nil)
}

+ 20
- 0
darkID-library-login-example/readConfig.go

@ -0,0 +1,20 @@
package main
import (
"encoding/json"
"io/ioutil"
)
//Config reads the config
type Config struct {
Port string `json:"port"`
}
var config Config
func readConfig(path string) {
file, err := ioutil.ReadFile(path)
check(err)
content := string(file)
json.Unmarshal([]byte(content), &config)
}

+ 47
- 0
darkID-library-login-example/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
}

+ 24
- 0
darkID-library-login-example/restRoutes.go

@ -0,0 +1,24 @@
package main
type Routes []Route
var routes = Routes{
Route{
"Index",
"GET",
"/",
Index,
},
Route{
"Signup",
"POST",
"/signup",
Signup,
},
Route{
"Login",
"POST",
"/login",
Login,
},
}

+ 20
- 0
darkID-library-login-example/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"}'

+ 49
- 0
darkID-library-login-example/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.")
}
}

+ 1
- 1
eth/darkID_contract.sol

@ -13,7 +13,7 @@ contract DarkID {
}
IdStruct ID;
IdStruct public ID;
function DarkID(string _pubK, string _hashed, string _unblindedSig, string _serverVerifier, string _signerID) public {

+ 1
- 0
eth/darkID_contract_sol_DarkID.abi

@ -0,0 +1 @@
[{"constant":true,"inputs":[],"name":"getDarkID","outputs":[{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ID","outputs":[{"name":"pubK","type":"string"},{"name":"date","type":"string"},{"name":"hashed","type":"string"},{"name":"unblindedSig","type":"string"},{"name":"serverVerifier","type":"string"},{"name":"signerID","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_pubK","type":"string"},{"name":"_hashed","type":"string"},{"name":"_unblindedSig","type":"string"},{"name":"_serverVerifier","type":"string"},{"name":"_signerID","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]

+ 1
- 0
eth/darkID_contract_sol_DarkID.bin
File diff suppressed because it is too large
View File


+ 52
- 0
eth/instructions.md

@ -0,0 +1,52 @@
- start node and blockchain syncing in testnet
```
geth --testnet --datadir ~/eth-testnet
```
- create first account (wallet)
```
geth --testnet --datadir ~/eth-testnet account new
```
- mine ethers in testnet
```
geth --testnet --datadir ~/eth-testnet --mine
```
- serve dapp running on localhost:8000 via RPC
```
geth --testnet --datadir ~/eth-testnet --rpc --rpccorsdomain "http://localhost:8000" --rpcapi eth,web3,personal
```
- generate ABI from contract.sol
```
solcjs --abi HelloWorldContract.sol
```
- generate the byte code
```
solcjs --bin HelloWorldContract.sol
```
- deploy contract via geth js console
- open geth console
```
geth --testnet --datadir ~/eth-testnet console
```
- in the console create the contract using ABI and BYTE CODE result from compilation
```js
var abi = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"}];
var code = '0x60606040527f48656c6c6f20576f726c64000000000000000000000000000000000000000000600090600019169055341561003957600080fd5b5b609d806100486000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde0314603d575b600080fd5b3415604757600080fd5b604d606b565b60405180826000191660001916815260200191505060405180910390f35b600054815600a165627a7a72305820f4c510e24a238337d5334b5b38a44e88ea53ef40f26aeb96eba4609cb72827cd0029';
web3.personal.unlockAccount(eth.accounts[0], 'PASSWORD');
var inputdata = ["pub", "h", "u", "sv", "signerid"];
var contract = web3.eth.contract(abi).new(inputdata,{ from: eth.accounts[0], data: code, gas: 1000000 });
web3.personal.lockAccount(eth.accounts[0]);
```
- call the method in the contract
```js
contract.name()
```

serverIDsigner/userRESTFunctions.go → serverIDsigner/RESTfunctions.go

@ -82,11 +82,21 @@ func Login(w http.ResponseWriter, r *http.Request) {
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)
jResp, err := json.Marshal("error login, email not found")
check(err)
fmt.Fprintln(w, string(jResp))
return
}
//user exists, check password
if user.Password != rUser.Password {
jResp, err := json.Marshal("error login, password not match")
check(err)
fmt.Fprintln(w, string(jResp))
return
}
//update with the token
err = userCollection.Update(bson.M{"_id": rUser.Id}, user)
check(err)
jResp, err := json.Marshal(user)
if err != nil {

Loading…
Cancel
Save