Matias Alejo Garcia
10 years ago
28 changed files with 1150 additions and 1591 deletions
@ -0,0 +1,62 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
var _ = require('lodash'); |
||||
|
var $ = require('preconditions').singleton(); |
||||
|
var util = require('util'); |
||||
|
var async = require('async'); |
||||
|
var log = require('npmlog'); |
||||
|
var events = require('events'); |
||||
|
log.debug = log.verbose; |
||||
|
var Bitcore = require('bitcore') |
||||
|
|
||||
|
var Credentials = require('./credentials'); |
||||
|
var WalletUtils = require('../walletutils'); |
||||
|
var Verifier = require('./verifier'); |
||||
|
var ServerCompromisedError = require('./servercompromisederror'); |
||||
|
var ClientError = require('../clienterror'); |
||||
|
|
||||
|
function AirGapped(opts) { |
||||
|
this.verbose = !!opts.verbose; |
||||
|
if (this.verbose) { |
||||
|
log.level = 'debug'; |
||||
|
} else { |
||||
|
log.level = 'info'; |
||||
|
} |
||||
|
this.credentials = Credentials.create(opts.network || 'livenet'); |
||||
|
}; |
||||
|
|
||||
|
util.inherits(AirGapped, events.EventEmitter); |
||||
|
|
||||
|
AirGapped.prototype.getSeed = function() { |
||||
|
return { |
||||
|
xPubKey: this.credentials.xPubKey, |
||||
|
requestPrivKey: this.credentials.requestPrivKey, |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
AirGapped.prototype.signTxProposal = function(txp, encryptedPkr, m, n) { |
||||
|
var self = this; |
||||
|
|
||||
|
var publicKeyRing; |
||||
|
try { |
||||
|
publicKeyRing = JSON.parse(WalletUtils.decryptMessage(encryptedPkr, self.credentials.personalEncryptingKey)); |
||||
|
} catch (ex) { |
||||
|
console.log(ex); |
||||
|
throw new Error('Could not decrypt public key ring'); |
||||
|
} |
||||
|
|
||||
|
if (!_.isArray(publicKeyRing) || publicKeyRing.length != n) { |
||||
|
throw new Error('Invalid public key ring'); |
||||
|
} |
||||
|
|
||||
|
self.credentials.m = m; |
||||
|
self.credentials.n = n; |
||||
|
self.credentials.addPublicKeyRing(publicKeyRing); |
||||
|
|
||||
|
if (!Verifier.checkTxProposal(self.credentials, txp)) { |
||||
|
throw new Error('Fake transaction proposal'); |
||||
|
} |
||||
|
return WalletUtils.signTxp(txp, self.credentials.xPrivKey); |
||||
|
}; |
||||
|
|
||||
|
module.exports = AirGapped; |
File diff suppressed because it is too large
@ -0,0 +1,169 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
var $ = require('preconditions').singleton(); |
||||
|
var _ = require('lodash'); |
||||
|
var Bitcore = require('bitcore'); |
||||
|
var WalletUtils = require('../walletutils'); |
||||
|
|
||||
|
var FIELDS = [ |
||||
|
'network', |
||||
|
'xPrivKey', |
||||
|
'xPubKey', |
||||
|
'requestPrivKey', |
||||
|
'copayerId', |
||||
|
'publicKeyRing', |
||||
|
'walletId', |
||||
|
'walletName', |
||||
|
'm', |
||||
|
'n', |
||||
|
'walletPrivKey', |
||||
|
'personalEncryptingKey', |
||||
|
'sharedEncryptingKey', |
||||
|
'copayerName', |
||||
|
]; |
||||
|
|
||||
|
var EXPORTABLE_FIELDS = [ |
||||
|
'xPrivKey', |
||||
|
'requestPrivKey', |
||||
|
'xPubKey', |
||||
|
'm', |
||||
|
'n', |
||||
|
'publicKeyRing', |
||||
|
'sharedEncryptingKey', |
||||
|
]; |
||||
|
|
||||
|
function Credentials() { |
||||
|
this.version = '1.0.0'; |
||||
|
}; |
||||
|
|
||||
|
Credentials.create = function(network) { |
||||
|
var x = new Credentials(); |
||||
|
|
||||
|
x.network = network; |
||||
|
x.xPrivKey = (new Bitcore.HDPrivateKey(network)).toString(); |
||||
|
x._expand(); |
||||
|
return x; |
||||
|
}; |
||||
|
|
||||
|
Credentials.fromExtendedPrivateKey = function(xPrivKey) { |
||||
|
var x = new Credentials(); |
||||
|
x.xPrivKey = xPrivKey; |
||||
|
x._expand(); |
||||
|
return x; |
||||
|
}; |
||||
|
|
||||
|
Credentials.fromExtendedPublicKey = function(xPubKey, requestPrivKey) { |
||||
|
var x = new Credentials(); |
||||
|
x.xPubKey = xPubKey; |
||||
|
x.requestPrivKey = requestPrivKey; |
||||
|
x._expand(); |
||||
|
return x; |
||||
|
}; |
||||
|
|
||||
|
Credentials.prototype._expand = function() { |
||||
|
$.checkState(this.xPrivKey || this.xPubKey); |
||||
|
|
||||
|
if (this.xPrivKey) { |
||||
|
var xPrivKey = new Bitcore.HDPrivateKey.fromString(this.xPrivKey); |
||||
|
this.xPubKey = (new Bitcore.HDPublicKey(xPrivKey)).toString(); |
||||
|
this.requestPrivKey = xPrivKey.derive('m/1/1').privateKey.toString(); |
||||
|
} |
||||
|
var network = WalletUtils.getNetworkFromXPubKey(this.xPubKey); |
||||
|
if (this.network) { |
||||
|
$.checkState(this.network == network); |
||||
|
} else { |
||||
|
this.network = network; |
||||
|
} |
||||
|
|
||||
|
this.personalEncryptingKey = WalletUtils.privateKeyToAESKey(this.requestPrivKey); |
||||
|
this.copayerId = WalletUtils.xPubToCopayerId(this.xPubKey); |
||||
|
}; |
||||
|
|
||||
|
Credentials.fromObj = function(obj) { |
||||
|
var x = new Credentials(); |
||||
|
|
||||
|
_.each(FIELDS, function(k) { |
||||
|
x[k] = obj[k]; |
||||
|
}); |
||||
|
|
||||
|
return x; |
||||
|
}; |
||||
|
|
||||
|
Credentials.prototype.toObj = function() { |
||||
|
return this; |
||||
|
}; |
||||
|
|
||||
|
Credentials.prototype.addWalletInfo = function(walletId, walletName, m, n, walletPrivKey, copayerName) { |
||||
|
this.walletId = walletId; |
||||
|
this.walletName = walletName; |
||||
|
this.m = m; |
||||
|
this.n = n; |
||||
|
this.walletPrivKey = walletPrivKey; |
||||
|
this.sharedEncryptingKey = WalletUtils.privateKeyToAESKey(walletPrivKey); |
||||
|
this.copayerName = copayerName; |
||||
|
if (n == 1) { |
||||
|
this.addPublicKeyRing([this.xPubKey]); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
Credentials.prototype.hasWalletInfo = function() { |
||||
|
return !!this.walletId; |
||||
|
}; |
||||
|
|
||||
|
Credentials.prototype.addPublicKeyRing = function(publicKeyRing) { |
||||
|
this.publicKeyRing = _.clone(publicKeyRing); |
||||
|
}; |
||||
|
|
||||
|
Credentials.prototype.canSign = function() { |
||||
|
return !!this.xPrivKey; |
||||
|
}; |
||||
|
|
||||
|
Credentials.prototype.isComplete = function() { |
||||
|
if (!this.m || !this.n) return false; |
||||
|
if (!this.publicKeyRing || this.publicKeyRing.length != this.n) return false; |
||||
|
return true; |
||||
|
}; |
||||
|
|
||||
|
Credentials.prototype.exportCompressed = function() { |
||||
|
var self = this; |
||||
|
|
||||
|
var values = _.map(EXPORTABLE_FIELDS, function(field) { |
||||
|
if ((field == 'xPubKey' || field == 'requestPrivKey') && self.canSign()) return ''; |
||||
|
if (field == 'requestPrivKey') { |
||||
|
return Bitcore.PrivateKey.fromString(self.requestPrivKey).toWIF(); |
||||
|
} |
||||
|
if (field == 'publicKeyRing') { |
||||
|
return _.without(self.publicKeyRing, self.xPubKey); |
||||
|
} |
||||
|
return self[field]; |
||||
|
}); |
||||
|
values.unshift(self.version); |
||||
|
|
||||
|
return JSON.stringify(values); |
||||
|
}; |
||||
|
|
||||
|
Credentials.importCompressed = function(compressed) { |
||||
|
var list; |
||||
|
try { |
||||
|
list = JSON.parse(compressed); |
||||
|
} catch (ex) { |
||||
|
throw new Error('Invalid compressed format'); |
||||
|
} |
||||
|
|
||||
|
var x = new Credentials(); |
||||
|
|
||||
|
// Remove version
|
||||
|
var version = list[0]; |
||||
|
list = _.rest(list); |
||||
|
|
||||
|
_.each(EXPORTABLE_FIELDS, function(field, i) { |
||||
|
x[field] = list[i]; |
||||
|
}); |
||||
|
x._expand(); |
||||
|
|
||||
|
x.network = WalletUtils.getNetworkFromXPubKey(x.xPubKey); |
||||
|
x.publicKeyRing.push(x.xPubKey); |
||||
|
return x; |
||||
|
}; |
||||
|
|
||||
|
module.exports = Credentials; |
@ -1,5 +1,3 @@ |
|||||
//var client = ;
|
|
||||
|
|
||||
var client = module.exports = require('./api'); |
var client = module.exports = require('./api'); |
||||
client.FileStorage = require('./filestorage'); |
|
||||
client.Verifier = require('./verifier'); |
client.Verifier = require('./verifier'); |
||||
|
client.AirGapped = require('./airgapped'); |
||||
|
File diff suppressed because it is too large
Loading…
Reference in new issue