added hd (bip32) support!
This commit is contained in:
parent
8405b47d04
commit
cde2757342
6 changed files with 441 additions and 10 deletions
|
@ -25,5 +25,6 @@ Coinb.in supports a number of key features such as:
|
||||||
- Compatible with bitcoin-qt
|
- Compatible with bitcoin-qt
|
||||||
- An offical .onion address for tor users.
|
- An offical .onion address for tor users.
|
||||||
- Offline qrcode creator and scanning tool
|
- Offline qrcode creator and scanning tool
|
||||||
|
- HD (bip32) support
|
||||||
|
|
||||||
Donate to 1CWHWkTWaq1K5hevimJia3cyinQsrgXUvg to see more development!
|
Donate to 1CWHWkTWaq1K5hevimJia3cyinQsrgXUvg to see more development!
|
||||||
|
|
128
index.html
128
index.html
|
@ -20,6 +20,7 @@
|
||||||
<script type="text/javascript" src="js/crypto-min.js"></script>
|
<script type="text/javascript" src="js/crypto-min.js"></script>
|
||||||
<script type="text/javascript" src="js/crypto-sha256.js"></script>
|
<script type="text/javascript" src="js/crypto-sha256.js"></script>
|
||||||
<script type="text/javascript" src="js/crypto-sha256-hmac.js"></script>
|
<script type="text/javascript" src="js/crypto-sha256-hmac.js"></script>
|
||||||
|
<script type="text/javascript" src="js/sha512.js"></script>
|
||||||
<script type="text/javascript" src="js/ripemd160.js"></script>
|
<script type="text/javascript" src="js/ripemd160.js"></script>
|
||||||
<script type="text/javascript" src="js/aes.js"></script>
|
<script type="text/javascript" src="js/aes.js"></script>
|
||||||
|
|
||||||
|
@ -53,6 +54,7 @@
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a href="#newAddress" data-toggle="tab">New Address</a></li>
|
<li><a href="#newAddress" data-toggle="tab">New Address</a></li>
|
||||||
<li><a href="#newMultiSig" data-toggle="tab">MultiSig Address</a></li>
|
<li><a href="#newMultiSig" data-toggle="tab">MultiSig Address</a></li>
|
||||||
|
<li><a href="#newHDaddress" data-toggle="tab">HD Address</a></li>
|
||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
<li><a href="#newTransaction" data-toggle="tab">Transaction</a></li>
|
<li><a href="#newTransaction" data-toggle="tab">Transaction</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -90,7 +92,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<h3><span class="glyphicon glyphicon-ok"></span> Open Source</h3>
|
<h3><span class="glyphicon glyphicon-ok"></span> Open Source</h3>
|
||||||
<p>Coinbin is an open source web based wallet written in javascript and released under the <a href="LICENCE">MIT licence</a> which means its free to use and edit.</p>
|
<p>Coinbin is an open source web based wallet written in javascript and released under the <a href="LICENSE">MIT license</a> which means its free to use and edit.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
|
@ -361,6 +363,37 @@
|
||||||
<br>
|
<br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-pane tab-content" id="newHDaddress">
|
||||||
|
<h2>New HD Address <small>making bip32 even easier</small></h2>
|
||||||
|
<p>Use the form below to generate a <i>master</i> hierarchical deterministic address.</p>
|
||||||
|
|
||||||
|
<label>xPub Address</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<input id="newHDxpub" type="text" class="form-control" value="" readonly>
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button class="deriveHDbtn btn btn-default" type="button"><span title="Derive from key" class="glyphicon glyphicon-chevron-right"></span></button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label>xPrv Address</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<input id="newHDxprv" type="text" class="form-control" value="" readonly>
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button class="deriveHDbtn btn btn-default" type="button"><span title="Derive from key" class="glyphicon glyphicon-chevron-right"></span></button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>Address Options</h3>
|
||||||
|
<p>You can use the advanced options below to generate different kind of master address.</p>
|
||||||
|
|
||||||
|
<div class="checkbox">
|
||||||
|
<label><input type="checkbox" id="newHDBrainwallet" class="checkbox-inline"> Custom Seed or Brain Wallet</label>
|
||||||
|
<input type="text" class="form-control hidden" id="HDBrainwallet">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="button" class="btn btn-primary" value="Generate" id="newHDKeysBtn">
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane tab-content" id="newTransaction">
|
<div class="tab-pane tab-content" id="newTransaction">
|
||||||
<h2>Transaction <small>Create a new transaction</small></h2>
|
<h2>Transaction <small>Create a new transaction</small></h2>
|
||||||
<p>Use this page to create a raw transaction</p>
|
<p>Use this page to create a raw transaction</p>
|
||||||
|
@ -518,7 +551,7 @@
|
||||||
<h2>Verify <small>transactions and other scripts</small></h2>
|
<h2>Verify <small>transactions and other scripts</small></h2>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<p>Enter the raw transaction, redeem script, pubkey or wif key to convert it into a readable format that can be verified manually.</p>
|
<p>Enter the raw transaction, redeem script, pubkey, hd address or wif key to convert it into a readable format that can be verified manually.</p>
|
||||||
<textarea type="text" id="verifyScript" class="form-control" style="height:125px"></textarea>
|
<textarea type="text" id="verifyScript" class="form-control" style="height:125px"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -595,6 +628,95 @@
|
||||||
<p><b>Address</b>: <input type="text" class="form-control address" readonly></p>
|
<p><b>Address</b>: <input type="text" class="form-control address" readonly></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="hidden verifyData" id="verifyHDaddress">
|
||||||
|
<h4>HD Address</h4>
|
||||||
|
<p><span style="float:right"><a href="" target="_blank" class="verifyLink" title="Link to this page"><span class="glyphicon glyphicon-link"></span></a></span>The key <small><span class="hdKey hidden"></span></small> has been decoded</p>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-2">
|
||||||
|
<b>Type</b><br>
|
||||||
|
<span class="key_type"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-5">
|
||||||
|
<b>Chain Code</b><br>
|
||||||
|
<input type="text" class="form-control chain_code" value="" readonly>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-md-5">
|
||||||
|
<b>Key</b><br>
|
||||||
|
<input type="text" class="form-control hdwifkey" value="" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<b>Version</b><br>
|
||||||
|
<input type="text" class="form-control version" value="" readonly>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<b>Parent FingerPrint</b><br>
|
||||||
|
<input type="text" class="form-control parent_fingerprint" value="" readonly>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<b>Depth</b><br>
|
||||||
|
<input type="text" class="form-control depth" value="" readonly>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<b>Index</b><br>
|
||||||
|
<input type="text" class="form-control child_index" value="" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h4>Key Derivation</h4>
|
||||||
|
<p>The path of key derivation</p>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<b>Path</b><br>
|
||||||
|
<select class="form-control">
|
||||||
|
<option>Simple: m/i</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-2">
|
||||||
|
<b>Index (Start)</b><br>
|
||||||
|
<input type="text" class="form-control derivation_index_start" value="0">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-2">
|
||||||
|
<b>Index (End)</b><br>
|
||||||
|
<input type="text" class="form-control derivation_index_end" value="1">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4>Keys</h4>
|
||||||
|
|
||||||
|
<p>Keys derived from the hd address provided</p>
|
||||||
|
|
||||||
|
<div class="derived_data">
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr><td><b>Index</b></td><td><b>Address</b><td><b>Private Key (WIF)</b></td></td><td><b>Extended xPub</b></td><td><b>Extended xPrv</b></td></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="verifyStatus" class="alert alert-danger hidden"><span class="glyphicon glyphicon-exclamation-sign"></span> Unable to decode</div>
|
<div id="verifyStatus" class="alert alert-danger hidden"><span class="glyphicon glyphicon-exclamation-sign"></span> Unable to decode</div>
|
||||||
|
|
||||||
<input type="button" value="Submit" class="btn btn-primary" id="verifyBtn">
|
<input type="button" value="Submit" class="btn btn-primary" id="verifyBtn">
|
||||||
|
@ -663,7 +785,7 @@
|
||||||
<p>Github <a href="https://github.com/OutCast3k/coinbin/">https://github.com/OutCast3k/coinbin/</a></p>
|
<p>Github <a href="https://github.com/OutCast3k/coinbin/">https://github.com/OutCast3k/coinbin/</a></p>
|
||||||
<p>TOR <a href="http://4zpinp6gdkjfplhk.onion">4zpinp6gdkjfplhk.onion</a></p>
|
<p>TOR <a href="http://4zpinp6gdkjfplhk.onion">4zpinp6gdkjfplhk.onion</a></p>
|
||||||
<h3>Information</h3>
|
<h3>Information</h3>
|
||||||
<p>Coinb.in is a free and open source project released under the MIT licence, originally by <a href="https://bitcointalk.org/index.php?action=profile;u=34834" target="_blank">OutCast3k</a> in 2013. Discussion of the project can be found at <a href="https://bitcointalk.org/index.php?topic=390046" target="_blank">bitcointalk.org</a> during its early testing stages when its primary focus was to develop a proof of concept multisig solution in javascript.</p>
|
<p>Coinb.in is a free and open source project released under the MIT license, originally by <a href="https://bitcointalk.org/index.php?action=profile;u=34834" target="_blank">OutCast3k</a> in 2013. Discussion of the project can be found at <a href="https://bitcointalk.org/index.php?topic=390046" target="_blank">bitcointalk.org</a> during its early testing stages when its primary focus was to develop a proof of concept multisig solution in javascript.</p>
|
||||||
<p>Coinb.in is run and funded by the generosity of others in terms of <a href="https://github.com/OutCast3k/coinbin/graphs/contributors" target="_blank">development</a> and hosting.</p>
|
<p>Coinb.in is run and funded by the generosity of others in terms of <a href="https://github.com/OutCast3k/coinbin/graphs/contributors" target="_blank">development</a> and hosting.</p>
|
||||||
<h3>Privacy</h3>
|
<h3>Privacy</h3>
|
||||||
<p>Coinb.in beleives strongly in privacy, not only do we support the use of TOR, the site does not collect and store IP or transaction data via our servers nor do we store your bitcoins private key. We do use google analytics to track hits and route traffic via cloudflare using an SSL certificate.</p>
|
<p>Coinb.in beleives strongly in privacy, not only do we support the use of TOR, the site does not collect and store IP or transaction data via our servers nor do we store your bitcoins private key. We do use google analytics to track hits and route traffic via cloudflare using an SSL certificate.</p>
|
||||||
|
|
213
js/coin.js
213
js/coin.js
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Coinjs 0.01 beta by OutCast3k{at}gmail.com
|
Coinjs 0.01 beta by OutCast3k{at}gmail.com
|
||||||
A bitcoin framework loosely based on bitcoinjs.
|
A bitcoin frameworkcoinjs.
|
||||||
|
|
||||||
http://github.com/OutCast3k/coinjs or http://coinb.in/coinjs
|
http://github.com/OutCast3k/coinjs or http://coinb.in/coinjs
|
||||||
*/
|
*/
|
||||||
|
@ -13,10 +13,12 @@
|
||||||
coinjs.pub = 0x00;
|
coinjs.pub = 0x00;
|
||||||
coinjs.priv = 0x80;
|
coinjs.priv = 0x80;
|
||||||
coinjs.multisig = 0x05;
|
coinjs.multisig = 0x05;
|
||||||
|
coinjs.hdkey = {'prv':0x0488ade4, 'pub':0x0488b21e};
|
||||||
|
|
||||||
coinjs.compressed = false;
|
coinjs.compressed = false;
|
||||||
|
|
||||||
/* other vars */
|
/* other vars */
|
||||||
coinjs.developer = '1CWHWkTWaq1K5hevimJia3cyinQsrgXUvg';
|
coinjs.developer = '1CWHWkTWaq1K5hevimJia3cyinQsrgXUvg'; // bitcoin
|
||||||
|
|
||||||
/* bit(coinb.in) api vars */
|
/* bit(coinb.in) api vars */
|
||||||
coinjs.host = ('https:'==document.location.protocol?'https://':'http://')+'coinb.in/api/';
|
coinjs.host = ('https:'==document.location.protocol?'https://':'http://')+'coinb.in/api/';
|
||||||
|
@ -26,8 +28,8 @@
|
||||||
/* start of address functions */
|
/* start of address functions */
|
||||||
|
|
||||||
/* generate a private and public keypair, with address and WIF address */
|
/* generate a private and public keypair, with address and WIF address */
|
||||||
coinjs.newKeys = function(string){
|
coinjs.newKeys = function(input){
|
||||||
var privkey = (string) ? Crypto.SHA256(string) : this.newPrivkey();
|
var privkey = (input) ? Crypto.SHA256(input) : this.newPrivkey();
|
||||||
var pubkey = this.newPubkey(privkey);
|
var pubkey = this.newPubkey(privkey);
|
||||||
return {
|
return {
|
||||||
'privkey': privkey,
|
'privkey': privkey,
|
||||||
|
@ -376,9 +378,199 @@
|
||||||
return result_txt;
|
return result_txt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* start of hd functions, thanks bip32.org */
|
||||||
|
coinjs.hd = function(data){
|
||||||
|
|
||||||
|
var r = {};
|
||||||
|
|
||||||
|
/* some hd value parsing */
|
||||||
|
r.parse = function() {
|
||||||
|
|
||||||
|
var bytes = [];
|
||||||
|
|
||||||
|
// some quick validation
|
||||||
|
if(typeof(data) == 'string'){
|
||||||
|
var decoded = coinjs.base58decode(data);
|
||||||
|
if(decoded.length == 82){
|
||||||
|
var checksum = decoded.slice(78, 82);
|
||||||
|
var hash = Crypto.SHA256(Crypto.SHA256(decoded.slice(0, 78), { asBytes: true } ), { asBytes: true } );
|
||||||
|
if(checksum[0]==hash[0] && checksum[1]==hash[1] && checksum[2]==hash[2] && checksum[3]==hash[3]){
|
||||||
|
bytes = decoded.slice(0, 78);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// actual parsing code
|
||||||
|
if(bytes && bytes.length>0) {
|
||||||
|
r.version = coinjs.uint(bytes.slice(0, 4) , 4);
|
||||||
|
r.depth = coinjs.uint(bytes.slice(4, 5) ,1);
|
||||||
|
r.parent_fingerprint = bytes.slice(5, 9);
|
||||||
|
r.child_index = coinjs.uint(bytes.slice(9, 13), 4);
|
||||||
|
r.chain_code = bytes.slice(13, 45);
|
||||||
|
r.key_bytes = bytes.slice(45, 78);
|
||||||
|
|
||||||
|
var c = coinjs.compressed; // get current default
|
||||||
|
coinjs.compressed = true;
|
||||||
|
|
||||||
|
if(r.key_bytes[0] == 0x00) {
|
||||||
|
r.type = 'private';
|
||||||
|
var privkey = (r.key_bytes).slice(1, 33);
|
||||||
|
var privkeyHex = Crypto.util.bytesToHex(privkey);
|
||||||
|
var pubkey = coinjs.newPubkey(privkeyHex);
|
||||||
|
|
||||||
|
r.keys = {'privkey':privkeyHex,
|
||||||
|
'pubkey':pubkey,
|
||||||
|
'address':coinjs.pubkey2address(pubkey),
|
||||||
|
'wif':coinjs.privkey2wif(privkeyHex)};
|
||||||
|
|
||||||
|
} else if(r.key_bytes[0] == 0x02 || r.key_bytes[0] == 0x03) {
|
||||||
|
r.type = 'public';
|
||||||
|
var pubkeyHex = Crypto.util.bytesToHex(r.key_bytes);
|
||||||
|
|
||||||
|
r.keys = {'pubkey': pubkeyHex,
|
||||||
|
'address':coinjs.pubkey2address(pubkeyHex)};
|
||||||
|
} else {
|
||||||
|
r.type = 'invalid';
|
||||||
|
}
|
||||||
|
|
||||||
|
r.keys_extended = r.extend();
|
||||||
|
|
||||||
|
coinjs.compressed = c; // reset to default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r.extend = function(){
|
||||||
|
var hd = coinjs.hd();
|
||||||
|
return hd.make({'depth':(this.depth*1)+1,
|
||||||
|
'parent_fingerprint':this.parent_fingerprint,
|
||||||
|
'child_index':this.child_index,
|
||||||
|
'chain_code':this.chain_code,
|
||||||
|
'privkey':this.keys.privkey,
|
||||||
|
'pubkey':this.keys.pubkey});
|
||||||
|
}
|
||||||
|
|
||||||
|
r.derive = function(i){
|
||||||
|
i = (i)?i:0;
|
||||||
|
var blob = (Crypto.util.hexToBytes(this.keys.pubkey)).concat(coinjs.numToBytes(i,4).reverse());
|
||||||
|
|
||||||
|
var j = new jsSHA(Crypto.util.bytesToHex(blob), 'HEX');
|
||||||
|
var hash = j.getHMAC(Crypto.util.bytesToHex(r.chain_code), "HEX", "SHA-512", "HEX");
|
||||||
|
|
||||||
|
var il = new BigInteger(hash.slice(0, 64), 16);
|
||||||
|
var ir = Crypto.util.hexToBytes(hash.slice(64,128));
|
||||||
|
|
||||||
|
var ecparams = EllipticCurve.getSECCurveByName("secp256k1");
|
||||||
|
var curve = ecparams.getCurve();
|
||||||
|
|
||||||
|
var k, key, pubkey, o;
|
||||||
|
|
||||||
|
o = coinjs.clone(this);
|
||||||
|
o.chain_code = ir;
|
||||||
|
o.child_index = i;
|
||||||
|
|
||||||
|
if(this.type=='private'){
|
||||||
|
k = il.add(new BigInteger([0].concat(Crypto.util.hexToBytes(this.keys.privkey)))).mod(ecparams.getN());
|
||||||
|
key = Crypto.util.bytesToHex(k.toByteArrayUnsigned());
|
||||||
|
|
||||||
|
pubkey = coinjs.newPubkey(key);
|
||||||
|
|
||||||
|
o.keys = {'privkey':key,
|
||||||
|
'pubkey':pubkey,
|
||||||
|
'wif':coinjs.privkey2wif(key),
|
||||||
|
'address':coinjs.pubkey2address(pubkey)};
|
||||||
|
|
||||||
|
} else if (this.type=='public'){
|
||||||
|
q = ecparams.curve.decodePointHex(this.keys.pubkey);
|
||||||
|
var curvePt = ecparams.getG().multiply(il).add(q);
|
||||||
|
|
||||||
|
var x = curvePt.getX().toBigInteger();
|
||||||
|
var y = curvePt.getY().toBigInteger();
|
||||||
|
|
||||||
|
var publicKeyBytesCompressed = EllipticCurve.integerToBytes(x,32)
|
||||||
|
if (y.isEven()){
|
||||||
|
publicKeyBytesCompressed.unshift(0x02)
|
||||||
|
} else {
|
||||||
|
publicKeyBytesCompressed.unshift(0x03)
|
||||||
|
}
|
||||||
|
pubkey = Crypto.util.bytesToHex(publicKeyBytesCompressed);
|
||||||
|
|
||||||
|
o.keys = {'pubkey':pubkey,
|
||||||
|
'address':coinjs.pubkey2address(pubkey)}
|
||||||
|
} else {
|
||||||
|
// fail
|
||||||
|
}
|
||||||
|
|
||||||
|
o.parent_fingerprint = (ripemd160(Crypto.SHA256(Crypto.util.hexToBytes(r.keys.pubkey),{asBytes:true}),{asBytes:true})).slice(0,4);
|
||||||
|
o.keys_extended = o.extend();
|
||||||
|
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
r.master = function(pass) {
|
||||||
|
var seed = (pass) ? Crypto.SHA256(pass) : coinjs.newPrivkey();
|
||||||
|
var hasher = new jsSHA(seed, 'HEX');
|
||||||
|
var I = hasher.getHMAC("Bitcoin seed", "TEXT", "SHA-512", "HEX");
|
||||||
|
|
||||||
|
var privkey = Crypto.util.hexToBytes(I.slice(0, 64));
|
||||||
|
var chain = Crypto.util.hexToBytes(I.slice(64, 128));
|
||||||
|
|
||||||
|
var hd = coinjs.hd();
|
||||||
|
return hd.make({'depth':0,
|
||||||
|
'parent_fingerprint':[0,0,0,0],
|
||||||
|
'child_index':0,
|
||||||
|
'chain_code':chain,
|
||||||
|
'privkey':I.slice(0, 64),
|
||||||
|
'pubkey':coinjs.newPubkey(I.slice(0, 64))});
|
||||||
|
}
|
||||||
|
|
||||||
|
r.make = function(data){ // { (int) depth, (array) parent_fingerprint, (int) child_index, (byte array) chain_code, (hex str) privkey, (hex str) pubkey}
|
||||||
|
var k = [];
|
||||||
|
|
||||||
|
//depth
|
||||||
|
k.push(data.depth*1);
|
||||||
|
|
||||||
|
//parent fingerprint
|
||||||
|
k = k.concat(data.parent_fingerprint);
|
||||||
|
|
||||||
|
//child index
|
||||||
|
k = k.concat((coinjs.numToBytes(data.child_index, 4)).reverse());
|
||||||
|
|
||||||
|
// Chain code
|
||||||
|
k = k.concat(data.chain_code);
|
||||||
|
|
||||||
|
var o = {}; // results
|
||||||
|
|
||||||
|
// Extended HD Private Key
|
||||||
|
if(data.privkey){
|
||||||
|
var prv = (coinjs.numToBytes(coinjs.hdkey.prv, 4)).reverse();
|
||||||
|
prv = prv.concat(k);
|
||||||
|
prv.push(0x00);
|
||||||
|
prv = prv.concat(Crypto.util.hexToBytes(data.privkey));
|
||||||
|
var hash = Crypto.SHA256( Crypto.SHA256(prv, { asBytes: true } ), { asBytes: true } );
|
||||||
|
var checksum = hash.slice(0, 4);
|
||||||
|
var ret = prv.concat(checksum);
|
||||||
|
o.privkey = coinjs.base58encode(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extended HD Public Key
|
||||||
|
if(data.pubkey){
|
||||||
|
var pub = (coinjs.numToBytes(coinjs.hdkey.pub, 4)).reverse();
|
||||||
|
pub = pub.concat(k);
|
||||||
|
pub = pub.concat(Crypto.util.hexToBytes(data.pubkey));
|
||||||
|
var hash = Crypto.SHA256( Crypto.SHA256(pub, { asBytes: true } ), { asBytes: true } );
|
||||||
|
var checksum = hash.slice(0, 4);
|
||||||
|
var ret = pub.concat(checksum);
|
||||||
|
o.pubkey = coinjs.base58encode(ret);
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
r.parse();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* start of script functions */
|
/* start of script functions */
|
||||||
|
|
||||||
coinjs.script = function(data) {
|
coinjs.script = function(data) {
|
||||||
var r = {};
|
var r = {};
|
||||||
|
|
||||||
|
@ -1211,6 +1403,17 @@
|
||||||
else return bytes[0] + 256 * coinjs.bytesToNum(bytes.slice(1));
|
else return bytes[0] + 256 * coinjs.bytesToNum(bytes.slice(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
coinjs.uint = function(f, size) {
|
||||||
|
if (f.length < size)
|
||||||
|
throw new Error("not enough data");
|
||||||
|
var n = 0;
|
||||||
|
for (var i = 0; i < size; i++) {
|
||||||
|
n *= 256;
|
||||||
|
n += f[i];
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
coinjs.isArray = function(o){
|
coinjs.isArray = function(o){
|
||||||
return Object.prototype.toString.call(o) === '[object Array]';
|
return Object.prototype.toString.call(o) === '[object Array]';
|
||||||
}
|
}
|
||||||
|
|
|
@ -331,6 +331,32 @@ $(document).ready(function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* new -> Hd address code */
|
||||||
|
|
||||||
|
$(".deriveHDbtn").click(function(){
|
||||||
|
$("#verifyScript").val($("input[type='text']",$(this).parent().parent()).val());
|
||||||
|
window.location = "#verify";
|
||||||
|
$("#verifyBtn").click();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#newHDKeysBtn").click(function(){
|
||||||
|
coinjs.compressed = true;
|
||||||
|
var s = ($("#newHDBrainwallet").is(":checked")) ? $("#HDBrainwallet").val() : null;
|
||||||
|
var hd = coinjs.hd();
|
||||||
|
var pair = hd.master(s);
|
||||||
|
$("#newHDxpub").val(pair.pubkey);
|
||||||
|
$("#newHDxprv").val(pair.privkey);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#newHDBrainwallet").click(function(){
|
||||||
|
if($(this).is(":checked")){
|
||||||
|
$("#HDBrainwallet").removeClass("hidden");
|
||||||
|
} else {
|
||||||
|
$("#HDBrainwallet").addClass("hidden");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/* new -> transaction code */
|
/* new -> transaction code */
|
||||||
|
|
||||||
$("#recipients .addressAddTo").click(function(){
|
$("#recipients .addressAddTo").click(function(){
|
||||||
|
@ -626,11 +652,13 @@ $(document).ready(function() {
|
||||||
if(!decodeTransactionScript()){
|
if(!decodeTransactionScript()){
|
||||||
if(!decodePrivKey()){
|
if(!decodePrivKey()){
|
||||||
if(!decodePubKey()){
|
if(!decodePubKey()){
|
||||||
|
if(!decodeHDaddress()){
|
||||||
$("#verifyStatus").removeClass('hidden').fadeOut().fadeIn();
|
$("#verifyStatus").removeClass('hidden').fadeOut().fadeIn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -780,6 +808,50 @@ $(document).ready(function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function decodeHDaddress(){
|
||||||
|
var s = $("#verifyScript").val();
|
||||||
|
if(s.match(/^x[prv|pub]/)){
|
||||||
|
try {
|
||||||
|
var hd = coinjs.hd(s);
|
||||||
|
$("#verifyHDaddress .hdKey").html(s);
|
||||||
|
$("#verifyHDaddress .chain_code").val(Crypto.util.bytesToHex(hd.chain_code));
|
||||||
|
$("#verifyHDaddress .depth").val(hd.depth);
|
||||||
|
$("#verifyHDaddress .version").val('0x'+(hd.version).toString(16));
|
||||||
|
$("#verifyHDaddress .child_index").val(hd.child_index);
|
||||||
|
$("#verifyHDaddress .hdwifkey").val((hd.keys.wif)?hd.keys.wif:'');
|
||||||
|
$("#verifyHDaddress .key_type").html((((hd.depth==0 && hd.child_index==0)?'Master':'Derived')+' '+hd.type).toLowerCase());
|
||||||
|
$("#verifyHDaddress .parent_fingerprint").val(Crypto.util.bytesToHex(hd.parent_fingerprint));
|
||||||
|
$("#verifyHDaddress .derived_data table tbody").html("");
|
||||||
|
deriveHDaddress();
|
||||||
|
$(".verifyLink").attr('href','?verify='+$("#verifyScript").val());
|
||||||
|
$("#verifyHDaddress").removeClass("hidden");
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deriveHDaddress() {
|
||||||
|
var hd = coinjs.hd($("#verifyHDaddress .hdKey").html());
|
||||||
|
var index_start = $("#verifyHDaddress .derivation_index_start").val()*1;
|
||||||
|
var index_end = $("#verifyHDaddress .derivation_index_end").val()*1;
|
||||||
|
var html = '';
|
||||||
|
$("#verifyHDaddress .derived_data table tbody").html("");
|
||||||
|
for(var i=index_start;i<=index_end;i++){
|
||||||
|
var derived = hd.derive(i);
|
||||||
|
html += '<tr>';
|
||||||
|
html += '<td>'+i+'</td>';
|
||||||
|
html += '<td><input type="text" class="form-control" value="'+derived.keys.address+'" readonly></td>';
|
||||||
|
html += '<td><input type="text" class="form-control" value="'+((derived.keys.wif)?derived.keys.wif:'')+'" readonly></td>';
|
||||||
|
html += '<td><input type="text" class="form-control" value="'+derived.keys_extended.pubkey+'" readonly></td>';
|
||||||
|
html += '<td><input type="text" class="form-control" value="'+((derived.keys_extended.privkey)?derived.keys_extended.privkey:'')+'" readonly></td>';
|
||||||
|
html += '</tr>';
|
||||||
|
}
|
||||||
|
$(html).appendTo("#verifyHDaddress .derived_data table tbody");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* sign code */
|
/* sign code */
|
||||||
|
|
||||||
$("#signBtn").click(function(){
|
$("#signBtn").click(function(){
|
||||||
|
@ -894,7 +966,8 @@ $(document).ready(function() {
|
||||||
$(".pubkeyAdd").click();
|
$(".pubkeyAdd").click();
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#newKeysBtn").click();
|
$("#newKeysBtn, #newHDKeysBtn").click();
|
||||||
|
|
||||||
|
|
||||||
validateOutputAmount();
|
validateOutputAmount();
|
||||||
|
|
||||||
|
|
32
js/sha512.js
Normal file
32
js/sha512.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
(function() {/*
|
||||||
|
A JavaScript implementation of the SHA family of hashes, as defined in FIPS
|
||||||
|
PUB 180-2 as well as the corresponding HMAC implementation as defined in
|
||||||
|
FIPS PUB 198a
|
||||||
|
|
||||||
|
Copyright Brian Turek 2008-2012
|
||||||
|
Distributed under the BSD License
|
||||||
|
See http://caligatio.github.com/jsSHA/ for more information
|
||||||
|
|
||||||
|
Several functions taken from Paul Johnson
|
||||||
|
*/
|
||||||
|
function n(a){throw a;}var q=null;function s(a,b){this.a=a;this.b=b}function u(a,b){var d=[],h=(1<<b)-1,f=a.length*b,g;for(g=0;g<f;g+=b)d[g>>>5]|=(a.charCodeAt(g/b)&h)<<32-b-g%32;return{value:d,binLen:f}}function x(a){var b=[],d=a.length,h,f;0!==d%2&&n("String of HEX type must be in byte increments");for(h=0;h<d;h+=2)f=parseInt(a.substr(h,2),16),isNaN(f)&&n("String of HEX type contains invalid characters"),b[h>>>3]|=f<<24-4*(h%8);return{value:b,binLen:4*d}}
|
||||||
|
function B(a){var b=[],d=0,h,f,g,k,m;-1===a.search(/^[a-zA-Z0-9=+\/]+$/)&&n("Invalid character in base-64 string");h=a.indexOf("=");a=a.replace(/\=/g,"");-1!==h&&h<a.length&&n("Invalid '=' found in base-64 string");for(f=0;f<a.length;f+=4){m=a.substr(f,4);for(g=k=0;g<m.length;g+=1)h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(m[g]),k|=h<<18-6*g;for(g=0;g<m.length-1;g+=1)b[d>>2]|=(k>>>16-8*g&255)<<24-8*(d%4),d+=1}return{value:b,binLen:8*d}}
|
||||||
|
function E(a,b){var d="",h=4*a.length,f,g;for(f=0;f<h;f+=1)g=a[f>>>2]>>>8*(3-f%4),d+="0123456789abcdef".charAt(g>>>4&15)+"0123456789abcdef".charAt(g&15);return b.outputUpper?d.toUpperCase():d}
|
||||||
|
function F(a,b){var d="",h=4*a.length,f,g,k;for(f=0;f<h;f+=3){k=(a[f>>>2]>>>8*(3-f%4)&255)<<16|(a[f+1>>>2]>>>8*(3-(f+1)%4)&255)<<8|a[f+2>>>2]>>>8*(3-(f+2)%4)&255;for(g=0;4>g;g+=1)d=8*f+6*g<=32*a.length?d+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(k>>>6*(3-g)&63):d+b.b64Pad}return d}
|
||||||
|
function G(a){var b={outputUpper:!1,b64Pad:"="};try{a.hasOwnProperty("outputUpper")&&(b.outputUpper=a.outputUpper),a.hasOwnProperty("b64Pad")&&(b.b64Pad=a.b64Pad)}catch(d){}"boolean"!==typeof b.outputUpper&&n("Invalid outputUpper formatting option");"string"!==typeof b.b64Pad&&n("Invalid b64Pad formatting option");return b}
|
||||||
|
function H(a,b){var d=q,d=new s(a.a,a.b);return d=32>=b?new s(d.a>>>b|d.b<<32-b&4294967295,d.b>>>b|d.a<<32-b&4294967295):new s(d.b>>>b-32|d.a<<64-b&4294967295,d.a>>>b-32|d.b<<64-b&4294967295)}function I(a,b){var d=q;return d=32>=b?new s(a.a>>>b,a.b>>>b|a.a<<32-b&4294967295):new s(0,a.a>>>b-32)}function J(a,b,d){return new s(a.a&b.a^~a.a&d.a,a.b&b.b^~a.b&d.b)}function U(a,b,d){return new s(a.a&b.a^a.a&d.a^b.a&d.a,a.b&b.b^a.b&d.b^b.b&d.b)}
|
||||||
|
function V(a){var b=H(a,28),d=H(a,34);a=H(a,39);return new s(b.a^d.a^a.a,b.b^d.b^a.b)}function W(a){var b=H(a,14),d=H(a,18);a=H(a,41);return new s(b.a^d.a^a.a,b.b^d.b^a.b)}function X(a){var b=H(a,1),d=H(a,8);a=I(a,7);return new s(b.a^d.a^a.a,b.b^d.b^a.b)}function Y(a){var b=H(a,19),d=H(a,61);a=I(a,6);return new s(b.a^d.a^a.a,b.b^d.b^a.b)}
|
||||||
|
function Z(a,b){var d,h,f;d=(a.b&65535)+(b.b&65535);h=(a.b>>>16)+(b.b>>>16)+(d>>>16);f=(h&65535)<<16|d&65535;d=(a.a&65535)+(b.a&65535)+(h>>>16);h=(a.a>>>16)+(b.a>>>16)+(d>>>16);return new s((h&65535)<<16|d&65535,f)}
|
||||||
|
function aa(a,b,d,h){var f,g,k;f=(a.b&65535)+(b.b&65535)+(d.b&65535)+(h.b&65535);g=(a.b>>>16)+(b.b>>>16)+(d.b>>>16)+(h.b>>>16)+(f>>>16);k=(g&65535)<<16|f&65535;f=(a.a&65535)+(b.a&65535)+(d.a&65535)+(h.a&65535)+(g>>>16);g=(a.a>>>16)+(b.a>>>16)+(d.a>>>16)+(h.a>>>16)+(f>>>16);return new s((g&65535)<<16|f&65535,k)}
|
||||||
|
function ba(a,b,d,h,f){var g,k,m;g=(a.b&65535)+(b.b&65535)+(d.b&65535)+(h.b&65535)+(f.b&65535);k=(a.b>>>16)+(b.b>>>16)+(d.b>>>16)+(h.b>>>16)+(f.b>>>16)+(g>>>16);m=(k&65535)<<16|g&65535;g=(a.a&65535)+(b.a&65535)+(d.a&65535)+(h.a&65535)+(f.a&65535)+(k>>>16);k=(a.a>>>16)+(b.a>>>16)+(d.a>>>16)+(h.a>>>16)+(f.a>>>16)+(g>>>16);return new s((k&65535)<<16|g&65535,m)}
|
||||||
|
function $(a,b,d){var h,f,g,k,m,j,A,C,K,e,L,v,l,M,t,p,y,z,r,N,O,P,Q,R,c,S,w=[],T,D;"SHA-384"===d||"SHA-512"===d?(L=80,h=(b+128>>>10<<5)+31,M=32,t=2,c=s,p=Z,y=aa,z=ba,r=X,N=Y,O=V,P=W,R=U,Q=J,S=[new c(1116352408,3609767458),new c(1899447441,602891725),new c(3049323471,3964484399),new c(3921009573,2173295548),new c(961987163,4081628472),new c(1508970993,3053834265),new c(2453635748,2937671579),new c(2870763221,3664609560),new c(3624381080,2734883394),new c(310598401,1164996542),new c(607225278,1323610764),
|
||||||
|
new c(1426881987,3590304994),new c(1925078388,4068182383),new c(2162078206,991336113),new c(2614888103,633803317),new c(3248222580,3479774868),new c(3835390401,2666613458),new c(4022224774,944711139),new c(264347078,2341262773),new c(604807628,2007800933),new c(770255983,1495990901),new c(1249150122,1856431235),new c(1555081692,3175218132),new c(1996064986,2198950837),new c(2554220882,3999719339),new c(2821834349,766784016),new c(2952996808,2566594879),new c(3210313671,3203337956),new c(3336571891,
|
||||||
|
1034457026),new c(3584528711,2466948901),new c(113926993,3758326383),new c(338241895,168717936),new c(666307205,1188179964),new c(773529912,1546045734),new c(1294757372,1522805485),new c(1396182291,2643833823),new c(1695183700,2343527390),new c(1986661051,1014477480),new c(2177026350,1206759142),new c(2456956037,344077627),new c(2730485921,1290863460),new c(2820302411,3158454273),new c(3259730800,3505952657),new c(3345764771,106217008),new c(3516065817,3606008344),new c(3600352804,1432725776),new c(4094571909,
|
||||||
|
1467031594),new c(275423344,851169720),new c(430227734,3100823752),new c(506948616,1363258195),new c(659060556,3750685593),new c(883997877,3785050280),new c(958139571,3318307427),new c(1322822218,3812723403),new c(1537002063,2003034995),new c(1747873779,3602036899),new c(1955562222,1575990012),new c(2024104815,1125592928),new c(2227730452,2716904306),new c(2361852424,442776044),new c(2428436474,593698344),new c(2756734187,3733110249),new c(3204031479,2999351573),new c(3329325298,3815920427),new c(3391569614,
|
||||||
|
3928383900),new c(3515267271,566280711),new c(3940187606,3454069534),new c(4118630271,4000239992),new c(116418474,1914138554),new c(174292421,2731055270),new c(289380356,3203993006),new c(460393269,320620315),new c(685471733,587496836),new c(852142971,1086792851),new c(1017036298,365543100),new c(1126000580,2618297676),new c(1288033470,3409855158),new c(1501505948,4234509866),new c(1607167915,987167468),new c(1816402316,1246189591)],e="SHA-384"===d?[new c(3418070365,3238371032),new c(1654270250,914150663),
|
||||||
|
new c(2438529370,812702999),new c(355462360,4144912697),new c(1731405415,4290775857),new c(41048885895,1750603025),new c(3675008525,1694076839),new c(1203062813,3204075428)]:[new c(1779033703,4089235720),new c(3144134277,2227873595),new c(1013904242,4271175723),new c(2773480762,1595750129),new c(1359893119,2917565137),new c(2600822924,725511199),new c(528734635,4215389547),new c(1541459225,327033209)]):n("Unexpected error in SHA-2 implementation");a[b>>>5]|=128<<24-b%32;a[h]=b;T=a.length;for(v=0;v<
|
||||||
|
T;v+=M){b=e[0];h=e[1];f=e[2];g=e[3];k=e[4];m=e[5];j=e[6];A=e[7];for(l=0;l<L;l+=1)w[l]=16>l?new c(a[l*t+v],a[l*t+v+1]):y(N(w[l-2]),w[l-7],r(w[l-15]),w[l-16]),C=z(A,P(k),Q(k,m,j),S[l],w[l]),K=p(O(b),R(b,h,f)),A=j,j=m,m=k,k=p(g,C),g=f,f=h,h=b,b=p(C,K);e[0]=p(b,e[0]);e[1]=p(h,e[1]);e[2]=p(f,e[2]);e[3]=p(g,e[3]);e[4]=p(k,e[4]);e[5]=p(m,e[5]);e[6]=p(j,e[6]);e[7]=p(A,e[7])}"SHA-384"===d?D=[e[0].a,e[0].b,e[1].a,e[1].b,e[2].a,e[2].b,e[3].a,e[3].b,e[4].a,e[4].b,e[5].a,e[5].b]:"SHA-512"===d?D=[e[0].a,e[0].b,
|
||||||
|
e[1].a,e[1].b,e[2].a,e[2].b,e[3].a,e[3].b,e[4].a,e[4].b,e[5].a,e[5].b,e[6].a,e[6].b,e[7].a,e[7].b]:n("Unexpected error in SHA-2 implementation");return D}
|
||||||
|
window.jsSHA=function(a,b,d){var h=q,f=q,g=0,k=[0],m=0,j=q,m="undefined"!==typeof d?d:8;8===m||16===m||n("charSize must be 8 or 16");"HEX"===b?(0!==a.length%2&&n("srcString of HEX type must be in byte increments"),j=x(a),g=j.binLen,k=j.value):"ASCII"===b||"TEXT"===b?(j=u(a,m),g=j.binLen,k=j.value):"B64"===b?(j=B(a),g=j.binLen,k=j.value):n("inputFormat must be HEX, TEXT, ASCII, or B64");this.getHash=function(a,b,d){var e=q,m=k.slice(),j="";switch(b){case "HEX":e=E;break;case "B64":e=F;break;default:n("format must be HEX or B64")}"SHA-384"===
|
||||||
|
a?(q===h&&(h=$(m,g,a)),j=e(h,G(d))):"SHA-512"===a?(q===f&&(f=$(m,g,a)),j=e(f,G(d))):n("Chosen SHA variant is not supported");return j};this.getHMAC=function(a,b,d,e,f){var h,l,j,t,p,y=[],z=[],r=q;switch(e){case "HEX":h=E;break;case "B64":h=F;break;default:n("outputFormat must be HEX or B64")}"SHA-384"===d?(j=128,p=384):"SHA-512"===d?(j=128,p=512):n("Chosen SHA variant is not supported");"HEX"===b?(r=x(a),t=r.binLen,l=r.value):"ASCII"===b||"TEXT"===b?(r=u(a,m),t=r.binLen,l=r.value):"B64"===b?(r=B(a),
|
||||||
|
t=r.binLen,l=r.value):n("inputFormat must be HEX, TEXT, ASCII, or B64");a=8*j;b=j/4-1;j<t/8?(l=$(l,t,d),l[b]&=4294967040):j>t/8&&(l[b]&=4294967040);for(j=0;j<=b;j+=1)y[j]=l[j]^909522486,z[j]=l[j]^1549556828;d=$(z.concat($(y.concat(k),a+g,d)),a+p,d);return h(d,G(f))}};})();
|
Loading…
Reference in a new issue