Skip to content
This repository has been archived by the owner on Nov 21, 2019. It is now read-only.

Commit

Permalink
Merge pull request #2172 from benma/bitbox
Browse files Browse the repository at this point in the history
BitBox
  • Loading branch information
gamalielhere authored Dec 5, 2018
2 parents a90bf5e + 09d3c1e commit 80a5376
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 89 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Check gh-pages files against live website at https://www.myetherwallet.com
| File Name| Status|
|---|---|
| index.html |![embedded.html](https://filechecker.myetherwallet.com/check?localFile=https://raw.githubusercontent.com/kvhnuke/etherwallet/gh-pages/index.html&remoteFile=https://www.myetherwallet.com/index.html)|
| embedded.html |![embedded.html](https://filechecker.myetherwallet.com/check?localFile=https://raw.githubusercontent.com/kvhnuke/etherwallet/gh-pages/embedded.html&remoteFile=https://www.myetherwallet.com/embedded.html)|
| embedded.html |![embedded.html](https://filechecker.myetherwallet.com/check?localFile=https://raw.githubusercontent.com/kvhnuke/etherwallet/gh-pages/embedded.html&remoteFile=https://www.myetherwallet.com/embedded.html)|
| helpers.html |![embedded.html](https://filechecker.myetherwallet.com/check?localFile=https://raw.githubusercontent.com/kvhnuke/etherwallet/gh-pages/helpers.html&remoteFile=https://www.myetherwallet.com/helpers.html)|
| signmsg.html |![signmsg.html](https://filechecker.myetherwallet.com/check?localFile=https://raw.githubusercontent.com/kvhnuke/etherwallet/gh-pages/signmsg.html&remoteFile=https://www.myetherwallet.com/signmsg.html)|
| bin/startMEW.js |![startMEW.js](https://filechecker.myetherwallet.com/check?localFile=https://raw.githubusercontent.com/kvhnuke/etherwallet/gh-pages/bin/startMEW.js&remoteFile=https://www.myetherwallet.com/bin/startMEW.js)|
Expand Down Expand Up @@ -64,10 +64,10 @@ Check gh-pages files against live website at https://www.myetherwallet.com
#### Features

- Create new wallets completely client side.
- Access your wallet via unencrypted private key, encrypted private key, keystore files, mnemonics, or Digital Bitbox, Ledger Nano S or TREZOR hardware wallet.
- Access your wallet via unencrypted private key, encrypted private key, keystore files, mnemonics, or BitBox, Ledger Nano S or TREZOR hardware wallet.
- Easily send ETH and *any* ERC-20 Standard Token. [Many tokens included as default.](https://myetherwallet.groovehq.com/knowledge_base/topics/can-i-send-my-steem-slash-btc-slash-ltc-slash-nem-slash-to-myetherwallet)
- Generate, sign & send transactions offline, ensuring your private keys never touch an internet-connected device.
- Securely access your ETH & Tokens on your [Digital Bitbox, Ledger or TREZOR Hardware Wallet](https://myetherwallet.groovehq.com/knowledge_base/topics/hardware-wallet-recommends) via the MyEtherWallet interface (Chrome & Opera natively, Firefox w/ [add-on](https://addons.mozilla.org/en-US/firefox/addon/u2f-support-add-on/))
- Securely access your ETH & Tokens on your [BitBox, Ledger or TREZOR Hardware Wallet](https://myetherwallet.groovehq.com/knowledge_base/topics/hardware-wallet-recommends) via the MyEtherWallet interface (Chrome & Opera natively, Firefox w/ [add-on](https://addons.mozilla.org/en-US/firefox/addon/u2f-support-add-on/))
- Now in 18 languages thanks 100% to the amazing Ethereum community.
- Supports URI Strings on Send Transaction Page.
- to=[address]
Expand Down
2 changes: 1 addition & 1 deletion app/includes/footer.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
<div class="footer__pill-wrap footer__pill-custom-wrap">
<a class="footer__pill" href="https://www.ledger.com/products/ledger-nano-s?r=fa4b" target="_blank" rel="noopener">Ledger Wallet</a>
<a class="footer__pill" href="https://trezor.io/?a=myetherwallet.com" target="_blank" rel="noopener">TREZOR</a>
<a class="footer__pill" href="http://shiftcrypto.ositracker.com/91316/7114" target="_blank" rel="noopener">Digital Bitbox</a>
<a class="footer__pill" href="http://shiftcrypto.ositracker.com/91316/7114" target="_blank" rel="noopener">BitBox</a>
<a class="footer__pill" href="https://ether.cards/?utm_source=mew&utm_medium=cpm&utm_campaign=site" target="_blank" rel="noopener">ether.card</a>
<a class="footer__pill" href="https://thehodlwallet.com?aff=15" target="_blank" rel="noopener">HODL Wallet</a>
<a class="footer__pill" href="http://billfodl.com?afmc=2j&utm_campaign=2j&utm_source=leaddyno&utm_medium=affiliate" target="_blank" rel="noopener">Billfodl</a>
Expand Down
2 changes: 1 addition & 1 deletion app/includes/generateWallet.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
<li>
<p>
<strong>
Ledger / TREZOR / Digital Bitbox / Secalot
Ledger / TREZOR / BitBox / Secalot
</strong>:
<span translate="GEN_Help_1">
Use your
Expand Down
2 changes: 1 addition & 1 deletion app/scripts/controllers/signMsgCtrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ var signMsgCtrl = function($scope, $sce, walletService) {
localCallback
);

// Sign via Digital Bitbox
// Sign via BitBox
} else if (typeof hwType != "undefined" && hwType == "digitalBitbox") {
var msg = ethUtil.hashPersonalMessage(ethUtil.toBuffer(thisMessage));
var localCallback = function(signed, error) {
Expand Down
22 changes: 11 additions & 11 deletions app/scripts/directives/walletDecryptDrtv.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ <h4 translate="decrypt_Access">
ng-show="ajaxReq.type=='ETH'||ajaxReq.type=='ETC'||ajaxReq.type=='ROPSTEN ETH'||ajaxReq.type=='RINKEBY ETH'||ajaxReq.type=='KOVAN ETH'||ajaxReq.type=='EXP'">
<input aria-flowto="aria5"
type="radio"
aria-label="Digital Bitbox hardware wallet"
aria-label="BitBox hardware wallet"
ng-model="walletType"
value="digitalBitbox"/>
Digital Bitbox
BitBox
</label>

<!-- Secalot -->
Expand Down Expand Up @@ -413,7 +413,7 @@ <h5>
<!-- Digital Bitbox-->
<div id="selectedTypeDigitalBitbox" ng-if="walletType=='digitalBitbox'">
<h4>
Digital Bitbox Hardware Wallet
BitBox Hardware Wallet
</h4>
<h5>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 79.536 79.536"><path fill="#5dba5a" d="M39.769 0C17.8 0 0 17.8 0 39.768c0 21.965 17.8 39.768 39.769 39.768 21.965 0 39.768-17.803 39.768-39.768C79.536 17.8 61.733 0 39.769 0zm-5.627 58.513L15.397 39.768l7.498-7.498 11.247 11.247 22.497-22.493 7.498 7.498-29.995 29.991z"/></svg>
Expand All @@ -424,31 +424,31 @@ <h5>
</div>
<ul>
<li class="u__protip">
<a href="https://digitalbitbox.com/ethereum"
<a href="https://shiftcrypto.ch/ethereum"
target="_blank"
rel="noopener noreferrer">
How to use Digital Bitbox with MyEtherWallet
How to use BitBox with MyEtherWallet
</a>
</li>
<li class="u__protip">
<a href="https://digitalbitbox.com/?ref=mew"
<a href="https://shiftcrypto.ch/?ref=mew"
target="_blank"
rel="noopener noreferrer">
Don't have a Digital Bitbox? Get one now.
Don't have a BitBox? Get one now.
</a>
</li>
</ul>
<input class="form-control"
aria-label="Enter the Digital Bitbox password"
aria-label="Enter the BitBox password"
aria-describedby="selectedTypeDigitalBitbox"
type="password"
placeholder="Digital Bitbox password"
placeholder="BitBox password"
spellcheck="false"
value=""
ng-model="HDWallet.digitalBitboxSecret" />
<div class="form-group">
<a tabindex="0" role="button" class="btn btn-primary" ng-click="scanDigitalBitbox()" translate="ADD_DigitalBitbox_scan">
Connect your Digital Bitbox
Connect your BitBox
</a>
</div>
</div>
Expand Down Expand Up @@ -873,7 +873,7 @@ <h4 id="modalTitle" class="modal-title" translate="ADD_Radio_5_Path" style="marg
value="{{HDWallet.defaultDPath}}"/>
<span ng-bind="HDWallet.defaultDPath"></span>
<p class="small">
Jaxx, Metamask, Exodus, imToken, TREZOR (ETH) &amp; Digital Bitbox
Jaxx, Metamask, Exodus, imToken, TREZOR (ETH) &amp; BitBox
</p>
</label>
</div>
Expand Down
169 changes: 99 additions & 70 deletions app/scripts/staticJS/digitalBitboxEth.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,46 @@ var DigitalBitboxEth = function(comm, sec) {
DigitalBitboxEth.to = setTimeout(function(){ DigitalBitboxEth.sec = ''; }, 60000);
}

var BitBoxSupportedMajorVersion = 5;

DigitalBitboxEth.sec = '';
DigitalBitboxEth.to = null;

DigitalBitboxEth.aes_cbc_b64_decrypt = function(ciphertext, key) {
var res;
try {
var h = Crypto.createHash('sha512').update(key).digest();
var encryptionKey = h.slice(0, 32);
var authenticationKey = h.slice(32, 64);

var ub64 = new Buffer(ciphertext, "base64").toString("binary");
var iv = new Buffer(ub64.slice(0, 16), "binary");
var enc = new Buffer(ub64.slice(16), "binary");
var decipher = Crypto.createDecipheriv("aes-256-cbc", key, iv);
var cipher = new Buffer(ub64.slice(0, ub64.length - 32), "binary");
var hmac = new Buffer(ub64.slice(ub64.length - 32), "binary");
var expectedHmac = Crypto.createHmac('sha256', authenticationKey).update(cipher).digest();
if (!hmac.equals(expectedHmac)) {
throw "hmac check failed";
}
var iv = new Buffer(cipher.slice(0, 16), "binary");
var enc = new Buffer(cipher.slice(16), "binary");
var decipher = Crypto.createDecipheriv("aes-256-cbc", encryptionKey, iv);
var dec = decipher.update(enc) + decipher.final();
res = dec.toString("utf8");
return dec.toString("utf8");
}
catch(err) {
res = ciphertext;
return ciphertext;
}
return res;
}

DigitalBitboxEth.aes_cbc_b64_encrypt = function(plaintext, key) {
try {
var h = Crypto.createHash('sha512').update(key).digest();
var encryptionKey = h.slice(0, 32);
var authenticationKey = h.slice(32, 64);

var iv = Crypto.pseudoRandomBytes(16);
var cipher = Crypto.createCipheriv("aes-256-cbc", key, iv);
var cipher = Crypto.createCipheriv("aes-256-cbc", encryptionKey, iv);
var ciphertext = Buffer.concat([iv, cipher.update(plaintext), cipher.final()]);
return ciphertext.toString("base64");
var hmac = Crypto.createHmac('sha256', authenticationKey).update(ciphertext).digest();
return Buffer.concat([ciphertext, hmac]).toString("base64");
}
catch(err) {
return '';
Expand All @@ -55,25 +70,48 @@ DigitalBitboxEth.aes_cbc_b64_encrypt = function(plaintext, key) {

DigitalBitboxEth.parseError = function(errObject) {
var errMsg = {
err101: 'The Digital Bitbox is not initialized. First use the <a href="https://digitalbitbox.com/start" target="_blank" rel="noopener noreferrer">Digital Bitbox desktop app</a> to set up a wallet.',// No password set
err250: 'The Digital Bitbox is not initialized. First use the <a href="https://digitalbitbox.com/start" target="_blank" rel="noopener noreferrer">Digital Bitbox desktop app</a> to set up a wallet.',// Wallet not seeded
err251: 'The Digital Bitbox is not initialized. First use the <a href="https://digitalbitbox.com/start" target="_blank" rel="noopener noreferrer">Digital Bitbox desktop app</a> to set up a wallet.',// Wallet not seeded
err109: 'The Digital Bitbox received unexpected data. Was the correct password used? ' + errObject.message,
err101: 'The BitBox is not initialized. First use the <a href="https://shiftcrypto.ch/start" target="_blank" rel="noopener noreferrer">Digital Bitbox desktop app</a> to set up a wallet.',// No password set
err250: 'The BitBox is not initialized. First use the <a href="https://shiftcrypto.ch/start" target="_blank" rel="noopener noreferrer">BitBox desktop app</a> to set up a wallet.',// Wallet not seeded
err251: 'The BitBox is not initialized. First use the <a href="https://shiftcrypto.ch/start" target="_blank" rel="noopener noreferrer">BitBox desktop app</a> to set up a wallet.',// Wallet not seeded
err109: 'The BitBox received unexpected data. Was the correct password used? ' + errObject.message,
};
var code = 'err' + errObject.code.toString();
var msg = errMsg[code] || errObject.message;
return msg;
}

DigitalBitboxEth.prototype.getAddress = function(path, callback) {
DigitalBitboxEth.prototype.send = function(cmd, callback) {
var self = this;
var cmd = '{"xpub":"' + path + '"}';
cmd = DigitalBitboxEth.aes_cbc_b64_encrypt(cmd, this.key);
var localCallback = function(response, error) {
if (typeof error != "undefined") {
callback(undefined, error);
}
else {

this.comm.exchange('{"ping":""}', function(pingResponse, pingError) {
if (typeof pingError !== 'undefined') {
callback(undefined, pingError);
return;
}
pingResponse = JSON.parse(pingResponse.toString('utf8'));
if (!('device' in pingResponse)) {
callback(undefined, 'Please upgrade to the newest firmware using the <a href="https://shiftcrypto.ch/start" target="_blank">BitBox Desktop app.</a>');
return;
}
var match = (/^v(\d+)\.\d+\.\d+/).exec(pingResponse.device.version);
if (match === null || match.length != 2) {
throw 'unexpected reply';
}
var majorVersion = parseInt(match[1]);
if (majorVersion < BitBoxSupportedMajorVersion) {
callback(undefined, 'Please upgrade to the newest firmware using the <a href="https://shiftcrypto.ch/start" target="_blank">BitBox Desktop app.</a>');
return;
}
if (majorVersion > BitBoxSupportedMajorVersion) {
callback(undefined, 'MyEtherWallet does not yet support this version of the firmware');
return;
}
var cipher = DigitalBitboxEth.aes_cbc_b64_encrypt(cmd, self.key)
self.comm.exchange(cipher, function(response, error) {
if (typeof pingError !== 'undefined') {
callback(undefined, pingError);
return;
}
try {
response = JSON.parse(response.toString('utf8'));
if ('error' in response) {
Expand All @@ -86,71 +124,62 @@ DigitalBitboxEth.prototype.getAddress = function(path, callback) {
callback(undefined, DigitalBitboxEth.parseError(response.error));
return;
}
var hdkey = HDKey.fromExtendedKey(response.xpub);
var result = {
publicKey: hdkey.publicKey.toString('hex'),
chainCode: hdkey.chainCode.toString('hex'),
};
callback(result);
return;
callback(response, undefined);
}
}
catch(err) {
callback(undefined, 'Unexpected error: ' + err.message);
}
});
});
}

DigitalBitboxEth.prototype.getAddress = function(path, callback) {
var self = this;
var cmd = '{"xpub":"' + path + '"}';
var localCallback = function(response, error) {
if (typeof error != "undefined") {
callback(undefined, error);
return;
}
var hdkey = HDKey.fromExtendedKey(response.xpub);
var result = {
publicKey: hdkey.publicKey.toString('hex'),
chainCode: hdkey.chainCode.toString('hex'),
};
callback(result);
return;
};
self.comm.exchange(cmd, localCallback);
self.send(cmd, localCallback);
}

DigitalBitboxEth.signGeneric = function(self, path, chainId, hashToSign, callback) {
var cmd = '{"sign":{"data":[{"hash":"' + hashToSign + '","keypath":"' + path + '"}]}}';
cmd = DigitalBitboxEth.aes_cbc_b64_encrypt(cmd, self.key);

var localCallback = function(response, error) {
if (typeof error != "undefined") {
callback(undefined, error);
return;
}
else {
try {
response = JSON.parse(response.toString('utf8'));
if ('error' in response) {
callback(undefined, DigitalBitboxEth.parseError(response.error));
return;
}
if ('ciphertext' in response) {
response = JSON.parse(DigitalBitboxEth.aes_cbc_b64_decrypt(response.ciphertext, self.key));
if ('error' in response) {
callback(undefined, DigitalBitboxEth.parseError(response.error));
return;
}
if ('echo' in response) {
// Echo from first sign command. (Smart verification not implemented.)
// Send second sign command.
var cmd = '{"sign":""}';
cmd = DigitalBitboxEth.aes_cbc_b64_encrypt(cmd, self.key);
self.comm.exchange(cmd, localCallback);
return;
}
if ('sign' in response) {
var vOffset = chainId ? chainId * 2 + 8 : 0;
var v = new Buffer([parseInt(response.sign[0].recid, 16) + 27 + vOffset]);
var result = {
v: v.toString('hex'),
r: response.sign[0].sig.slice(0, 64),
s: response.sign[0].sig.slice(64, 128),
};
callback(result);
return;
}
}
}
catch(err) {
callback(undefined, 'Unexpected error:' + err.message);
}
}
if ('echo' in response) {
// Echo from first sign command. (Smart verification not implemented.)
// Send second sign command.
var cmd = '{"sign":""}';
self.send(cmd, localCallback);
return;
}
if ('sign' in response) {
var vOffset = chainId ? chainId * 2 + 8 : 0;
var v = new Buffer([parseInt(response.sign[0].recid, 16) + 27 + vOffset]);
var result = {
v: v.toString('hex'),
r: response.sign[0].sig.slice(0, 64),
s: response.sign[0].sig.slice(64, 128),
};
callback(result);
return;
}
};
self.comm.exchange(cmd, localCallback);
self.send(cmd, localCallback);
}

DigitalBitboxEth.prototype.signTransaction = function(path, eTx, callback) {
Expand Down
4 changes: 2 additions & 2 deletions app/scripts/translations/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ ONBOARD_resume : 'It looks like you didn\'t finish reading thr
/* Old */
ADD_DigitalBitbox_0a : 'Re-open MyEtherWallet on a secure (SSL) connection',
ADD_DigitalBitbox_0b : 'Re-open MyEtherWallet using [Chrome](https://www.google.com/chrome/browser/desktop/) or [Opera](https://www.opera.com/)',
ADD_DigitalBitbox_scan : 'Connect your Digital Bitbox',
ADD_DigitalBitbox_scan : 'Connect your BitBox',
ADD_Secalot_0a : 'Re-open MyEtherWallet on a secure (SSL) connection ',
ADD_Secalot_0b : 'Re-open MyEtherWallet using [Chrome](https://www.google.com/chrome/browser/desktop/) or [Opera](https://www.opera.com/) ',
ADD_Secalot_scan : 'Connect your Secalot ',
Expand Down Expand Up @@ -580,7 +580,7 @@ x_Cancel : 'Cancel',
x_CancelReplaceTx : 'Cancel or Replace Transaction',
x_CancelTx : 'Cancel Transaction',
x_CSV : 'CSV file (unencrypted)',
x_DigitalBitbox : 'Digital Bitbox',
x_DigitalBitbox : 'BitBox',
x_Secalot : 'Secalot ',
x_Download : 'Download',
x_Json : 'JSON File (unencrypted)',
Expand Down

0 comments on commit 80a5376

Please sign in to comment.