mirror of https://github.com/BTCPrivate/copay.git
Merge pull request #1275 from matiaspando/feature/secret
Added secret number feature
This commit is contained in:
commit
bd5b7a22b0
|
@ -43,6 +43,7 @@ function Wallet(opts) {
|
|||
' and tried to create a Wallet with network ' + this.getNetworkName());
|
||||
|
||||
this.id = opts.id || Wallet.getRandomId();
|
||||
this.secretNumber = opts.secretNumber || Wallet.getRandomNumber();
|
||||
this.lock = new WalletLock(this.storage, this.id, opts.lockTimeOutMin);
|
||||
this.name = opts.name;
|
||||
|
||||
|
@ -50,6 +51,7 @@ function Wallet(opts) {
|
|||
this.publicKeyRing.walletId = this.id;
|
||||
this.txProposals.walletId = this.id;
|
||||
this.network.maxPeers = this.totalCopayers;
|
||||
this.network.secretNumber = this.secretNumber;
|
||||
this.registeredPeerIds = [];
|
||||
this.addressBook = opts.addressBook || {};
|
||||
this.publicKey = this.privateKey.publicHex;
|
||||
|
@ -78,6 +80,11 @@ Wallet.getRandomId = function() {
|
|||
return r;
|
||||
};
|
||||
|
||||
Wallet.getRandomNumber = function() {
|
||||
var r = bitcore.SecureRandom.getPseudoRandomBuffer(5).toString('hex');
|
||||
return r;
|
||||
};
|
||||
|
||||
Wallet.prototype.seedCopayer = function(pubKey) {
|
||||
this.seededCopayerId = pubKey;
|
||||
};
|
||||
|
@ -408,18 +415,28 @@ Wallet.prototype.getMyCopayerIdPriv = function() {
|
|||
return this.privateKey.getIdPriv(); //copayer idpriv is hex of a private key
|
||||
};
|
||||
|
||||
|
||||
Wallet.prototype.getSecretNumber = function() {
|
||||
if (this.secretNumber) return this.secretNumber;
|
||||
this.secretNumber = Wallet.getRandomNumber();
|
||||
return this.secretNumber;
|
||||
};
|
||||
|
||||
Wallet.prototype.getSecret = function() {
|
||||
var pubkeybuf = new Buffer(this.getMyCopayerId(), 'hex');
|
||||
var str = Base58Check.encode(pubkeybuf);
|
||||
var buf = new Buffer(this.getMyCopayerId() + this.getSecretNumber(), 'hex');
|
||||
var str = Base58Check.encode(buf);
|
||||
return str;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Wallet.decodeSecret = function(secretB) {
|
||||
var secret = Base58Check.decode(secretB);
|
||||
var pubKeyBuf = secret.slice(0, 33);
|
||||
var secretNumber = secret.slice(33, 38);
|
||||
return {
|
||||
pubKey: pubKeyBuf.toString('hex')
|
||||
pubKey: pubKeyBuf.toString('hex'),
|
||||
secretNumber : secretNumber.toString('hex')
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -445,6 +462,7 @@ Wallet.prototype.netStart = function(callback) {
|
|||
privkey: myIdPriv,
|
||||
maxPeers: self.totalCopayers,
|
||||
lastTimestamp: this.lastTimestamp,
|
||||
secretNumber: self.secretNumber,
|
||||
};
|
||||
|
||||
if (this.publicKeyRing.isComplete()) {
|
||||
|
|
|
@ -233,7 +233,8 @@ WalletFactory.prototype.joinCreateSession = function(secret, nickname, passphras
|
|||
var opts = {
|
||||
copayerId: privateKey.getId(),
|
||||
privkey: privateKey.getIdPriv(),
|
||||
key: privateKey.getIdKey()
|
||||
key: privateKey.getIdKey(),
|
||||
secretNumber : s.secretNumber,
|
||||
};
|
||||
self.network.cleanUp();
|
||||
|
||||
|
@ -248,7 +249,7 @@ WalletFactory.prototype.joinCreateSession = function(secret, nickname, passphras
|
|||
});
|
||||
|
||||
self.network.start(opts, function() {
|
||||
self.network.greet(s.pubKey);
|
||||
self.network.greet(s.pubKey,opts.secretNumber);
|
||||
self.network.on('data', function(sender, data) {
|
||||
if (data.type === 'walletId') {
|
||||
if (data.networkName !== self.networkName) {
|
||||
|
|
|
@ -17,6 +17,7 @@ function Network(opts) {
|
|||
this.host = opts.host || 'localhost';
|
||||
this.port = opts.port || 3001;
|
||||
this.schema = opts.schema || 'https';
|
||||
this.secretNumber = opts.secretNumber;
|
||||
this.cleanUp();
|
||||
}
|
||||
|
||||
|
@ -73,11 +74,12 @@ Network.prototype.connectedCopayers = function() {
|
|||
return ret;
|
||||
};
|
||||
|
||||
Network.prototype._sendHello = function(copayerId) {
|
||||
Network.prototype._sendHello = function(copayerId,secretNumber) {
|
||||
|
||||
this.send(copayerId, {
|
||||
type: 'hello',
|
||||
copayerId: this.copayerId,
|
||||
secretNumber : secretNumber
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -193,6 +195,12 @@ Network.prototype._onMessage = function(enc) {
|
|||
var self = this;
|
||||
switch (payload.type) {
|
||||
case 'hello':
|
||||
|
||||
if (typeof payload.secretNumber === 'undefined' || payload.secretNumber !== this.secretNumber)
|
||||
{
|
||||
this._deletePeer(enc.pubkey, 'incorrect secret number');
|
||||
return;
|
||||
}
|
||||
// if we locked allowed copayers, check if it belongs
|
||||
if (this.allowedCopayerIds && !this.allowedCopayerIds[payload.copayerId]) {
|
||||
this._deletePeer(sender);
|
||||
|
@ -240,8 +248,8 @@ Network.prototype._onError = function(err) {
|
|||
this.criticalError = err.message;
|
||||
};
|
||||
|
||||
Network.prototype.greet = function(copayerId) {
|
||||
this._sendHello(copayerId);
|
||||
Network.prototype.greet = function(copayerId,secretNumber) {
|
||||
this._sendHello(copayerId,secretNumber);
|
||||
var peerId = this.peerFromCopayer(copayerId);
|
||||
this._addCopayerMap(peerId, copayerId);
|
||||
};
|
||||
|
@ -350,6 +358,7 @@ Network.prototype.send = function(dest, payload, cb) {
|
|||
if (to == this.copayerId)
|
||||
continue;
|
||||
log.debug('SEND to: ' + to, this.copayerId, payload);
|
||||
|
||||
var message = this.encode(to, payload);
|
||||
this.socket.emit('message', message);
|
||||
}
|
||||
|
|
|
@ -337,22 +337,29 @@ describe('Wallet model', function() {
|
|||
it('#getSecret decodeSecret', function() {
|
||||
var w = cachedCreateW2();
|
||||
var id = w.getMyCopayerId();
|
||||
var secretNumber = w.getSecretNumber();
|
||||
|
||||
var sb = w.getSecret();
|
||||
should.exist(sb);
|
||||
|
||||
var s = Wallet.decodeSecret(sb);
|
||||
s.pubKey.should.equal(id);
|
||||
s.secretNumber.should.equal(secretNumber);
|
||||
|
||||
});
|
||||
|
||||
|
||||
it('decodeSecret check', function() {
|
||||
(function() {
|
||||
Wallet.decodeSecret('4fp61K187CsYmjoRQC5iAdC5eGmbCRsAAXfwEwetSQgHvZs27eWKaLaNHRoKM');
|
||||
}).should.not.
|
||||
throw();
|
||||
|
||||
(function() {
|
||||
Wallet.decodeSecret('4fp61K187CsYmjoRQC5iAdC5eGmbCRsAAXfwEwetSQgHvZs27eWKaLaNHRoK');
|
||||
}).should.
|
||||
throw();
|
||||
|
||||
(function() {
|
||||
Wallet.decodeSecret('12345');
|
||||
}).should.
|
||||
|
|
|
@ -27,10 +27,12 @@ describe('Network / Async', function() {
|
|||
privkey: pk || '31701118abde096d166607115ed00ce74a2231f68f43144406c863f5ebf06c32',
|
||||
lastTimestamp: 1,
|
||||
};
|
||||
n.secretNumber = 'mySecret';
|
||||
n.start(opts);
|
||||
return n;
|
||||
};
|
||||
|
||||
|
||||
it('should create an instance', function() {
|
||||
var n = createN();
|
||||
should.exist(n);
|
||||
|
@ -129,7 +131,8 @@ describe('Network / Async', function() {
|
|||
|
||||
var message = {
|
||||
type: 'hello',
|
||||
copayerId: cid1
|
||||
copayerId: cid1,
|
||||
secretNumber : 'mySecret'
|
||||
};
|
||||
var enc = n1.encode(cid2, message);
|
||||
n2._onMessage(enc);
|
||||
|
@ -141,7 +144,8 @@ describe('Network / Async', function() {
|
|||
|
||||
var message = {
|
||||
type: 'hello',
|
||||
copayerId: cid3 // MITM
|
||||
copayerId: cid3, // MITM
|
||||
secretNumber : 'mySecret'
|
||||
};
|
||||
|
||||
var enc = n.encode(cid2, message);
|
||||
|
@ -160,7 +164,8 @@ describe('Network / Async', function() {
|
|||
|
||||
var message = {
|
||||
type: 'hello',
|
||||
copayerId: cid1
|
||||
copayerId: cid1,
|
||||
secretNumber : 'mySecret'
|
||||
};
|
||||
var nonce = new Buffer('0000000000000001', 'hex');
|
||||
var enc = n1.encode(cid2, message, nonce);
|
||||
|
@ -176,7 +181,8 @@ describe('Network / Async', function() {
|
|||
|
||||
var message = {
|
||||
type: 'hello',
|
||||
copayerId: cid1
|
||||
copayerId: cid1,
|
||||
secretNumber : 'mySecret'
|
||||
};
|
||||
n2.networkNonces = {};
|
||||
n2.networkNonces[cid1] = new Buffer('5000000000000001', 'hex');
|
||||
|
@ -195,7 +201,8 @@ describe('Network / Async', function() {
|
|||
|
||||
var message = {
|
||||
type: 'hello',
|
||||
copayerId: cid1
|
||||
copayerId: cid1,
|
||||
secretNumber : 'mySecret'
|
||||
};
|
||||
n2.networkNonces = {};
|
||||
n2.networkNonces[cid1] = new Buffer('0000000000000002', 'hex');
|
||||
|
@ -205,6 +212,40 @@ describe('Network / Async', function() {
|
|||
n2._deletePeer.calledOnce.should.equal(true);
|
||||
});
|
||||
|
||||
it('should accept join with a correct secret number', function() {
|
||||
var n1 = createN(pk1);
|
||||
var n2 = createN(pk2);
|
||||
n2._deletePeer = sinon.spy();
|
||||
|
||||
var message = {
|
||||
type: 'hello',
|
||||
copayerId: cid1,
|
||||
secretNumber : 'mySecret'
|
||||
};
|
||||
|
||||
var enc = n1.encode(cid2, message);
|
||||
n2._onMessage(enc);
|
||||
n2._deletePeer.calledOnce.should.equal(false);
|
||||
|
||||
});
|
||||
|
||||
it('should reject join with a incorrect secret number', function() {
|
||||
var n1 = createN(pk1);
|
||||
var n2 = createN(pk2);
|
||||
n2._deletePeer = sinon.spy();
|
||||
|
||||
var message = {
|
||||
type: 'hello',
|
||||
copayerId: cid1,
|
||||
secretNumber : 'otherSecret'
|
||||
};
|
||||
|
||||
var enc = n1.encode(cid2, message);
|
||||
n2._onMessage(enc);
|
||||
n2._deletePeer.calledOnce.should.equal(true);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#setHexNonce', function() {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<h1 class="text-primary line-sidebar-b">Waiting copayers</h1>
|
||||
<h3>Share this secret with your other copayers</h3>
|
||||
<div class="panel">
|
||||
<qrcode size="250" data="{{$root.wallet.getSecret()}}"></qrcode>
|
||||
<qrcode size="350" data="{{$root.wallet.getSecret()}}"></qrcode>
|
||||
<div class="secret text-gray size-14">
|
||||
{{$root.wallet.getSecret()}}
|
||||
<span class="btn-copy" clip-copy="$root.wallet.getSecret()"></span>
|
||||
|
|
Loading…
Reference in New Issue