fix airgapped

This commit is contained in:
Matias Alejo Garcia 2015-02-24 21:35:00 -03:00
parent e6be33d290
commit 82efc8001d
7 changed files with 41 additions and 14 deletions

View File

@ -124,7 +124,10 @@ bit import output.dat
```
# Airgapped Operation
# Airgapped Operation
## WARNING: THIS IS STILL WIP ##
Air gapped (non connected) devices are supported. This setup can be useful is maximun security is needed, to prevent private keys to get compromissed. In this setup a device is installed without network access, and transactions are signed off-line. Transactions can be pulled from the server using a `proxy` device, then downloaded to a pendrive to be moved to the air-gapped device, signed there and then moved back the `proxy` device to be send back to the server. Note that Private keys are generated off-line in the airgapped device.
@ -133,10 +136,12 @@ Air gapped (non connected) devices are supported. This setup can be useful is ma
# On the Air-gapped device
airgapped$ bit genkey
airgapped$ bit export -o wallet.dat --readonly #(or --readwrite if you need the proxy to be able to propose transactions)
airgapped$ bit export -o toProxy --access readwrite #(or --readonly if proxy wont be allowed to propose transactions)
# On the proxy machine
proxy$ bit join secret -i wallet.dat
proxy$ bit import toProxy
proxy$ bit join secret # Or bit create
proxy$ bit address # Only if readwrite access was granted
proxy$ bit balance
# Export pending transaction to be signed offline

View File

@ -9,6 +9,7 @@ program = utils.configureCommander(program);
program
.version('0.0.1')
.option('-n, --nopasswd [level]', 'Set access for no password usage: none(default), readonly, readwrite, full', 'none')
.usage('import [options] <file>')
.parse(process.argv);

View File

@ -16,11 +16,8 @@ var args = program.args;
var txpid = args[0] || '';
var client = utils.getClient(program);
client.getTxProposals({}, function(err, txps) {
utils.die(err);
var txp = utils.findOneTxProposal(txps, txpid);
function end(txp) {
if (program.output) {
client.getSignatures(txp, function(err, signatures) {
utils.die(err);
@ -34,6 +31,7 @@ client.getTxProposals({}, function(err, txps) {
} else {
if (program.input) {
var infile = JSON.parse(fs.readFileSync(program.input));
if (infile.id != txp.id)
utils.die('Signatures does not match Transaction')
@ -49,4 +47,17 @@ client.getTxProposals({}, function(err, txps) {
console.log('Transaction signed by you.');
});
}
});
};
if (program.input && program.output) {
var inFile = JSON.parse(fs.readFileSync(program.input));
end(inFile.txps[0]);
} else {
client.getTxProposals({}, function(err, txps) {
utils.die(err);
var txp = utils.findOneTxProposal(txps, txpid);
utils.die(err);
end(txp);
});
}

View File

@ -6,7 +6,11 @@ var Utils = function() {};
var die = Utils.die = function(err) {
if (err) {
console.error(err);
if (err.code && err.code == 'ECONNREFUSED') {
console.error('Could not connect to Bicore Wallet Service');
} else {
console.error(err);
}
process.exit(1);
}
};
@ -49,14 +53,19 @@ Utils.getClient = function(args) {
if (args.nopasswd)
c.setNopasswdAccess(args.nopasswd);
var setPassword;
c.on('needPassword', function(cb) {
if (args.password) {
return cb(args.password);
} else {
if (setPassword)
return cb(setPassword);
read({
prompt: 'Password for ' + args.file + ' : ',
silent: true
}, function(er, password) {
setPassword = password;
return cb(password);
})
}

View File

@ -234,6 +234,7 @@ API.prototype.setNopasswdAccess = function(noPasswdAccess) {
API.prototype._processWcdBeforeWrite = function(wcd, cb) {
var self = this;
// Is any encrypted?
if (this.noPasswdAccess == 'full') {
return cb(null, wcd);
@ -257,6 +258,7 @@ API.prototype._load = function(opts, cb) {
if (err && err.code == 'ENOENT') err = 'NOTFOUND';
return cb(err || 'NOTFOUND');
}
self._processWcdAfterRead(rawdata, opts.requiredAccess, cb);
});
};
@ -618,7 +620,7 @@ API.prototype.export = function(opts, cb) {
if (err) return cb(err);
var v = [];
var myXPubKey = (new Bitcore.HDPublicKey(wcd.xPrivKey)).toString();
var myXPubKey = wcd.xPrivKey ? (new Bitcore.HDPublicKey(wcd.xPrivKey)).toString() : '';
_.each(WALLET_CRITICAL_DATA, function(k) {
var d;
@ -679,6 +681,7 @@ API.prototype.import = function(str, cb) {
return cb('Invalid source wallet');
wcd.network = wcd.publicKeyRing[0].substr(0, 4) == 'tpub' ? 'testnet' : 'livenet';
self.save(wcd, function(err) {
return cb(err, WalletUtils.accessFromData(wcd));
});

View File

@ -66,6 +66,8 @@ Verifier.checkTxProposal = function(data, txp) {
var hash = WalletUtils.getProposalHash(txp.toAddress, txp.amount, txp.encryptedMessage || txp.message);
log.debug('Regenerating & verifying tx proposal hash -> Hash: ', hash, ' Signature: ', txp.proposalSignature);
if (!WalletUtils.verifyMessage(hash, txp.proposalSignature, creatorSigningPubKey))
return false;

View File

@ -185,10 +185,6 @@ WalletUtils.encryptWallet = function(data, accessWithoutEncrytion, password) {
var fieldsEncrypt = fieldsEncryptByLevel[accessWithoutEncrytion];
$.checkState(!_.isUndefined(fieldsEncrypt));
if (!_.every(fieldsEncrypt, function(k) {
return data[k];
})) throw new Error('Wallet does not contain necesary info to encrypt');
var toEncrypt = _.pick(data, fieldsEncrypt);
var enc = sjcl.encrypt(password, JSON.stringify(toEncrypt), WalletUtils.sjclOpts);