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'); |
|||
client.FileStorage = require('./filestorage'); |
|||
client.Verifier = require('./verifier'); |
|||
client.AirGapped = require('./airgapped'); |
|||
|
File diff suppressed because it is too large
Loading…
Reference in new issue