Begin work on converting to bitcore 0.8.
This commit is contained in:
parent
9e54ccdae3
commit
92405b3a90
|
@ -1,22 +1,49 @@
|
||||||
var request = require('request');
|
var request = require('request');
|
||||||
var bitauth = require('../lib/bitauth');
|
var BitAuth = require('../lib/bitauth');
|
||||||
|
var bitauth = new BitAuth();
|
||||||
|
|
||||||
// These can be generated with bitauth.generateSin()
|
// These can be generated with bitauth.generateIdentity()
|
||||||
var keys = {
|
var keys = {
|
||||||
alice: '38f93bdda21a5c4a7bae4eb75bb7811cbc3eb627176805c1009ff2099263c6ad',
|
alice: 'L1i9Xe5gVdg78Cc1U1aCUGG8ZjZ5qieL9axpmKxwjak8FFbSnfYQ',
|
||||||
bob: '09880c962437080d72f72c8c63a69efd65d086c9e7851a87b76373eb6ce9aab5'
|
bob: 'KxpMscE4vhkdTbVHFDuWjYh73APHGATLy1ZndDdL5jCy5d9Kv166'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log('Alice:')
|
||||||
|
var alice = new BitAuth();
|
||||||
|
alice.generateIdentity();
|
||||||
|
console.log( alice._keypair.privkey.toString() );
|
||||||
|
console.log( alice._keypair.pubkey.toString() );
|
||||||
|
console.log( 'pubDER:' , alice._keypair.pubkey.toDER().toString('hex') );
|
||||||
|
console.log( alice._identity.toString() );
|
||||||
|
|
||||||
|
console.log('Bob:')
|
||||||
|
var bob = new BitAuth();
|
||||||
|
bob.generateIdentity();
|
||||||
|
console.log( bob._keypair.privkey.toString() );
|
||||||
|
console.log( bob._keypair.pubkey.toString() );
|
||||||
|
console.log( 'pubDER:' , bob._keypair.pubkey.toDER().toString('hex') );
|
||||||
|
console.log( bob._identity.toString() );
|
||||||
|
|
||||||
|
var keys = {
|
||||||
|
alice: alice,
|
||||||
|
bob: bob
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('keys', keys);
|
||||||
|
|
||||||
// GET
|
// GET
|
||||||
|
|
||||||
for(k in keys) {
|
for(k in keys) {
|
||||||
|
|
||||||
|
console.log( keys[k]._keypair.privkey )
|
||||||
|
|
||||||
var url = 'http://localhost:3000/user';
|
var url = 'http://localhost:3000/user';
|
||||||
var dataToSign = url;
|
var dataToSign = url;
|
||||||
var options = {
|
var options = {
|
||||||
url: url,
|
url: url,
|
||||||
headers: {
|
headers: {
|
||||||
'x-identity': bitauth.getPublicKeyFromPrivateKey(keys[k]),
|
'x-identity': keys[k]._identity.toString() ,
|
||||||
'x-signature': bitauth.sign(dataToSign, keys[k])
|
'x-signature': bitauth.sign( dataToSign , keys[k]._keypair )
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,8 +68,8 @@ for(k in keys) {
|
||||||
var options = {
|
var options = {
|
||||||
url: url,
|
url: url,
|
||||||
headers: {
|
headers: {
|
||||||
'x-identity': bitauth.getPublicKeyFromPrivateKey(keys[k]),
|
'x-identity': keys[k]._identity.toString(),
|
||||||
'x-signature': bitauth.sign(dataToSign, keys[k])
|
'x-signature': bitauth.sign( dataToSign , keys[k]._keypair )
|
||||||
},
|
},
|
||||||
json: data
|
json: data
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,26 +4,27 @@ var rawBody = require('../lib/middleware/rawbody');
|
||||||
var bitauth = require('../lib/middleware/bitauth');
|
var bitauth = require('../lib/middleware/bitauth');
|
||||||
|
|
||||||
var users = {
|
var users = {
|
||||||
'Tf7UNQnxB8SccfoyZScQmb34V2GdEtQkzDz': {name: 'Alice'},
|
'Tf7Rm1ETjHRiUWZoJTXwVA3nXEQiih35vp3': {name: 'Alice'},
|
||||||
'Tf22EUFxHWh4wmA3sDuw151W5C5g32jgph2': {name: 'Bob'}
|
'TexKrSDV87wMhVzTUda5gz92L2joMuwo17m': {name: 'Bob'}
|
||||||
};
|
};
|
||||||
|
|
||||||
var pizzas = [];
|
var pizzas = [];
|
||||||
|
|
||||||
var app = express();
|
var app = express();
|
||||||
app.use(rawBody);
|
app.use(rawBody);
|
||||||
app.use(bodyParser());
|
app.use(bodyParser.raw());
|
||||||
|
|
||||||
|
|
||||||
app.get('/user', bitauth, function(req, res) {
|
app.get('/user', bitauth, function(req, res) {
|
||||||
if(!req.sin || !users[req.sin]) return res.send(401, {error: 'Unauthorized'});
|
console.log('req.identity' , req.identity);
|
||||||
res.send(200, users[req.sin]);
|
|
||||||
|
if(!req.identity || !users[req.identity]) return res.send(401, {error: 'Unauthorized'});
|
||||||
|
res.send(200, users[req.identity]);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/pizzas', bitauth, function(req, res) {
|
app.post('/pizzas', bitauth, function(req, res) {
|
||||||
if(!req.sin || !users[req.sin]) return res.send(401, {error: 'Unauthorized'});
|
if(!req.identity || !users[req.identity]) return res.send(401, {error: 'Unauthorized'});
|
||||||
var pizza = req.body;
|
var pizza = req.body;
|
||||||
pizza.owner = users[req.sin].name;
|
pizza.owner = users[req.identity].name;
|
||||||
pizzas.push(pizza);
|
pizzas.push(pizza);
|
||||||
res.send(200, req.body);
|
res.send(200, req.body);
|
||||||
});
|
});
|
||||||
|
|
9
index.js
9
index.js
|
@ -1,9 +1,12 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
// get base functionality
|
// get base functionality
|
||||||
var bitauth = require('./lib/bitauth');
|
var BitAuth = require('./lib/bitauth');
|
||||||
|
var bitauth = new BitAuth();
|
||||||
|
|
||||||
// add node-specific encrypt/decrypt
|
// add node-specific encrypt/decrypt
|
||||||
bitauth.encrypt = require('./lib/encrypt');
|
bitauth.encrypt = require('./lib/encrypt');
|
||||||
bitauth.decrypt = require('./lib/decrypt');
|
bitauth.decrypt = require('./lib/decrypt');
|
||||||
bitauth.middleware = require('./lib/middleware/bitauth');
|
bitauth.middleware = require('./lib/middleware/bitauth');
|
||||||
|
|
||||||
module.exports = bitauth;
|
module.exports = bitauth;
|
||||||
|
|
112
lib/bitauth.js
112
lib/bitauth.js
|
@ -1,76 +1,84 @@
|
||||||
|
var util = require('util');
|
||||||
|
|
||||||
var bitcore = require('bitcore');
|
var bitcore = require('bitcore');
|
||||||
var Key = bitcore.Key;
|
var Keypair = bitcore.Keypair;
|
||||||
var SIN = bitcore.SIN;
|
var Privkey = bitcore.Privkey;
|
||||||
var SINKey = bitcore.SINKey
|
var Identity = bitcore.Identity;
|
||||||
var util = bitcore.util;
|
var Message = bitcore.Message;
|
||||||
|
var Hash = bitcore.Hash;
|
||||||
|
|
||||||
var BitAuth = {};
|
var BitAuth = function() {
|
||||||
|
this._identity = null;
|
||||||
BitAuth.generateSin = function() {
|
this._keypair = null;
|
||||||
var sk = new SINKey();
|
|
||||||
sk.generate();
|
|
||||||
return sk.storeObj();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BitAuth.getPublicKeyFromPrivateKey = function(privkey) {
|
BitAuth.prototype.generateIdentity = function( keypair ) {
|
||||||
try {
|
var self = this;
|
||||||
var key = new Key();
|
|
||||||
|
if (!keypair) var keypair = new Keypair().fromRandom();
|
||||||
|
|
||||||
key.private = new Buffer(privkey, 'hex');
|
self._keypair = keypair;
|
||||||
key.regenerateSync();
|
self._identity = new Identity().fromPubkey( self._keypair.pubkey );
|
||||||
|
|
||||||
return key.public.toString('hex');
|
return self;
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BitAuth.getSinFromPublicKey = function(pubkey) {
|
BitAuth.prototype.sign = function(data, privkey) {
|
||||||
var pubkeyHash = util.sha256ripe160(new Buffer(pubkey, 'hex'));
|
var self = this;
|
||||||
var sin = new SIN(SIN.SIN_EPHEM, pubkeyHash);
|
var signature = Message.sign( new Buffer( data ) , privkey );
|
||||||
return sin.toString();
|
return signature;
|
||||||
}
|
|
||||||
|
|
||||||
BitAuth.sign = function(data, privkey) {
|
|
||||||
var hash = util.sha256(data);
|
|
||||||
|
|
||||||
try {
|
|
||||||
var key = new Key();
|
|
||||||
key.private = new Buffer(privkey, 'hex');
|
|
||||||
return key.signSync(hash).toString('hex');
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err.stack);
|
|
||||||
console.log(err);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BitAuth.verifySignature = function(data, pubkey, signature, callback) {
|
BitAuth.prototype.getIdentityFromPublicKey = function( pubkey ) {
|
||||||
var hash = util.sha256(data);
|
var identity = new Identity( pubkey );
|
||||||
|
return identity.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
BitAuth.prototype.getPublicKeyFromPrivateKey = function( privkey ) {
|
||||||
|
var keypair = Keypair().fromString( JSON.stringify({ privkey : privkey }) );
|
||||||
|
return keypair.pubkey.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
BitAuth.prototype.getPublicKeyFromIdentity = function( identity ) {
|
||||||
|
var identity = Identity().fromString( identity );
|
||||||
|
|
||||||
|
console.log('pubkeyfromident, ident:' , identity );
|
||||||
|
|
||||||
|
return identity.toPubkey();
|
||||||
|
};
|
||||||
|
|
||||||
|
BitAuth.prototype.verifySignature = function(data, identity, signature, callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
console.log('verifySignature', identity , signature );
|
||||||
|
|
||||||
|
var pubkey = self.getPublicKeyFromIdentity( identity );
|
||||||
|
|
||||||
|
console.log('pubkey', pubkey );
|
||||||
|
|
||||||
|
var messageBuffer = new Buffer( data );
|
||||||
|
|
||||||
|
var signature = Message.sign( messageBuffer , identity._keypair );
|
||||||
|
|
||||||
|
console.log('verifySig', identity);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var key = new Key();
|
Message.verify( messageBuffer , signature , identity );
|
||||||
key.public = new Buffer(pubkey, 'hex');
|
callback();
|
||||||
key.verifySignature(hash, new Buffer(signature, 'hex'), callback);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
callback(err, false);
|
callback(err, false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
BitAuth.validateSin = function(sin, callback) {
|
BitAuth.prototype.validateIdentity = function( identity , callback ) {
|
||||||
var s = new SIN(sin);
|
var s = new Identity( identity );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
s.validate()
|
s.validate();
|
||||||
|
callback();
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
if ( callback )
|
callback(err);
|
||||||
callback(err);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if ( callback )
|
|
||||||
callback(null);
|
|
||||||
return true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = BitAuth;
|
module.exports = BitAuth;
|
||||||
|
|
|
@ -1,21 +1,25 @@
|
||||||
var bitauth = require('../bitauth');
|
var BitAuth = require('../bitauth');
|
||||||
|
var bitauth = new BitAuth();
|
||||||
|
|
||||||
|
var bitcore = require('bitcore');
|
||||||
|
var Identity = bitcore.Identity;
|
||||||
|
|
||||||
module.exports = function(req, res, next) {
|
module.exports = function(req, res, next) {
|
||||||
if(req.headers && req.headers['x-identity'] && req.headers['x-signature']) {
|
if (req.headers && req.headers['x-identity'] && req.headers['x-signature']) {
|
||||||
// Check signature is valid
|
// Check signature is valid
|
||||||
// First construct data to check signature on
|
// First construct data to check signature on
|
||||||
var fullUrl = req.protocol + '://' + req.get('host') + req.url;
|
var fullUrl = req.protocol + '://' + req.get('host') + req.url;
|
||||||
var data = fullUrl + req.rawBody;
|
var data = fullUrl + req.rawBody;
|
||||||
|
|
||||||
bitauth.verifySignature(data, req.headers['x-identity'], req.headers['x-signature'], function(err, result) {
|
bitauth.verifySignature( data , req.headers['x-identity'], req.headers['x-signature'], function(err, result) {
|
||||||
if(err || !result) {
|
if(err || !result) {
|
||||||
return res.send(400, {error: 'Invalid signature'});
|
return res.send(400, {error: 'Invalid signature'});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the SIN from the public key
|
// Get the Identity from the public key
|
||||||
var sin = bitauth.getSinFromPublicKey(req.headers['x-identity']);
|
var identity = bitauth.getIdentityFromPublicKey(req.headers['x-identity']);
|
||||||
if(!sin) return res.send(400, {error: 'Bad public key from identity'});
|
if(!identity) return res.send(400, {error: 'Bad public key from identity'});
|
||||||
req.sin = sin;
|
req.identity = identity;
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
25
package.json
25
package.json
|
@ -1,15 +1,11 @@
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "bitauth",
|
"name": "bitauth",
|
||||||
"description": "Passwordless authentication using Bitcoin cryptography",
|
"description": "Passwordless authentication using Bitcoin cryptography",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Patrick Nagurny",
|
"name": "BitPay",
|
||||||
"email": "patrick@bitpay.com"
|
"email": "dev@bitpay.com"
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/bitpay/bitauth.git"
|
|
||||||
},
|
},
|
||||||
|
"repository": "https://github.com/bitpay/bitauth.git",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
{
|
{
|
||||||
"name": "Eric Martindale",
|
"name": "Eric Martindale",
|
||||||
|
@ -18,6 +14,10 @@
|
||||||
{
|
{
|
||||||
"name": "Gordon Hall",
|
"name": "Gordon Hall",
|
||||||
"email": "gordon@bitpay.com"
|
"email": "gordon@bitpay.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Patrick Nagurny",
|
||||||
|
"email": "patrick@bitpay.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -26,14 +26,13 @@
|
||||||
"postinstall": "npm run make-dist"
|
"postinstall": "npm run make-dist"
|
||||||
},
|
},
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"version": "0.1.1",
|
"version": "0.2.0",
|
||||||
"repository": "https://github.com/bitpay/bitauth.git",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bitcore": "0.1.32",
|
|
||||||
"request": "^2.36.0",
|
|
||||||
"express": "^4.3.1",
|
|
||||||
"base58-native": "^0.1.4",
|
"base58-native": "^0.1.4",
|
||||||
"body-parser": "^1.2.0"
|
"bitcore": "bitcore",
|
||||||
|
"body-parser": "^1.2.0",
|
||||||
|
"express": "^4.3.1",
|
||||||
|
"request": "^2.36.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"uglify-js": "~2.4.14",
|
"uglify-js": "~2.4.14",
|
||||||
|
|
|
@ -5,22 +5,22 @@ var bitauth = require('../index');
|
||||||
describe('bitauth', function() {
|
describe('bitauth', function() {
|
||||||
|
|
||||||
var keys = null;
|
var keys = null;
|
||||||
var sin = 'Tf1Jc1xSbqasm5QLwwSQc5umddx2h7mAMHX';
|
var identity = 'Tf1Jc1xSbqasm5QLwwSQc5umddx2h7mAMHX';
|
||||||
var sinb = 'Tf1Jc1xSbqasm5QLwwSQc5umddx2h7mAMhX';
|
var identityb = 'Tf1Jc1xSbqasm5QLwwSQc5umddx2h7mAMhX';
|
||||||
var contract = 'keyboard cat';
|
var contract = 'keyboard cat';
|
||||||
var secret = 'o hai, nsa. how i do teh cryptos?';
|
var secret = 'o hai, nsa. how i do teh cryptos?';
|
||||||
var password = 's4705hiru13z!';
|
var password = 's4705hiru13z!';
|
||||||
var signature = null;
|
var signature = null;
|
||||||
var enc = null;
|
var enc = null;
|
||||||
|
|
||||||
describe('#generateSin', function() {
|
describe('#generateIdentity', function() {
|
||||||
|
|
||||||
it('should generate a sin object', function(done) {
|
it('should generate a identity object', function(done) {
|
||||||
keys = bitauth.generateSin();
|
keys = bitauth.generateIdentity()._keypair;
|
||||||
should.exist(keys);
|
should.exist(keys);
|
||||||
should.exist(keys.pub);
|
should.exist(keys._keypair.pubkey);
|
||||||
should.exist(keys.priv);
|
should.exist(keys._keypair.privkey);
|
||||||
should.exist(keys.sin);
|
should.exist(keys._identity);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -35,10 +35,10 @@ describe('bitauth', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#getSinFromPublicKey', function() {
|
describe('#getIdentityFromPublicKey', function() {
|
||||||
|
|
||||||
it('should properly get the sin', function(done) {
|
it('should properly get the identity', function(done) {
|
||||||
bitauth.getSinFromPublicKey(keys.pub).should.equal(keys.sin);
|
bitauth.getIdentityFromPublicKey(keys.pub).should.equal(keys.identity);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -62,31 +62,31 @@ describe('bitauth', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#validateSinTrue', function() {
|
describe('#validateIdentityTrue', function() {
|
||||||
|
|
||||||
it('should validate the sin as true', function(done) {
|
it('should validate the identity as true', function(done) {
|
||||||
var valid = bitauth.validateSin(sin);
|
var valid = bitauth.validateIdentity(identity);
|
||||||
should.equal(true, valid);
|
should.equal(true, valid);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#validateSinFalse', function() {
|
describe('#validateIdentityFalse', function() {
|
||||||
|
|
||||||
it('should validate the sin as false', function(done) {
|
it('should validate the identity as false', function(done) {
|
||||||
var valid = bitauth.validateSin(sinb);
|
var valid = bitauth.validateIdentity(identityb);
|
||||||
should.equal(false, valid);
|
should.equal(false, valid);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#validateSinCallback', function() {
|
describe('#validateIdentityCallback', function() {
|
||||||
|
|
||||||
var received;
|
var received;
|
||||||
|
|
||||||
var valid = bitauth.validateSin(sinb, function(err){
|
var valid = bitauth.validateIdentity(identityb, function(err){
|
||||||
if ( err && typeof(err) == 'object' ) {
|
if ( err && typeof(err) == 'object' ) {
|
||||||
received = true;
|
received = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue