@ -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") |
@ -0,0 +1 @@ |
|||
keys.json |
@ -0,0 +1,3 @@ |
|||
{ |
|||
"directory": "bower_components" |
|||
} |
@ -0,0 +1,2 @@ |
|||
bower_components |
|||
node_modules |
@ -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(); |
|||
}); |
@ -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": "*" |
|||
} |
|||
} |
@ -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; |
|||
} |
@ -0,0 +1,5 @@ |
|||
.o_nav { |
|||
background: #000000!important; |
|||
color: #ffffff!important; |
|||
border-bottom: 2px solid #4DD0E1!important; |
|||
} |
@ -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> |
@ -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.
|
@ -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" |
|||
} |
@ -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> |
@ -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); |
|||
}); |
|||
|
|||
}; |
|||
}); |
@ -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> |
@ -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'); |
|||
}); |
|||
}; |
|||
}); |
@ -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> |
@ -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(); |
|||
}; |
|||
|
|||
}); |
@ -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> |
@ -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); |
|||
|
|||
|
|||
}; |
|||
}); |
@ -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 |
@ -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)) |
|||
} |
@ -0,0 +1,5 @@ |
|||
{ |
|||
"port": "4100", |
|||
"keysDirectory": "keys", |
|||
"server": "http://127.0.0.1:3130/" |
|||
} |
@ -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) |
|||
} |
|||
} |
@ -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 |
|||
} |
@ -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) |
|||
} |
@ -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
|
|||
} |
@ -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) |
|||
} |
@ -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 |
|||
} |
@ -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) |
|||
} |
@ -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 |
|||
} |
@ -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, |
|||
}, |
|||
} |
@ -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"}' |
@ -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 |
@ -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 |
@ -0,0 +1,8 @@ |
|||
{ |
|||
"ip": "127.0.0.1", |
|||
"port": "3130", |
|||
"mongodb": { |
|||
"ip": "127.0.0.1:27017", |
|||
"database": "serverIDsigner" |
|||
} |
|||
} |
@ -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) |
|||
} |
|||
} |
@ -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) |
|||
} |
@ -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))) |
|||
} |
@ -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 |
|||
} |
@ -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) |
|||
} |
@ -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 |
|||
} |
@ -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) |
|||
} |
@ -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 |
|||
} |
@ -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, |
|||
}, |
|||
} |
@ -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"}' |
@ -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.") |
|||
} |
|||
} |
@ -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) |
|||
} |