readme and some clean

This commit is contained in:
arnaucode
2018-02-09 10:52:43 +01:00
parent 3b65da470d
commit bb7f01ffb5
43 changed files with 111 additions and 61 deletions

2
darkID-login-example/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
keys.json
keys

View File

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

View File

@@ -0,0 +1,115 @@
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"encoding/json"
"errors"
"fmt"
mrand "math/rand"
"net/http"
"strings"
"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")
}
type Proof struct {
PublicKey string `json:"publicKey"`
Clear string `json:"clear"`
Question []byte `json:"question"`
Answer string `json:"answer"`
}
var proofs []Proof
func GetProof(w http.ResponseWriter, r *http.Request) {
decoder := json.NewDecoder(r.Body)
var receivedProof Proof
err := decoder.Decode(&receivedProof)
if err != nil {
panic(err)
}
defer r.Body.Close()
//TODO check if the user password exists in the database
stringPublicKey := strings.Replace(receivedProof.PublicKey, " ", "\n", -1)
stringPublicKey = strings.Replace(stringPublicKey, "-----BEGIN\n", "-----BEGIN ", -1)
stringPublicKey = strings.Replace(stringPublicKey, "-----END\n", "-----END ", -1)
stringPublicKey = strings.Replace(stringPublicKey, "PUBLIC\n", "PUBLIC ", -1)
color.Green(stringPublicKey)
publicKey, err := ParseRsaPublicKeyFromPemStr(stringPublicKey)
check(err)
var proof Proof
proof.Clear = RandStringRunes(40)
out, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, &publicKey, []byte(proof.Clear), []byte("orders"))
check(err)
proof.Question = out
proofs = append(proofs, proof)
proof.Clear = ""
jResp, err := json.Marshal(proof)
if err != nil {
panic(err)
}
fmt.Fprintln(w, string(jResp))
}
func AnswerProof(w http.ResponseWriter, r *http.Request) {
decoder := json.NewDecoder(r.Body)
var ansProof Proof
err := decoder.Decode(&ansProof)
if err != nil {
panic(err)
}
defer r.Body.Close()
proof, err := getProofFromStorage(ansProof.PublicKey)
if err != nil {
}
if ansProof.Answer == proof.Clear {
token, err := newToken()
check(err)
fmt.Fprintln(w, string(token))
}
fmt.Fprintln(w, string("fail"))
}
func getProofFromStorage(publicKey string) (Proof, error) {
var voidProof Proof
for _, proof := range proofs {
if proof.PublicKey == publicKey {
return proof, nil
}
}
return voidProof, errors.New("proof not exist in storage")
}
//function to generate random string of fixed length
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
func RandStringRunes(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letterRunes[mrand.Intn(len(letterRunes))]
}
return string(b)
}

View File

@@ -0,0 +1,4 @@
{
"port": "5010",
"webserverport": "5011"
}

15
darkID-login-example/errors.go Executable file
View File

@@ -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)
}
}

View File

@@ -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))
}

View File

@@ -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
darkID-login-example/log.go Executable file
View File

@@ -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)
}

View File

@@ -0,0 +1,49 @@
package main
import (
"fmt"
"log"
"math/rand"
"net/http"
"time"
"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)
//initialize rand
rand.Seed(time.Now().UnixNano())
//initialize token
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 " + config.WebServerPort)
http.Handle("/", http.FileServer(http.Dir("./web")))
http.ListenAndServe(":"+config.WebServerPort, nil)
}

View File

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

View File

@@ -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
}

View File

@@ -0,0 +1,24 @@
package main
type Routes []Route
var routes = Routes{
Route{
"Index",
"GET",
"/",
Index,
},
Route{
"GetProof",
"POST",
"/getproof",
GetProof,
},
Route{
"AnswerProof",
"POST",
"/answerproof",
AnswerProof,
},
}

View File

@@ -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.")
}
}

View File

@@ -0,0 +1,3 @@
{
"directory": "bower_components"
}

2
darkID-login-example/web/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
bower_components
node_modules

View File

@@ -0,0 +1,63 @@
'use strict';
var urlapi = "http://127.0.0.1:5010/";
// Declare app level module which depends on views, and components
angular.module('app', [
'ngRoute',
'ngMessages',
'angularBootstrapMaterial',
'ui.bootstrap',
'toastr',
'app.main',
'app.login'
]).
config(['$locationProvider', '$routeProvider', function($locationProvider, $routeProvider) {
$locationProvider.hashPrefix('!');
$routeProvider.otherwise({
redirectTo: '/login'
});
}])
.config(function(toastrConfig) {
angular.extend(toastrConfig, {
autoDismiss: false,
containerId: 'toast-container',
maxOpened: 0,
newestOnTop: true,
positionClass: 'toast-bottom-right',
preventDuplicates: false,
preventOpenDuplicates: false,
target: 'body'
});
})
.factory('httpInterceptor', function httpInterceptor() {
return {
request: function(config) {
return config;
},
requestError: function(config) {
return config;
},
response: function(res) {
return res;
},
responseError: function(res) {
return res;
}
};
})
.factory('api', function($http) {
return {
init: function() {
/*$http.defaults.headers.common['X-Access-Token'] = localStorage.getItem('block_webapp_token');
$http.defaults.headers.post['X-Access-Token'] = localStorage.getItem('block_webapp_token');*/
}
};
})
.run(function(api) {
api.init();
});

View File

@@ -0,0 +1,19 @@
{
"name": "darkID-library-login-example",
"description": "",
"version": "0.0.0",
"homepage": "",
"license": "MIT",
"private": true,
"dependencies": {
"angular": "^1.6.2",
"angular-route": "^1.6.1",
"angular-messages": "^1.6.5",
"angular-bootstrap-material": "abm#^0.1.4",
"angular-bootstrap": "^2.5.0",
"components-font-awesome": "^4.7.0",
"angular-toastr": "^2.1.1",
"cssMaterialColors": "*",
"angular-chart.js": "^1.1.1"
}
}

View File

View File

@@ -0,0 +1,74 @@
<!DOCTYPE html>
<html lang="en" ng-app="app" ng-cloak>
<head>
<meta charset="utf-8">
<title>library-login-example</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Fonts -->
<!-- in development I use googlefonts to go faster, but for the final app, I'll use downloaded fonts -->
<link href="https://fonts.googleapis.com/css?family=Open+Sans|Overpass+Mono:700|Raleway:700" rel="stylesheet">
<link rel="stylesheet" href="bower_components/components-font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="css/own.css">
<link href="bower_components/cssMaterialColors/colors.css" rel="stylesheet">
</head>
<body ng-app="webapp">
<br><br><br><br>
<div ng-view></div>
<!-- ELECTRON
Insert this line above script imports
Works for both browser and electron with the same code -->
<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
<!-- Angular js -->
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/angular-messages/angular-messages.js"></script>
<!-- Bootstrap -->
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
<!-- Bootstrap Material Design -->
<link rel="stylesheet" href="bower_components/bootstrap-material-design/dist/css/bootstrap-material-design.css">
<link rel="stylesheet" href="bower_components/bootstrap-material-design/dist/css/ripples.css">
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<script src="bower_components/angular-bootstrap-material/dist/angular-bootstrap-material.js"></script>
<!-- jQuery for Bootstrap -->
<script src="bower_components/jquery/dist/jquery.min.js"></script>
<!-- Angular Chart -->
<script src="bower_components/chart.js/dist/Chart.min.js"></script>
<script src="bower_components/angular-chart.js/dist/angular-chart.min.js"></script>
<!-- toastr -->
<link rel="stylesheet" type="text/css" href="bower_components/angular-toastr/dist/angular-toastr.css" />
<script type="text/javascript" src="bower_components/angular-toastr/dist/angular-toastr.tpls.js"></script>
<!-- app's js -->
<script src="app.js"></script>
<script src="views/main/main.js"></script>
<script src="views/login/login.js"></script>
<!-- ELECTRON
Insert this line after script imports -->
<script>if (window.module) module = window.module;</script>
</body>
</html>

View File

@@ -0,0 +1,11 @@
{
"name": "darkID-library-login-example",
"version": "1.0.0",
"description": "darkID-library-login-example",
"scripts": {
"postinstall": "bower install",
"prestart": "npm install",
"start": "http-server"
},
"license": "MIT"
}

View File

@@ -0,0 +1,43 @@
<div class="container" style="margin-top: -60px;">
<div class="row">
<div class="col-sm-4">
</div>
<div class="col-sm-4">
<div class="card">
<div class="card-body">
<h4 class="card-title">
Some platform login example
</h4>
<div class="row">
<textarea style="color:#000000;width:100%;" rows="4"
ng-model="proof.PublicKey"
placeholder="Enter here the publicKey of darkID"
></textarea>
</div>
<div class="row">
<div ng-click="getproof()" class="btn btn-block btn-raised btn-block c_indigo300 pull-right">Proof of darkID</div>
</div>
<div ng-show="proof.question">
Proof question:
<br>
<div class="row">
<textarea disabled style="color:#81C784;width:100%;" rows="4"
ng-model="proof.question"
></textarea>
</div>
<input ng-model="proof.answer" class="form-control" placeholder="Proof answer" type="text">
<div class="row">
<div ng-click="sendanswer()" class="btn btn-block btn-raised btn-block c_green300 pull-right">Send answer</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-4">
</div>
</div>
</div>

View File

@@ -0,0 +1,64 @@
'use strict';
angular.module('app.login', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/login', {
templateUrl: 'views/login/login.html',
controller: 'LoginCtrl'
});
}])
.controller('LoginCtrl', function($scope, $rootScope, $http, $routeParams, toastr) {
$rootScope.server = ""
$scope.proof = {
publicKey: "",
clear: "",
question: "",
answer: ""
};
$scope.getproof = function() {
$http({
url: urlapi + 'getproof',
method: "POST",
headers: {
"Content-Type": undefined
},
data: $scope.proof
})
.then(function(data) {
console.log("data: ");
console.log(data.data);
$scope.proof = data.data;
},
function(data) {
console.log(data);
toastr.error("error: bad darkID PublicKey")
});
};
$scope.sendanswer = function() {
$http({
url: urlapi + 'answerproof',
method: "POST",
headers: {
"Content-Type": undefined
},
data: $scope.proof
})
.then(function(data) {
console.log("data: ");
console.log(data.data);
if(data.data=="fail\n") {
toastr.error("Proof of darkID failed");
}else{
toastr.success("You are logged with darkID!");
window.location="#!/main";
}
},
function(data) {
console.log(data);
});
};
});

View File

@@ -0,0 +1,19 @@
<div class="container">
<div class="row">
<div class="col-sm-2">
</div>
<div class="col-sm-8">
<h4 class="card-title">
You are logged!
</h4>
<div class="card">
</div>
</div>
<div class="col-sm-2">
</div>
</div>
</div>

View File

@@ -0,0 +1,15 @@
'use strict';
angular.module('app.main', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/main', {
templateUrl: 'views/main/main.html',
controller: 'MainCtrl'
});
}])
.controller('MainCtrl', function($scope, $rootScope, $http) {
});