Browse Source

started darkID

master
arnaucode 6 years ago
parent
commit
5a3d2a5944
56 changed files with 2163 additions and 0 deletions
  1. +59
    -0
      README.md
  2. +1
    -0
      clientApp/.gitignore
  3. +3
    -0
      clientApp/GUI/.bowerrc
  4. +2
    -0
      clientApp/GUI/.gitignore
  5. +84
    -0
      clientApp/GUI/app.js
  6. +18
    -0
      clientApp/GUI/bower.json
  7. +14
    -0
      clientApp/GUI/css/bootstrapMaterial-dark-overwrite.css
  8. +5
    -0
      clientApp/GUI/css/own.css
  9. BIN
      clientApp/GUI/img/darkID-logo-black.png
  10. BIN
      clientApp/GUI/img/darkID-logo-white.png
  11. BIN
      clientApp/GUI/img/darkID-logo.xcf
  12. BIN
      clientApp/GUI/img/darkID-logo01.png
  13. BIN
      clientApp/GUI/img/darkID-logo02.png
  14. +69
    -0
      clientApp/GUI/index.html
  15. +72
    -0
      clientApp/GUI/main.js
  16. +15
    -0
      clientApp/GUI/package.json
  17. +32
    -0
      clientApp/GUI/views/login/login.html
  18. +62
    -0
      clientApp/GUI/views/login/login.js
  19. +53
    -0
      clientApp/GUI/views/main/main.html
  20. +61
    -0
      clientApp/GUI/views/main/main.js
  21. +35
    -0
      clientApp/GUI/views/navbar.html
  22. +24
    -0
      clientApp/GUI/views/navbar.js
  23. +33
    -0
      clientApp/GUI/views/signup/signup.html
  24. +19
    -0
      clientApp/GUI/views/signup/signup.js
  25. +5
    -0
      clientApp/README.md
  26. +173
    -0
      clientApp/clientAppRESTFunctions.go
  27. +5
    -0
      clientApp/config.json
  28. +15
    -0
      clientApp/errors.go
  29. +47
    -0
      clientApp/keys.go
  30. +24
    -0
      clientApp/log.go
  31. +34
    -0
      clientApp/main.go
  32. +54
    -0
      clientApp/ownrsa/prime.go
  33. +229
    -0
      clientApp/ownrsa/rsa.go
  34. +22
    -0
      clientApp/readConfig.go
  35. +47
    -0
      clientApp/restConfig.go
  36. +42
    -0
      clientApp/restRoutes.go
  37. +20
    -0
      clientApp/testUser.sh
  38. BIN
      documentation/darkID-network.png
  39. +1
    -0
      documentation/darkID-network.xml
  40. BIN
      documentation/screenshot01.png
  41. BIN
      documentation/screenshot02.png
  42. +11
    -0
      runTmuxTestPeers.sh
  43. +5
    -0
      serverIDsigner/README.md
  44. +8
    -0
      serverIDsigner/config.json
  45. +15
    -0
      serverIDsigner/errors.go
  46. +24
    -0
      serverIDsigner/log.go
  47. +49
    -0
      serverIDsigner/main.go
  48. +26
    -0
      serverIDsigner/mongoOperations.go
  49. +54
    -0
      serverIDsigner/ownrsa/prime.go
  50. +228
    -0
      serverIDsigner/ownrsa/rsa.go
  51. +26
    -0
      serverIDsigner/readConfig.go
  52. +47
    -0
      serverIDsigner/restConfig.go
  53. +36
    -0
      serverIDsigner/restRoutes.go
  54. +20
    -0
      serverIDsigner/testUser.sh
  55. +49
    -0
      serverIDsigner/tokens.go
  56. +186
    -0
      serverIDsigner/userRESTFunctions.go

+ 59
- 0
README.md

@ -0,0 +1,59 @@
# darkID
Blockchain based anonymous distributed ID system
### Main concept
The objective is to guarantee a decentralized login system, but making sure that registered users are real ones and there are no bots generating large amounts of accounts. Only the verified (by email or phone) users can generate an anonymous ID (the Public-Key blind signed).
![screenshot](https://raw.githubusercontent.com/arnaucode/darkID/master/documentation/screenshot01.png "screenshot")
![screenshot](https://raw.githubusercontent.com/arnaucode/darkID/master/documentation/screenshot02.png "screenshot")
## How it works?
#### Network infrastructure
![network](https://raw.githubusercontent.com/arnaucode/darkID/master/documentation/darkID-network.png "network")
#### Step by step process
1. Once all the nodes of the network are running, a new user can connect to the server-ID-signer.
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 Ethereum 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 Ethereum 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
https://en.wikipedia.org/wiki/RSA_cryptosystem
- Public parameters: (e, n)
- Private parameters: (d, p, q, phi, sigma)
- Public-Key = (e, n)
- Private-Key = (d, n)
- Encryption:
![rsa](https://wikimedia.org/api/rest_v1/media/math/render/svg/fbfc70524a1ad983e6f3aac51226b9ca92fefb10 "rsa")
- Decryption:
![rsa](https://wikimedia.org/api/rest_v1/media/math/render/svg/10227461ee5f4784484f082d744ba5b8c468668c "rsa")
##### Blind signature process
https://en.wikipedia.org/wiki/Blind_signature
- m is the message (in our case, is the Public-Key of the user to be blinded)
![rsa](https://wikimedia.org/api/rest_v1/media/math/render/svg/a59b57fa153c8b327605672caadb0ecf59e5795a "rsa")
- server-ID-signer blind signs m'
![rsa](https://wikimedia.org/api/rest_v1/media/math/render/svg/e726b003ff1649f9254032cffae42d80577da787 "rsa")
- user can unblind m, to get m signed
![rsa](https://wikimedia.org/api/rest_v1/media/math/render/svg/e96fad0e1d46ec4c55986d1c8fc84e8c44259ecc "rsa")
- This works because RSA keys satisfy this equation
![rsa](https://wikimedia.org/api/rest_v1/media/math/render/svg/d6bd21fb4e25c311df07b50c313a248d978c3212 "rsa") and this ![rsa](https://wikimedia.org/api/rest_v1/media/math/render/svg/c13170a26e031125b417f22644fb64384c04eea7 "rsa")

+ 1
- 0
clientApp/.gitignore

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

+ 3
- 0
clientApp/GUI/.bowerrc

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

+ 2
- 0
clientApp/GUI/.gitignore

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

+ 84
- 0
clientApp/GUI/app.js

@ -0,0 +1,84 @@
'use strict';
//var urlapi = "http://127.0.0.1:3130/";
var clientapi = "http://127.0.0.1:4100/";
// Declare app level module which depends on views, and components
angular.module('app', [
'ngRoute',
'ngMessages',
'angularBootstrapMaterial',
'ui.bootstrap',
'toastr',
'app.navbar',
'app.main',
'app.signup',
'app.login'
]).
config(['$locationProvider', '$routeProvider', function($locationProvider, $routeProvider) {
$locationProvider.hashPrefix('!');
if ((localStorage.getItem('darkID_token'))) {
console.log(window.location.hash);
if ((window.location.hash === '#!/login') || (window.location.hash === '#!/signup')) {
window.location = '#!/main';
}
$routeProvider.otherwise({
redirectTo: '/main'
});
} else {
if ((window.location !== '#!/login') || (window.location !== '#!/signup')) {
console.log('app, user no logged');
localStorage.removeItem('darkID_token');
localStorage.removeItem('darkID_userdata');
window.location = '#!/login';
$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();
});

+ 18
- 0
clientApp/GUI/bower.json

@ -0,0 +1,18 @@
{
"name": "darkID-clientApp",
"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": "*"
}
}

+ 14
- 0
clientApp/GUI/css/bootstrapMaterial-dark-overwrite.css

@ -0,0 +1,14 @@
body {
/*background: #15191e!important;*/
background: #000000!important;
color: #ffffff!important;
}
.card {
/*background: #1f262d!important;*/
/*background: #15191e!important;
color: #ffffff!important;*/
/*border: 1px solid #ffffff!important;*/
background: #000000!important;
color: #ffffff!important;
}

+ 5
- 0
clientApp/GUI/css/own.css

@ -0,0 +1,5 @@
.o_nav {
background: #000000!important;
color: #ffffff!important;
border-bottom: 2px solid #4DD0E1!important;
}

BIN
clientApp/GUI/img/darkID-logo-black.png

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

BIN
clientApp/GUI/img/darkID-logo-white.png

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

BIN
clientApp/GUI/img/darkID-logo.xcf


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

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

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

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

+ 69
- 0
clientApp/GUI/index.html

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html lang="en" ng-app="app" ng-cloak>
<head>
<meta charset="utf-8">
<title>darkID</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="img/darkID-logo-black.png">
<link rel="stylesheet" href="bower_components/components-font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="css/own.css">
<link rel="stylesheet" href="css/bootstrapMaterial-dark-overwrite.css">
<link href="bower_components/cssMaterialColors/colors.css" rel="stylesheet">
</head>
<body ng-app="webapp">
<div ng-include="'views/navbar.html'"></div>
<br><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>
<!-- 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/navbar.js"></script>
<script src="views/main/main.js"></script>
<script src="views/signup/signup.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>

+ 72
- 0
clientApp/GUI/main.js

@ -0,0 +1,72 @@
const electron = require('electron')
// Module to control application life.
const app = electron.app
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow
const Tray = electron.Tray
const Menu = electron.Menu
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 850,
height: 600,
icon: 'img/darkID-logo-white.png'
})
tray = new Tray('img/darkID-logo-white.png')
const contextMenu = Menu.buildFromTemplate([
{label: 'Obre la finestra', type: 'radio'},
{label: 'javascript madness', type: 'radio'},
{label: 'Tanca', type: 'radio'}
//{label: 'Tanca', type: 'radio', checked: true}
])
tray.setToolTip('Panopticon, projectNSA')
tray.setContextMenu(contextMenu)
mainWindow.setMenu(null);
// and load the index.html of the app.
mainWindow.loadURL(`file://${__dirname}/index.html`)
// Open the DevTools.
//mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

+ 15
- 0
clientApp/GUI/package.json

@ -0,0 +1,15 @@
{
"name": "darkID-clientApp",
"version": "1.0.0",
"description": "frontend desktop app for darkID",
"main": "main.js",
"scripts": {
"postinstall": "bower install",
"prestart": "npm install",
"start": "electron ."
},
"devDependencies": {
"electron-prebuilt": "^1.2.0"
},
"license": "MIT"
}

+ 32
- 0
clientApp/GUI/views/login/login.html

@ -0,0 +1,32 @@
<div class="container" style="margin-top: -80px;">
<div class="row">
<div class="col-sm-3">
</div>
<div class="col-sm-6">
<div class="card">
<img src="img/darkID-logo01.png" class="img-responsive" />
<div class="card-body">
<h4 class="card-title">
darkID
</h4>
<input ng-model="user.email" class="form-control" placeholder="Email" type="text">
<input ng-model="user.password" class="form-control" placeholder="Password" type="password">
<div class="row">
<div class="col-sm-6">
<a href="#!/signup" class="btn btn-raised btn-block c_o_pink300">Signup</a>
</div>
<div class="col-sm-6">
<div ng-click="login()" class="btn btn-raised btn-block c_o_cyan300 pull-right">Login</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-3">
</div>
</div>
</div>

+ 62
- 0
clientApp/GUI/views/login/login.js

@ -0,0 +1,62 @@
'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.user = {};
//set server in goclient
$http.get(clientapi + 'getserver')
.then(function(data) {
console.log("data: ");
console.log(data.data);
$rootScope.server = data.data;
localStorage.setItem("darkID_server", JSON.stringify($rootScope.server));
console.log("server", $rootScope.server);
}, function(data) {
console.log('data error');
});
$scope.login = function() {
console.log('Doing login', $scope.user);
console.log($rootScope.server + "login");
//
$http({
url: $rootScope.server + 'login',
method: "POST",
headers: {
"Content-Type": undefined
},
data: $scope.user
})
.then(function(data) {
console.log("data: ");
console.log(data.data);
if (data.data.token) {
localStorage.setItem("darkID_token", data.data.token);
localStorage.setItem("darkID_user", JSON.stringify(data.data));
window.location.reload();
} else {
console.log("login failed");
toastr.error('Login failed');
}
},
function(data) {
console.log(data);
});
};
});

+ 53
- 0
clientApp/GUI/views/main/main.html

@ -0,0 +1,53 @@
<div class="container">
<div class="row">
<div class="col-sm-2">
</div>
<div class="col-sm-8">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-sm-6">
<div ng-click="" class="btn btn-raised btn-block c_o_green300">Use ID</div>
</div>
<div class="col-sm-6">
<div ng-click="newID()" class="btn btn-raised btn-block c_o_pink300">Create new ID</div>
</div>
</div>
</div>
<hr>
<div class="card-body">
<h4 class="card-title">
My IDs
</h4>
<div class="row" style="height:200px;" ng-repeat="id in ids">
<div class="col-sm-6">
Public Key: {{id.pubK}}
<!--<br> Private Key: {{id.privK}}-->
<br> Date of creation: {{id.date}}
<!--<br> {{id.pubKSigned}}-->
<br>
<br><br>
</div>
<div class="col-sm-6">
<div class="pull-right">
<span class="badge c_o_red300" ng-show="!id.verified">Not verified</span>
<span class="badge c_o_green300" ng-show="id.verified">Verified</span>
</div>
<div class="pull-right">
<span class="badge c_o_orange300" ng-show="!id.pubKSigned">Not signed</span>
<span class="badge c_o_green300" ng-show="id.pubKSigned">Signed</span>
</div>
<div ng-click="blindAndSendToSign(id.pubK)" ng-show="!id.pubKSigned" class="btn btn-sm btn-raised c_o_cyan300 pull-right">Send to serverIDsigner</div>
<div ng-click="verify(id.pubK)" ng-show="!id.verified"class="btn btn-sm btn-raised c_o_deepPurple300 pull-right">Verify</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-2">
</div>
</div>
</div>

+ 61
- 0
clientApp/GUI/views/main/main.js

@ -0,0 +1,61 @@
'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) {
$rootScope.server = JSON.parse(localStorage.getItem("darkID_server"));
$scope.ids = [];
$http.get(clientapi + 'ids')
.then(function(data) {
console.log('data success');
console.log(data);
$scope.ids = data.data;
}, function(data) {
console.log('data error');
});
$scope.newID = function() {
$http.get(clientapi + 'newid')
.then(function(data) {
console.log('data success');
console.log(data);
$scope.ids = data.data;
}, function(data) {
console.log('data error');
});
};
$scope.blindAndSendToSign = function(pubK) {
$http.get(clientapi + 'blindandsendtosign/' + pubK)
.then(function(data) {
console.log('data success');
console.log(data);
$scope.ids = data.data;
}, function(data) {
console.log('data error');
});
};
$scope.verify = function(pubK) {
$http.get(clientapi + 'verify/' + pubK)
.then(function(data) {
console.log('data success');
console.log(data);
$scope.ids = data.data;
}, function(data) {
console.log('data error');
});
};
});

+ 35
- 0
clientApp/GUI/views/navbar.html

@ -0,0 +1,35 @@
<div ng-controller="NavbarCtrl" ng-show="user">
<nav class="navbar navbar-fixed-top o_nav">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-responsive-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/" title="darkID">
<img src="img/darkID-logo-white.png" style="width:30px;height:30px;display:inline;" alt=""> <b>darkID</b>
</a>
</div>
<div class="navbar-collapse collapse navbar-responsive-collapse">
<ul class="nav navbar-nav navbar-right">
<li>
<a title="serverIDsigner">
<i title="Server" class="fa fa-server fa-1x"></i> {{server}}
</a>
</li>
<li>
<a href="">
<i title="User" class="fa fa-user fa-1x"></i> {{user.email}}
</a>
</li>
<li>
<a href="" ng-click="logout()">
<i title="Exit" class="fa fa-power-off fa-1x"></i>
</a>
</li>
</ul>
</div>
</div>
</nav>
</div>

+ 24
- 0
clientApp/GUI/views/navbar.js

@ -0,0 +1,24 @@
'use strict';
angular.module('app.navbar', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/navbar', {
templateUrl: 'views/navbar.html',
controller: 'NavbarCtrl'
});
}])
.controller('NavbarCtrl', function($scope, $rootScope, $http, $routeParams, $location) {
$rootScope.server = JSON.parse(localStorage.getItem("darkID_server"));
$scope.user = JSON.parse(localStorage.getItem("darkID_user"));
$scope.logout = function() {
localStorage.removeItem("darkID_token");
localStorage.removeItem("darkID_user");
localStorage.removeItem("darkID_server");
window.location.reload();
};
});

+ 33
- 0
clientApp/GUI/views/signup/signup.html

@ -0,0 +1,33 @@
<div class="container" style="margin-top: -80px;">
<div class="row">
<div class="col-sm-3">
</div>
<div class="col-sm-6">
<div class="card">
<img src="img/darkID-logo01.png" class="img-responsive" />
<div class="card-body">
<h4 class="card-title">
darkID
</h4>
<input ng-model="user.email" class="form-control" placeholder="Email" type="text">
<input ng-model="user.password" class="form-control" placeholder="Password" type="password">
<input ng-model="user.phone" class="form-control" placeholder="Phone" type="text">
<div class="row">
<div class="col-sm-6">
<a href="#!/login" class="btn btn-raised btn-block c_o_blue300">Cancel</a>
</div>
<div class="col-sm-6">
<div ng-click="signup()" class="btn btn-raised btn-block c_o_pink300 pull-right">Signup</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-3">
</div>
</div>
</div>

+ 19
- 0
clientApp/GUI/views/signup/signup.js

@ -0,0 +1,19 @@
'use strict';
angular.module('app.signup', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/signup', {
templateUrl: 'views/signup/signup.html',
controller: 'SignupCtrl'
});
}])
.controller('SignupCtrl', function($scope, $http, $routeParams) {
$scope.user = {};
$scope.doSignup = function() {
console.log('Doing signup', $scope.user);
};
});

+ 5
- 0
clientApp/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

+ 173
- 0
clientApp/clientAppRESTFunctions.go

@ -0,0 +1,173 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"time"
ownrsa "./ownrsa"
"github.com/fatih/color"
"github.com/gorilla/mux"
)
//TODO use rsa library instead own rsa functions
func Index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "serverIDsigner")
}
func GetServer(w http.ResponseWriter, r *http.Request) {
color.Green(config.Server)
fmt.Fprintln(w, config.Server)
}
func IDs(w http.ResponseWriter, r *http.Request) {
//read the keys stored in /keys directory
keys := readKeys("keys.json")
saveKeys(keys, "keys.json")
jResp, err := json.Marshal(keys)
check(err)
fmt.Fprintln(w, string(jResp))
}
func NewID(w http.ResponseWriter, r *http.Request) {
//generate RSA keys pair
newKey := ownrsa.GenerateKeyPair()
key := ownrsa.PackKey(newKey)
key.Date = time.Now()
fmt.Println(key)
keys := readKeys("keys.json")
keys = append(keys, key)
saveKeys(keys, "keys.json")
jResp, err := json.Marshal(keys)
check(err)
fmt.Fprintln(w, string(jResp))
}
type AskBlindSign struct {
M string `json:"m"`
}
func BlindAndSendToSign(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
packPubK := vars["pubK"]
color.Green(packPubK)
//read the keys stored in /keys directory
keys := readKeys("keys.json")
var key ownrsa.RSA
//search for complete key
for _, k := range keys {
if k.PubK == packPubK {
key = ownrsa.UnpackKey(k)
}
}
//blind the key.PubK
var m []int
//convert packPubK to []bytes
mBytes := []byte(packPubK)
for _, byte := range mBytes {
m = append(m, int(byte))
}
rVal := 101
blinded := ownrsa.Blind(m, rVal, key.PubK, key.PrivK)
fmt.Println(blinded)
//convert blinded to string
var askBlindSign AskBlindSign
askBlindSign.M = ownrsa.ArrayIntToString(blinded, "_")
//send to the serverIDsigner the key.PubK blinded
color.Green(askBlindSign.M)
body := new(bytes.Buffer)
json.NewEncoder(body).Encode(askBlindSign)
res, err := http.Post(config.Server+"blindsign", "application/json", body)
check(err)
fmt.Println(res)
decoder := json.NewDecoder(res.Body)
//var sigmaString string
err = decoder.Decode(&askBlindSign)
if err != nil {
panic(err)
}
defer r.Body.Close()
fmt.Println("sigmaString")
fmt.Println(askBlindSign)
sigma := ownrsa.StringToArrayInt(askBlindSign.M, "_")
fmt.Println(sigma)
//get the serverIDsigner pubK
serverPubK := getServerPubK(config.Server)
//unblind the response
mSigned := ownrsa.Unblind(sigma, rVal, serverPubK)
fmt.Print("mSigned: ")
fmt.Println(mSigned)
verified := ownrsa.Verify(m, mSigned, serverPubK)
fmt.Println(verified)
var iKey int
for i, k := range keys {
if k.PubK == packPubK {
iKey = i
//save to k the key updated
k.PubKSigned = ownrsa.ArrayIntToString(mSigned, "_")
k.Verified = verified
}
fmt.Println(k)
}
keys[iKey].PubKSigned = ownrsa.ArrayIntToString(mSigned, "_")
keys[iKey].Verified = verified
fmt.Println(keys)
saveKeys(keys, "keys.json")
jResp, err := json.Marshal(keys)
check(err)
fmt.Fprintln(w, string(jResp))
}
func Verify(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
packPubK := vars["pubK"]
color.Green(packPubK)
//read the keys stored in /keys directory
keys := readKeys("keys.json")
var key ownrsa.PackRSA
//search for complete key
for _, k := range keys {
if k.PubK == packPubK {
key = k
}
}
//get the serverIDsigner pubK
serverPubK := getServerPubK(config.Server)
m := ownrsa.StringToArrayInt(key.PubK, "_")
mSigned := ownrsa.StringToArrayInt(key.PubKSigned, "_")
verified := ownrsa.Verify(m, mSigned, serverPubK)
fmt.Println(verified)
for _, k := range keys {
if k.PubK == packPubK {
//save to k the key updated
k.PubKSigned = ownrsa.ArrayIntToString(mSigned, "_")
k.Verified = verified
}
}
saveKeys(keys, "keys.json")
jResp, err := json.Marshal(keys)
check(err)
fmt.Fprintln(w, string(jResp))
}

+ 5
- 0
clientApp/config.json

@ -0,0 +1,5 @@
{
"port": "4100",
"keysDirectory": "keys",
"server": "http://127.0.0.1:3130/"
}

+ 15
- 0
clientApp/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)
}
}

+ 47
- 0
clientApp/keys.go

@ -0,0 +1,47 @@
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
ownrsa "./ownrsa"
"github.com/fatih/color"
)
func readKeys(path string) []ownrsa.PackRSA {
var keys []ownrsa.PackRSA
file, err := ioutil.ReadFile(path)
check(err)
content := string(file)
json.Unmarshal([]byte(content), &keys)
return keys
}
func saveKeys(keys []ownrsa.PackRSA, path string) {
jsonKeys, err := json.Marshal(keys)
check(err)
err = ioutil.WriteFile(path, jsonKeys, 0644)
check(err)
}
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
clientApp/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)
}

+ 34
- 0
clientApp/main.go

@ -0,0 +1,34 @@
package main
import (
"fmt"
"log"
"net/http"
"github.com/fatih/color"
"github.com/gorilla/handlers"
)
func main() {
color.Blue("Starting darkID clientApp")
readConfig("config.json")
fmt.Println(config)
//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 electron app
}

+ 54
- 0
clientApp/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)
}

+ 229
- 0
clientApp/ownrsa/rsa.go

@ -0,0 +1,229 @@
package ownrsa
import (
"errors"
"fmt"
"math/big"
"math/rand"
"strconv"
"strings"
"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
}
type PackRSA struct {
PubK string `json:"pubK"`
PrivK string `json:"privK"`
Date time.Time `json:"date"`
PubKSigned string `json:"pubKSigned"`
Verified bool `json:"verified"`
}
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, 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, privK.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
}
func PackKey(k RSA) PackRSA {
var p PackRSA
p.PubK = k.PubK.E.String() + "," + k.PubK.N.String()
p.PrivK = k.PrivK.D.String() + "," + k.PrivK.N.String()
return p
}
func UnpackKey(p PackRSA) RSA {
var k RSA
var ok bool
k.PubK.E, ok = new(big.Int).SetString(strings.Split(p.PubK, ",")[0], 10)
k.PubK.N, ok = new(big.Int).SetString(strings.Split(p.PubK, ",")[1], 10)
k.PrivK.D, ok = new(big.Int).SetString(strings.Split(p.PrivK, ",")[0], 10)
k.PrivK.N, ok = new(big.Int).SetString(strings.Split(p.PrivK, ",")[1], 10)
if !ok {
fmt.Println("error on Unpacking Keys")
}
return k
}
func ArrayIntToString(a []int, delim string) string {
return strings.Trim(strings.Replace(fmt.Sprint(a), " ", delim, -1), "[]")
}
func StringToArrayInt(s string, delim string) []int {
var a []int
arrayString := strings.Split(s, delim)
for _, s := range arrayString {
i, err := strconv.Atoi(s)
if err != nil {
fmt.Println(err)
}
a = append(a, i)
}
return a
}

+ 22
- 0
clientApp/readConfig.go

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

+ 47
- 0
clientApp/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
}

+ 42
- 0
clientApp/restRoutes.go

@ -0,0 +1,42 @@
package main
type Routes []Route
var routes = Routes{
Route{
"Index",
"GET",
"/",
Index,
},
Route{
"GetServer",
"GET",
"/getserver",
GetServer,
},
Route{
"IDs",
"GET",
"/ids",
IDs,
},
Route{
"NewID",
"GET",
"/newid",
NewID,
},
Route{
"BlindAndSendToSign",
"GET",
"/blindandsendtosign/{pubK}",
BlindAndSendToSign,
},
Route{
"Verify",
"GET",
"/verify/{pubK}",
Verify,
},
}

+ 20
- 0
clientApp/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"}'

BIN
documentation/darkID-network.png

Before After
Width: 351  |  Height: 381  |  Size: 39 KiB

+ 1
- 0
documentation/darkID-network.xml
File diff suppressed because it is too large
View File


BIN
documentation/screenshot01.png

Before After
Width: 854  |  Height: 628  |  Size: 68 KiB

BIN
documentation/screenshot02.png

Before After
Width: 852  |  Height: 628  |  Size: 49 KiB

+ 11
- 0
runTmuxTestPeers.sh

@ -0,0 +1,11 @@
SESSION='darkIDtest'
tmux new-session -d -s $SESSION
tmux split-window -d -t 0 -v
tmux split-window -d -t 0 -h
tmux send-keys -t 0 'cd serverIDsigner && go run *.go' enter
tmux send-keys -t 1 'cd clientApp && go run *.go' enter
tmux send-keys -t 2 'cd clientApp/GUI && http-server' enter
tmux attach

+ 5
- 0
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

+ 8
- 0
serverIDsigner/config.json

@ -0,0 +1,8 @@
{
"ip": "127.0.0.1",
"port": "3130",
"mongodb": {
"ip": "127.0.0.1:27017",
"database": "serverIDsigner"
}
}

+ 15
- 0
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)
}
}

+ 24
- 0
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)
}

+ 49
- 0
serverIDsigner/main.go

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

+ 26
- 0
serverIDsigner/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
}

+ 54
- 0
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)
}

+ 228
- 0
serverIDsigner/ownrsa/rsa.go

@ -0,0 +1,228 @@
package ownrsa
import (
"errors"
"fmt"
"math/big"
"math/rand"
"strconv"
"strings"
"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
}
type PackRSA struct {
PubK string `json:"pubK"`
PrivK string `json:"privK"`
Date time.Time `json:"date"`
PubKSigned string `json:"pubKSigned"`
}
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, 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, privK.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
}
func PackKey(k RSA) PackRSA {
var p PackRSA
p.PubK = k.PubK.E.String() + "," + k.PubK.N.String()
p.PrivK = k.PrivK.D.String() + "," + k.PrivK.N.String()
return p
}
func UnpackKey(p PackRSA) RSA {
var k RSA
var ok bool
k.PubK.E, ok = new(big.Int).SetString(strings.Split(p.PubK, ",")[0], 10)
k.PubK.N, ok = new(big.Int).SetString(strings.Split(p.PubK, ",")[1], 10)
k.PrivK.D, ok = new(big.Int).SetString(strings.Split(p.PrivK, ",")[0], 10)
k.PrivK.N, ok = new(big.Int).SetString(strings.Split(p.PrivK, ",")[1], 10)
if !ok {
fmt.Println("error on Unpacking Keys")
}
return k
}
func ArrayIntToString(a []int, delim string) string {
return strings.Trim(strings.Replace(fmt.Sprint(a), " ", delim, -1), "[]")
}
func StringToArrayInt(s string, delim string) []int {
var a []int
arrayString := strings.Split(s, delim)
for _, s := range arrayString {
i, err := strconv.Atoi(s)
if err != nil {
fmt.Println(err)
}
a = append(a, i)
}
return a
}

+ 26
- 0
serverIDsigner/readConfig.go

@ -0,0 +1,26 @@
package main
import (
"encoding/json"
"io/ioutil"
)
//Config reads the config
type Config struct {
IP string `json:"ip"`
Port string `json:"port"`
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)
}

+ 47
- 0
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
}

+ 36
- 0
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,
},
}

+ 20
- 0
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 '{"m": "hola"}'
echo "serverIDsigner response:"
BLINDSIGNED=$(curl -X POST http://127.0.0.1:3130/blindsign -d '{"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
serverIDsigner/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.")
}
}

+ 186
- 0
serverIDsigner/userRESTFunctions.go

@ -0,0 +1,186 @@
package main
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/fatih/color"
"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
jResp, err := json.Marshal(serverRSA.PubK)
if err != nil {
panic(err)
}
fmt.Fprintln(w, string(jResp))
}
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()
//TODO check if the user password exists in the database
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) {
decoder := json.NewDecoder(r.Body)
var askBlindSign AskBlindSign
err := decoder.Decode(&askBlindSign)
if err != nil {
panic(err)
}
defer r.Body.Close()
color.Red(askBlindSign.M)
fmt.Println(askBlindSign)
/*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))
}*/
m := ownrsa.StringToArrayInt(askBlindSign.M, "_")
sigma := ownrsa.BlindSign(m, 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)
sigmaString := ownrsa.ArrayIntToString(sigma, "_")
askBlindSign.M = sigmaString
jResp, err := json.Marshal(askBlindSign)
if err != nil {
panic(err)
}
fmt.Fprintln(w, string(jResp))
}
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)
}

Loading…
Cancel
Save