Transaction

0425606c6609397c4bb17791da93c8692a90f61631981a5ad359c69c91e86546
( - )
269,167
2019-04-01 10:31:45
1
95,245 B

2 Outputs

Total Output:
  • j"1ChDHzdd1H4wSjgGMHyndZm6qxEDGjqpJLNspt?</label> <input type="checkbox" id="bulkencrypt" onchange="ninja.wallets.bulkwallet.toggleEncrypt(this);"></span> <span><label id="bulklabelBIPpassphrase" for="bulkpassphrase">Passphrase:</label> <input type="text" id="bulkpassphrase"></span> </div> </div> <div class="body"> <span class="label" id="bulklabelcsv">Comma Separated Values:</span> <span class="format" id="bulklabelformat">Index,Address,Private Key</span> <textarea rows="20" cols="88" id="bulktextarea"></textarea> </div> <div class="faqs"> <div id="bulkfaq1" class="faq"> <div id="bulkq1" class="question" onclick="ninja.wallets.bulkwallet.openCloseFaq(1);"> <span id="bulklabelq1">Why should I use a Bulk Wallet to accept bitcoins on my website?</span> <div id="bulke1" class="more"></div> </div> <div id="bulka1" class="answer">The traditional approach to accepting bitcoins on your website requires that you install the official bitcoin client daemon ("bitcoind"). Many website hosting packages don't support installing the bitcoin daemon. Also, running the bitcoin daemon on your web server means your private keys are hosted on the server and could get stolen if your web server is hacked. When using a Bulk Wallet you can upload only the bitcoin addresses and not the private keys to your web server. Then you don't have to worry about your bitcoin wallet being stolen if your web server is hacked. </div> </div> <div id="bulkfaq2" class="faq"> <div id="bulkq2" class="question" onclick="ninja.wallets.bulkwallet.openCloseFaq(2);"> <span id="bulklabelq2">How do I use a Bulk Wallet to accept bitcoins on my website?</span> <div id="bulke2" class="more"></div> </div> <div id="bulka2" class="answer"> <ol> <li id="bulklabela2li1">Use the Bulk Wallet tab to pre-generate a large number of bitcoin addresses (10,000+). Copy and paste the generated comma separated values (CSV) list to a secure text file on your computer. Backup the file you just created to a secure location.</li> <li id="bulklabela2li2">Import the bitcoin addresses into a database table on your web server. (Don't put the wallet/private keys on your web server, otherwise you risk hackers stealing your coins. Just the bitcoin addresses as they will be shown to customers.)</li> <li id="bulklabela2li3">Provide an option on your website's shopping cart for your customer to pay in Bitcoin. When the customer chooses to pay in Bitcoin you will then display one of the addresses from your database to the customer as his "payment address" and save it with his shopping cart order.</li> <li id="bulklabela2li4">You now need to be notified when the payment arrives. Google "bitcoin payment notification" and subscribe to at least one bitcoin payment notification service. There are various services that will notify you via Web Services, API, SMS, Email, etc. Once you receive this notification, which could be programmatically automated, you can process the customer's order. To manually check if a payment has arrived you can use Block Explorer. Replace THEADDRESSGOESHERE with the bitcoin address you are checking. It could take between 10 minutes to one hour for the transaction to be confirmed.<br>http://www.blockexplorer.com/address/THEADDRESSGOESHERE<br><br>Unconfirmed transactions can be viewed at: http://blockchain.info/ <br>You should see the transaction there within 30 seconds.</li> <li id="bulklabela2li5">Bitcoins will safely pile up on the block chain. Use the original wallet file you generated in step 1 to spend them.</li> </ol> </div> </div> </div> </div> <div id="brainarea" class="walletarea"> <div id="braincommands" class="commands"> <div class="row"> <span id="brainlabelenterpassphrase" class="label"><label for="brainpassphrase">Enter Passphrase: </label></span> <input tabindex="1" type="password" id="brainpassphrase" value="" onfocus="this.select();" onkeypress="if (event.keyCode == 13) ninja.wallets.brainwallet.view();"> <span><label id="brainlabelshow" for="brainpassphraseshow">Show?</label> <input type="checkbox" id="brainpassphraseshow" onchange="ninja.wallets.brainwallet.showToggle(this);"></span> <span class="print"><input type="button" name="print" id="brainprint" value="Print" onclick="window.print();"></span> </div> <div class="row extra"> <span class="label" id="brainlabelconfirm"><label for="brainpassphraseconfirm">Confirm Passphrase: </label></span> <input tabindex="2" type="password" id="brainpassphraseconfirm" value="" onfocus="this.select();" onkeypress="if (event.keyCode == 13) ninja.wallets.brainwallet.view();"> <span id="brainalgorithm" class="notes right">Algorithm: SHA256(passphrase)</span> </div> <div class="row extra"> <span><label tabindex="3" id="brainlabelcompressed" for="braincompressed">Compressed address?</label> <input type="checkbox" id="braincompressed"></span> <span><input tabindex="4" type="button" id="brainview" value="View" onclick="ninja.wallets.brainwallet.view();"></span> </div> <div class="row extra"><span id="brainwarning"></span></div> </div> <div id="brainkeyarea" class="keyarea"> <div class="public"> <div id="brainqrcodepublic" class="qrcode_public"></div> <div class="pubaddress"> <span class="label" id="brainlabelbitcoinaddress">Bitcoin Address:</span> <span class="output" id="brainbtcaddress"></span> </div> </div> <div class="private"> <div id="brainqrcodeprivate" class="qrcode_private"></div> <div class="privwif"> <span class="label" id="brainlabelprivatekey">Private Key (Wallet Import Format):</span> <span class="output" id="brainbtcprivwif"></span> </div> </div> </div> </div> <div id="vanityarea" class="walletarea"> <div id="vanitystep1label" class="commands expandable" onclick="ninja.wallets.vanitywallet.openCloseStep(1);"> <span><label id="vanitylabelstep1">Step 1 - Generate your "Step1 Key Pair"</label> <input type="button" id="vanitynewkeypair" value="Generate" onclick="ninja.wallets.vanitywallet.generateKeyPair();"></span> <div id="vanitystep1icon" class="more"></div> </div> <div id="vanitystep1area"> <div> <span class="label" id="vanitylabelstep1publickey">Step 1 Public Key:</span> <div class="output pubkeyhex" id="vanitypubkey"></div> <br><div class="notes" id="vanitylabelstep1pubnotes">Copy and paste the above into the Your-Part-Public-Key field in the Vanity Pool Website.</div> </div> <div> <span class="label" id="vanitylabelstep1privatekey">Step 1 Private Key:</span> <span class="output" id="vanityprivatekey"></span> <br><div class="notes" id="vanitylabelstep1privnotes">Copy and paste the above Private Key field into a text file. Ideally save to an encrypted drive. You will need this to retrieve the Bitcoin Private Key once the Pool has found your prefix.</div> </div> </div> <div id="vanitystep2label" class="expandable" onclick="ninja.wallets.vanitywallet.openCloseStep(2);"> <span id="vanitylabelstep2calculateyourvanitywallet">Step 2 - Calculate your Vanity Wallet</span> <div id="vanitystep2icon" class="more"></div> </div> <div id="vanitystep2inputs"> <div> <span id="vanitylabelenteryourpart">Enter Your Part Private Key (generated in Step 1 above and previously saved):</span> <br><span class="notes" id="vanitylabelnote1">[NOTE: this input box can accept a public key or private key]</span> </div> <div><textarea id="vanityinput1" rows="2" cols="90" onfocus="this.select();"></textarea></div> <div> <span id="vanitylabelenteryourpoolpart">Enter Pool Part Private Key (from Vanity Pool):</span> <br><span class="notes" id="vanitylabelnote2">[NOTE: this input box can accept a public key or private key]</span> </div> <div><textarea id="vanityinput2" rows="2" cols="90" onfocus="this.select();"></textarea></div> <div> <label for="vanityradioadd" id="vanitylabelradioadd">Add</label> <input type="radio" id="vanityradioadd" name="vanityradio" value="add" checked=""> <label for="vanityradiomultiply" id="vanitylabelradiomultiply">Multiply</label> <input type="radio" id="vanityradiomultiply" name="vanityradio" value="multiply"> </div> <div><input type="button" id="vanitycalc" value="Calculate Vanity Wallet" onclick="ninja.wallets.vanitywallet.addKeys();"></div> </div> <div id="vanitystep2area"> <div> <span class="label" id="vanitylabelbitcoinaddress">Vanity Bitcoin Address:</span> <span class="output" id="vanityaddress"></span> <br><div class="notes" id="vanitylabelnotesbitcoinaddress">The above is your new address that should include your required prefix.</div> </div> <div> <span class="label" id="vanitylabelpublickeyhex">Vanity Public Key (HEX):</span> <span class="output pubkeyhex" id="vanitypublickeyhex"></span> <br><div class="notes" id="vanitylabelnotespublickeyhex">The above is the Public Key in hexadecimal format. </div> </div> <div> <span class="label" id="vanitylabelprivatekey">Vanity Private Key (WIF):</span> <span class="output" id="vanityprivatekeywif"></span> <br><div class="notes" id="vanitylabelnotesprivatekey">The above is the Private Key to load into your wallet. </div> </div> </div> </div> <div id="splitarea" class="walletarea"> <div id="splitcommands" class="commands "> <label id="splitlabelthreshold">Minimum share threshold needed to combine</label> <input type="text" id="splitthreshold" value="2" size="4"> <br> <label id="splitlabelshares">Number of shares</label> <input type="text" id="splitshares" value="3" size="4"> <span><input type="button" id="splitview" value="Generate" onclick="ninja.wallets.splitwallet.splitKey();"></span> <div id="splitstep1icon" class="more " onclick="ninja.wallets.splitwallet.openCloseStep(1);"></div> </div> <div id="splitstep1area"></div> <div id="combinecommands" class="left commands"> <span> <label id="combinelabelentershares">Enter Available Shares (whitespace separated)</label><br> <textarea id="combineinput" cols="60" rows="10"></textarea><br> </span> <span><input type="button" id="combineview" value="Combine Shares" onclick="ninja.wallets.splitwallet.combineShares();"></span> </div> <div id="splitstep2area"> <div id="combineoutput"> <label id="combinelabelprivatekey">Combined Private Key</label> <div id="combinedprivatekey" class="output"></div> </div> </div> </div> <div id="detailarea" class="walletarea"> <div id="detailcommands" class="commands"> <span><label id="detaillabelenterprivatekey" for="detailprivkey">Enter Private Key</label></span> <input type="text" id="detailprivkey" value="" onfocus="this.select();" onkeypress="if (event.keyCode == 13) ninja.wallets.detailwallet.viewDetails();"> <span><input type="button" class="button" id="detailview" value="View Details" onclick="ninja.wallets.detailwallet.viewDetails();"></span> <div id="detailbip38toggle"> <span><label id="detaillabelencrypt" for="detailencrypt">BIP38 Encrypt?</label> <input type="checkbox" id="detailbip38checkbox" onchange="ninja.wallets.detailwallet.toggleEncrypt(this);"></span> </div> <div id="detailbip38commands"> <span><label id="detaillabelpassphrase">Enter BIP38 Passphrase</label> <input type="text" id="detailprivkeypassphrase" value="" onfocus="this.select();" onkeypress="if (event.keyCode == 13) ninja.wallets.detailwallet.enterOnPassphrase();"></span> <span id="detailbip38decryptspan"><input type="button" class="button" id="detailbip38decryptbutton" value="Decrypt BIP38" onclick="ninja.wallets.detailwallet.decryptBip38();"></span> <span id="detailbip38encryptspan"><input type="button" class="button" id="detailbip38encryptbutton" value="Encrypt BIP38" onclick="ninja.wallets.detailwallet.encryptBip38();"></span> </div> <span class="print"><input type="button" class="button" name="print" id="detailprint" value="Print" onclick="window.print();"></span> <div class="row extra"> <span><label id="detailkeyformats">Key Formats: WIF, WIFC, HEX, B64, B6, MINI, BIP38</label></span> </div> </div> <div id="detailkeyarea"> <div class="notes"> <span id="detaillabelnote1">Your Bitcoin Private Key is a unique secret number that only you know. It can be encoded in a number of different formats. Below we show the Bitcoin Address and Public Key that corresponds to your Private Key as well as your Private Key in the most popular encoding formats (WIF, WIFC, HEX, B64).</span> <br><br> <span id="detaillabelnote2">Bitcoin v0.6+ stores public keys in compressed format. The client now also supports import and export of private keys with importprivkey/dumpprivkey. The format of the exported private key is determined by whether the address was generated in an old or new wallet.</span> </div> <div class="pubqr"> <div class="item"> <span class="label" id="detaillabelbitcoinaddress">Bitcoin Address</span> <div id="detailqrcodepublic" class="qrcode_public"></div> <span class="output" id="detailaddress"></span> </div> <div class="item right"> <span class="label" id="detaillabelbitcoinaddresscomp">Bitcoin Address Compressed</span> <div id="detailqrcodepubliccomp" class="qrcode_public"></div> <span class="output" id="detailaddresscomp"></span> </div> </div> <br><br> <div class="item clear"> <span class="label" id="detaillabelpublickey">Public Key (130 characters [0-9A-F]):</span> <span class="output pubkeyhex" id="detailpubkey"></span> </div> <div class="item"> <span class="label" id="detaillabelpublickeycomp">Public Key (compressed, 66 characters [0-9A-F]):</span> <span class="output" id="detailpubkeycomp"></span> </div> <hr> <div class="privqr"> <div class="item"> <span class="label"><span id="detaillabelprivwif">Private Key WIF<br>51 characters base58, starts with a</span> <span id="detailwifprefix">'5'</span></span> <div id="detailqrcodeprivate" class="qrcode_private"></div> <span class="output" id="detailprivwif"></span> </div> <div class="item right"> <span class="label"><span id="detaillabelprivwifcomp">Private Key WIF Compressed<br>52 characters base58, starts with a</span> <span id="detailcompwifprefix">'K' or 'L'</span></span> <div id="detailqrcodeprivatecomp" class="qrcode_private"></div> <span class="output" id="detailprivwifcomp"></span> </div> </div> <br><br> <div class="item clear"> <span class="label" id="detaillabelprivhex">Private Key Hexadecimal Format (64 characters [0-9A-F]):</span> <span class="output" id="detailprivhex"></span> </div> <div class="item"> <span class="label" id="detaillabelprivb64">Private Key Base64 (44 characters):</span> <span class="output" id="detailprivb64"></span> </div> <div class="item" style="display: none;" id="detailmini"> <span class="label" id="detaillabelprivmini">Private Key Mini Format (22, 26 or 30 characters, starts with an 'S'):</span> <span class="output" id="detailprivmini"></span> </div> <div class="item" style="display: none;" id="detailb6"> <span class="label" id="detaillabelprivb6">Private Key Base6 Format (99 characters [0-5]):</span> <span class="output" id="detailprivb6"></span> </div> <div class="item" style="display: none;" id="detailbip38"> <span class="label" id="detaillabelprivbip38">Private Key BIP38 Format (58 characters base58, starts with '6P'):</span> <div id="detailqrcodeprivatebip38" class="qrcode_private"></div> <span class="output" id="detailprivbip38"></span> </div> </div> <div class="faqs"> <div id="detailfaq1" class="faq"> <div id="detailq1" class="question" onclick="ninja.wallets.detailwallet.openCloseFaq(1);"> <span id="detaillabelq1">How do I make a wallet using dice? What is B6?</span> <div id="detaile1" class="more"></div> </div> <div id="detaila1" class="answer">An important part of creating a Bitcoin wallet is ensuring the random numbers used to create the wallet are truly random. Physical randomness is better than computer generated pseudo-randomness. The easiest way to generate physical randomness is with dice. To create a Bitcoin private key you only need one six sided die which you roll 99 times. Stopping each time to record the value of the die. When recording the values follow these rules: 1=1, 2=2, 3=3, 4=4, 5=5, 6=0. By doing this you are recording the big random number, your private key, in B6 or base 6 format. You can then enter the 99 character base 6 private key into the text field above and click View Details. You will then see the Bitcoin address associated with your private key. You should also make note of your private key in WIF format since it is more widely used.</div> </div> </div> </div> </div> <div id="footer" class="footer"> <div class="tooltips"> <div class="tooltip" id="statuscryptogood"> <span class="statusgood" id="statuslabelcryptogood">✔ Good!</span> <span id="statuslabelcryptogood1">Your browser can generate cryptographically random keys using window.crypto.getRandomValues</span> <br><br><input type="button" value="OK" class="button" id="statusokcryptogood" onclick="document.getElementById(&#39;statuscryptogood&#39;).style.display = &#39;none&#39;;"> </div> <div class="tooltip" id="statuscryptobad"> <span class="statusbad" id="statuslabelcryptobad">× Oh no!</span> <span id="statuslabelcryptobad1">Your browser does NOT support window.crypto.getRandomValues. You should use a more modern browser with this generator to increase the security of the keys generated.</span> <br><br><input type="button" value="OK" class="button" id="statusokcryptobad" onclick="document.getElementById(&#39;statuscryptobad&#39;).style.display = &#39;none&#39;;"> </div> <div class="tooltip" id="statusunittestsgood"> <span class="statusgood" id="statuslabelunittestsgood">✔ Good!</span> <span id="statuslabelunittestsgood1">All synchronous unit tests passed.</span> <br><br><input type="button" value="OK" class="button" id="statusokunittestsgood" onclick="document.getElementById(&#39;statusunittestsgood&#39;).style.display = &#39;none&#39;;"> </div> <div class="tooltip" id="statusunittestsbad"> <span class="statusbad" id="statuslabelunittestsbad">× Oh no!</span> <span id="statuslabelunittestsbad1">Some synchronous unit tests DID NOT pass. You should find another browser to use with this generator.</span> <br><br><input type="button" value="OK" class="button" id="statusokunittestsbad" onclick="document.getElementById(&#39;statusunittestsbad&#39;).style.display = &#39;none&#39;;"> </div> <div class="tooltip" id="statusprotocolgood"> <span class="statusgood" id="statuslabelprotocolgood">✔ Good!</span> <span id="statuslabelprotocolgood1">You are running this generator from your local computer. <br>Tip: Double check you are offline by trying </span> <a href="http://www.google.com/" target="_blank">www.google.com</a> <br><br><input type="button" value="OK" class="button" id="statusokprotocolgood" onclick="document.getElementById(&#39;statusprotocolgood&#39;).style.display = &#39;none&#39;;"> </div> <div class="tooltip" id="statusprotocolbad"> <span class="statuswarn" id="statuslabelprotocolbad">⚠ Think twice!</span> <span id="statuslabelprotocolbad1">You appear to be running this generator online from a live website. For valuable wallets it is recommended to</span> <a id="statuslabelprotocolbad2" href="https://github.com/pointbiz/bitaddress.org/archive/v3.3.0.zip">download</a> <span id="statuslabelprotocolbad3">the zip file from GitHub and run this generator offline as a local html file.</span> <br><br><input type="button" value="OK" class="button" id="statusokprotocolbad" onclick="document.getElementById(&#39;statusprotocolbad&#39;).style.display = &#39;none&#39;;"> </div> <div class="tooltip" id="statuskeypoolgood"> <span id="statuslabelkeypool1">This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.</span> <textarea rows="20" cols="102" id="keypooltextarea"></textarea> <br><br> <input type="button" value="Refresh" class="button" id="statuskeypoolrefresh" onclick="ninja.status.showKeyPool();"> <input type="button" value="OK" class="button" id="statusokkeypool" onclick="document.getElementById(&#39;statuskeypoolgood&#39;).style.display = &#39;none&#39;;"> </div> </div> <div class="authorbtc"> <div> <span class="item"> <span class="statusicon" id="statusprotocol" onclick="ninja.status.showProtocol();">⚠</span> <span class="statusicon" id="statuscrypto" onclick="ninja.status.showCrypto();">✔</span> <span class="statusicon" id="statusunittests" onclick="ninja.status.showUnitTests();">...</span> <span class="statusicon" id="statuskeypool" onclick="ninja.status.showKeyPool();">≣</span> </span> <span class="item"><span id="footerlabeldonations">Donations:</span> <b>1NiNja</b>1bUmhSoTXozBRBEtR8LeF9TGbZBN</span> <span class="item" id="footerlabeltranslatedby"></span> <span class="item"><a href="https://github.com/pointbiz/bitaddress.org" target="_blank" id="footerlabelgithub">GitHub Repository</a> (<a href="https://github.com/pointbiz/bitaddress.org/archive/v3.3.0.zip" target="_blank" id="footerlabelgithubzip">zip</a>)</span> </div> </div> <div class="authorpgp"> <span class="item"> <a href="https://www.bitaddress.org/CHANGELOG.txt.asc" target="_blank"><span id="footerlabelversion">Version History</span> (3.3.0)</a> </span> <span class="item">527B 5C82 B1F6 B2DB 72A0<br>ECBF 8749 7B91 6397 4F5A</span> <span class="item"> (<a href="https://www.bitaddress.org/pointbiz_bitaddress.org.asc" target="_blank" id="footerlabelpgp">PGP</a>) (<a href="javascript:window.location=window.location.pathname+&#39;.sig&#39;;" target="_blank" id="footerlabelsig">sig</a>) </span> </div> <div class="copyright"> <span id="footerlabelcopyright1">Copyright bitaddress.org.</span> <span id="footerlabelcopyright2">JavaScript copyrights are included in the source.</span> <span id="footerlabelnowarranty">No warranty.</span> </div> </div> </div> <script type="text/javascript"> var ninja = { wallets: {} }; ninja.privateKey = { isPrivateKey: function (key) { return ( Bitcoin.ECKey.isWalletImportFormat(key) || Bitcoin.ECKey.isCompressedWalletImportFormat(key) || Bitcoin.ECKey.isHexFormat(key) || Bitcoin.ECKey.isBase64Format(key) || Bitcoin.ECKey.isMiniFormat(key) ); }, getECKeyFromAdding: function (privKey1, privKey2) { var n = EllipticCurve.getSECCurveByName("secp256k1").getN(); var ecKey1 = new Bitcoin.ECKey(privKey1); var ecKey2 = new Bitcoin.ECKey(privKey2); // if both keys are the same return null if (ecKey1.getBitcoinHexFormat() == ecKey2.getBitcoinHexFormat()) return null; if (ecKey1 == null || ecKey2 == null) return null; var combinedPrivateKey = new Bitcoin.ECKey(ecKey1.priv.add(ecKey2.priv).mod(n)); // compressed when both keys are compressed if (ecKey1.compressed && ecKey2.compressed) combinedPrivateKey.setCompressed(true); return combinedPrivateKey; }, getECKeyFromMultiplying: function (privKey1, privKey2) { var n = EllipticCurve.getSECCurveByName("secp256k1").getN(); var ecKey1 = new Bitcoin.ECKey(privKey1); var ecKey2 = new Bitcoin.ECKey(privKey2); // if both keys are the same return null if (ecKey1.getBitcoinHexFormat() == ecKey2.getBitcoinHexFormat()) return null; if (ecKey1 == null || ecKey2 == null) return null; var combinedPrivateKey = new Bitcoin.ECKey(ecKey1.priv.multiply(ecKey2.priv).mod(n)); // compressed when both keys are compressed if (ecKey1.compressed && ecKey2.compressed) combinedPrivateKey.setCompressed(true); return combinedPrivateKey; }, // 58 base58 characters starting with 6P isBIP38Format: function (key) { key = key.toString(); return (/^6P[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{56}$/.test(key)); }, BIP38EncryptedKeyToByteArrayAsync: function (base58Encrypted, passphrase, callback) { var hex; try { hex = Bitcoin.Base58.decode(base58Encrypted); } catch (e) { callback(new Error(ninja.translator.get("detailalertnotvalidprivatekey"))); return; } // 43 bytes: 2 bytes prefix, 37 bytes payload, 4 bytes checksum if (hex.length != 43) { callback(new Error(ninja.translator.get("detailalertnotvalidprivatekey"))); return; } // first byte is always 0x01 else if (hex[0] != 0x01) { callback(new Error(ninja.translator.get("detailalertnotvalidprivatekey"))); return; } var expChecksum = hex.slice(-4); hex = hex.slice(0, -4); var checksum = Bitcoin.Util.dsha256(hex); if (checksum[0] != expChecksum[0] || checksum[1] != expChecksum[1] || checksum[2] != expChecksum[2] || checksum[3] != expChecksum[3]) { callback(new Error(ninja.translator.get("detailalertnotvalidprivatekey"))); return; } var isCompPoint = false; var isECMult = false; var hasLotSeq = false; // second byte for non-EC-multiplied key if (hex[1] == 0x42) { // key should use compression if (hex[2] == 0xe0) { isCompPoint = true; } // key should NOT use compression else if (hex[2] != 0xc0) { callback(new Error(ninja.translator.get("detailalertnotvalidprivatekey"))); return; } } // second byte for EC-multiplied key else if (hex[1] == 0x43) { isECMult = true; isCompPoint = (hex[2] & 0x20) != 0; hasLotSeq = (hex[2] & 0x04) != 0; if ((hex[2] & 0x24) != hex[2]) { callback(new Error(ninja.translator.get("detailalertnotvalidprivatekey"))); return; } } else { callback(new Error(ninja.translator.get("detailalertnotvalidprivatekey"))); return; } var decrypted; var AES_opts = { mode: new Crypto.mode.ECB(Crypto.pad.NoPadding), asBytes: true }; var verifyHashAndReturn = function () { var tmpkey = new Bitcoin.ECKey(decrypted); // decrypted using closure var base58AddrText = tmpkey.setCompressed(isCompPoint).getBitcoinAddress(); // isCompPoint using closure checksum = Bitcoin.Util.dsha256(base58AddrText); // checksum using closure if (checksum[0] != hex[3] || checksum[1] != hex[4] || checksum[2] != hex[5] || checksum[3] != hex[6]) { callback(new Error(ninja.translator.get("bip38alertincorrectpassphrase"))); // callback using closure return; } callback(tmpkey.getBitcoinPrivateKeyByteArray()); // callback using closure }; if (!isECMult) { var addresshash = hex.slice(3, 7); Crypto_scrypt(passphrase, addresshash, 16384, 8, 8, 64, function (derivedBytes) { var k = derivedBytes.slice(32, 32 + 32); decrypted = Crypto.AES.decrypt(hex.slice(7, 7 + 32), k, AES_opts); for (var x = 0; x < 32; x++) decrypted[x] ^= derivedBytes[x]; verifyHashAndReturn(); //TODO: pass in 'decrypted' as a param }); } else { var ownerentropy = hex.slice(7, 7 + 8); var ownersalt = !hasLotSeq ? ownerentropy : ownerentropy.slice(0, 4); Crypto_scrypt(passphrase, ownersalt, 16384, 8, 8, 32, function (prefactorA) { var passfactor; if (!hasLotSeq) { // hasLotSeq using closure passfactor = prefactorA; } else { var prefactorB = prefactorA.concat(ownerentropy); // ownerentropy using closure passfactor = Bitcoin.Util.dsha256(prefactorB); } // remove this ECKey from the pool (because user does not see it) var userKeyPool = Bitcoin.KeyPool.getArray(); var kp = new Bitcoin.ECKey(passfactor); var passpoint = kp.setCompressed(true).getPub(); Bitcoin.KeyPool.setArray(userKeyPool); var encryptedpart2 = hex.slice(23, 23 + 16); var addresshashplusownerentropy = hex.slice(3, 3 + 12); Crypto_scrypt(passpoint, addresshashplusownerentropy, 1024, 1, 1, 64, function (derived) { var k = derived.slice(32); var unencryptedpart2 = Crypto.AES.decrypt(encryptedpart2, k, AES_opts); for (var i = 0; i < 16; i++) { unencryptedpart2[i] ^= derived[i + 16]; } var encryptedpart1 = hex.slice(15, 15 + 8).concat(unencryptedpart2.slice(0, 0 + 8)); var unencryptedpart1 = Crypto.AES.decrypt(encryptedpart1, k, AES_opts); for (var i = 0; i < 16; i++) { unencryptedpart1[i] ^= derived[i]; } var seedb = unencryptedpart1.slice(0, 0 + 16).concat(unencryptedpart2.slice(8, 8 + 8)); var factorb = Bitcoin.Util.dsha256(seedb); var ps = EllipticCurve.getSECCurveByName("secp256k1"); var privateKey = BigInteger.fromByteArrayUnsigned(passfactor).multiply(BigInteger.fromByteArrayUnsigned(factorb)).remainder(ps.getN()); decrypted = privateKey.toByteArrayUnsigned(); verifyHashAndReturn(); }); }); } }, BIP38PrivateKeyToEncryptedKeyAsync: function (base58Key, passphrase, compressed, callback) { var privKey = new Bitcoin.ECKey(base58Key); var privKeyBytes = privKey.getBitcoinPrivateKeyByteArray(); var address = privKey.setCompressed(compressed).getBitcoinAddress(); // compute sha256(sha256(address)) and take first 4 bytes var salt = Bitcoin.Util.dsha256(address).slice(0, 4); // derive key using scrypt var AES_opts = { mode: new Crypto.mode.ECB(Crypto.pad.NoPadding), asBytes: true }; Crypto_scrypt(passphrase, salt, 16384, 8, 8, 64, function (derivedBytes) { for (var i = 0; i < 32; ++i) { privKeyBytes[i] ^= derivedBytes[i]; } // 0x01 0x42 + flagbyte + salt + encryptedhalf1 + encryptedhalf2 var flagByte = compressed ? 0xe0 : 0xc0; var encryptedKey = [0x01, 0x42, flagByte].concat(salt); encryptedKey = encryptedKey.concat(Crypto.AES.encrypt(privKeyBytes, derivedBytes.slice(32), AES_opts)); encryptedKey = encryptedKey.concat(Bitcoin.Util.dsha256(encryptedKey).slice(0, 4)); callback(Bitcoin.Base58.encode(encryptedKey)); }); }, BIP38GenerateIntermediatePointAsync: function (passphrase, lotNum, sequenceNum, callback) { var noNumbers = lotNum === null || sequenceNum === null; var rng = new SecureRandom(); var ownerEntropy, ownerSalt; if (noNumbers) { ownerSalt = ownerEntropy = new Array(8); rng.nextBytes(ownerEntropy); } else { // 1) generate 4 random bytes ownerSalt = new Array(4); rng.nextBytes(ownerSalt); // 2) Encode the lot and sequence numbers as a 4 byte quantity (big-endian): // lotnumber * 4096 + sequencenumber. Call these four bytes lotsequence. var lotSequence = BigInteger(4096 * lotNum + sequenceNum).toByteArrayUnsigned(); // 3) Concatenate ownersalt + lotsequence and call this ownerentropy. var ownerEntropy = ownerSalt.concat(lotSequence); } // 4) Derive a key from the passphrase using scrypt Crypto_scrypt(passphrase, ownerSalt, 16384, 8, 8, 32, function (prefactor) { // Take SHA256(SHA256(prefactor + ownerentropy)) and call this passfactor var passfactorBytes = noNumbers ? prefactor : Bitcoin.Util.dsha256(prefactor.concat(ownerEntropy)); var passfactor = BigInteger.fromByteArrayUnsigned(passfactorBytes); // 5) Compute the elliptic curve point G * passfactor, and convert the result to compressed notation (33 bytes) var ellipticCurve = EllipticCurve.getSECCurveByName("secp256k1"); var passpoint = ellipticCurve.getG().multiply(passfactor).getEncoded(1); // 6) Convey ownersalt and passpoint to the party generating the keys, along with a checksum to ensure integrity. // magic bytes "2C E9 B3 E1 FF 39 E2 51" followed by ownerentropy, and then passpoint var magicBytes = [0x2C, 0xE9, 0xB3, 0xE1, 0xFF, 0x39, 0xE2, 0x51]; if (noNumbers) magicBytes[7] = 0x53; var intermediate = magicBytes.concat(ownerEntropy).concat(passpoint); // base58check encode intermediate = intermediate.concat(Bitcoin.Util.dsha256(intermediate).slice(0, 4)); callback(Bitcoin.Base58.encode(intermediate)); }); }, BIP38GenerateECAddressAsync: function (intermediate, compressed, callback) { // decode IPS var x = Bitcoin.Base58.decode(intermediate); //if(x.slice(49, 4) !== Bitcoin.Util.dsha256(x.slice(0,49)).slice(0,4)) { // callback({error: 'Invalid intermediate passphrase string'}); //} var noNumbers = (x[7] === 0x53); var ownerEntropy = x.slice(8, 8 + 8); var passpoint = x.slice(16, 16 + 33); // 1) Set flagbyte. // set bit 0x20 for compressed key // set bit 0x04 if ownerentropy contains a value for lotsequence var flagByte = (compressed ? 0x20 : 0x00) | (noNumbers ? 0x00 : 0x04); // 2) Generate 24 random bytes, call this seedb. var seedB = new Array(24); var rng = new SecureRandom(); rng.nextBytes(seedB); // Take SHA256(SHA256(seedb)) to yield 32 bytes, call this factorb. var factorB = Bitcoin.Util.dsha256(seedB); // 3) ECMultiply passpoint by factorb. Use the resulting EC point as a public key and hash it into a Bitcoin // address using either compressed or uncompressed public key methodology (specify which methodology is used // inside flagbyte). This is the generated Bitcoin address, call it generatedaddress. var ec = EllipticCurve.getSECCurveByName("secp256k1").getCurve(); var generatedPoint = ec.decodePointHex(ninja.publicKey.getHexFromByteArray(passpoint)); var generatedBytes = generatedPoint.multiply(BigInteger.fromByteArrayUnsigned(factorB)).getEncoded(compressed); var generatedAddress = (new Bitcoin.Address(Bitcoin.Util.sha256ripe160(generatedBytes))).toString(); // 4) Take the first four bytes of SHA256(SHA256(generatedaddress)) and call it addresshash. var addressHash = Bitcoin.Util.dsha256(generatedAddress).slice(0, 4); // 5) Now we will encrypt seedb. Derive a second key from passpoint using scrypt Crypto_scrypt(passpoint, addressHash.concat(ownerEntropy), 1024, 1, 1, 64, function (derivedBytes) { // 6) Do AES256Encrypt(seedb[0...15]] xor derivedhalf1[0...15], derivedhalf2), call the 16-byte result encryptedpart1 for (var i = 0; i < 16; ++i) { seedB[i] ^= derivedBytes[i]; } var AES_opts = { mode: new Crypto.mode.ECB(Crypto.pad.NoPadding), asBytes: true }; var encryptedPart1 = Crypto.AES.encrypt(seedB.slice(0, 16), derivedBytes.slice(32), AES_opts); // 7) Do AES256Encrypt((encryptedpart1[8...15] + seedb[16...23]) xor derivedhalf1[16...31], derivedhalf2), call the 16-byte result encryptedseedb. var message2 = encryptedPart1.slice(8, 8 + 8).concat(seedB.slice(16, 16 + 8)); for (var i = 0; i < 16; ++i) { message2[i] ^= derivedBytes[i + 16]; } var encryptedSeedB = Crypto.AES.encrypt(message2, derivedBytes.slice(32), AES_opts); // 0x01 0x43 + flagbyte + addresshash + ownerentropy + encryptedpart1[0...7] + encryptedpart2 var encryptedKey = [0x01, 0x43, flagByte].concat(addressHash).concat(ownerEntropy).concat(encryptedPart1.slice(0, 8)).concat(encryptedSeedB); // base58check encode encryptedKey = encryptedKey.concat(Bitcoin.Util.dsha256(encryptedKey).slice(0, 4)); callback(generatedAddress, Bitcoin.Base58.encode(encryptedKey)); }); } }; ninja.publicKey = { isPublicKeyHexFormat: function (key) { key = key.toString(); return ninja.publicKey.isUncompressedPublicKeyHexFormat(key) || ninja.publicKey.isCompressedPublicKeyHexFormat(key); }, // 130 characters [0-9A-F] starts with 04 isUncompressedPublicKeyHexFormat: function (key) { key = key.toString(); return /^04[A-Fa-f0-9]{128}$/.test(key); }, // 66 characters [0-9A-F] starts with 02 or 03 isCompressedPublicKeyHexFormat: function (key) { key = key.toString(); return /^0[2-3][A-Fa-f0-9]{64}$/.test(key); }, getBitcoinAddressFromByteArray: function (pubKeyByteArray) { var pubKeyHash = Bitcoin.Util.sha256ripe160(pubKeyByteArray); var addr = new Bitcoin.Address(pubKeyHash); return addr.toString(); }, getHexFromByteArray: function (pubKeyByteArray) { return Crypto.util.bytesToHex(pubKeyByteArray).toString().toUpperCase(); }, getByteArrayFromAdding: function (pubKeyHex1, pubKeyHex2) { var ecparams = EllipticCurve.getSECCurveByName("secp256k1"); var curve = ecparams.getCurve(); var ecPoint1 = curve.decodePointHex(pubKeyHex1); var ecPoint2 = curve.decodePointHex(pubKeyHex2); // if both points are the same return null if (ecPoint1.equals(ecPoint2)) return null; var compressed = (ecPoint1.compressed && ecPoint2.compressed); var pubKey = ecPoint1.add(ecPoint2).getEncoded(compressed); return pubKey; }, getByteArrayFromMultiplying: function (pubKeyHex, ecKey) { var ecparams = EllipticCurve.getSECCurveByName("secp256k1"); var ecPoint = ecparams.getCurve().decodePointHex(pubKeyHex); var compressed = (ecPoint.compressed && ecKey.compressed); // if both points are the same return null ecKey.setCompressed(false); if (ecPoint.equals(ecKey.getPubPoint())) { return null; } var bigInt = ecKey.priv; var pubKey = ecPoint.multiply(bigInt).getEncoded(compressed); return pubKey; }, // used by unit test getDecompressedPubKeyHex: function (pubKeyHexComp) { var ecparams = EllipticCurve.getSECCurveByName("secp256k1"); var ecPoint = ecparams.getCurve().decodePointHex(pubKeyHexComp); var pubByteArray = ecPoint.getEncoded(0); var pubHexUncompressed = ninja.publicKey.getHexFromByteArray(pubByteArray); return pubHexUncompressed; } }; </script> <script type="text/javascript"> ninja.seeder = { init: (function () { document.getElementById("generatekeyinput").value = ""; })(), // number of mouse movements to wait for seedLimit: (function () { var num = Crypto.util.randomBytes(12)[11]; return 200 + Math.floor(num); })(), seedCount: 0, // counter lastInputTime: new Date().getTime(), seedPoints: [], isStillSeeding: true, seederDependentWallets: ["singlewallet", "paperwallet", "bulkwallet", "vanitywallet", "splitwallet"], // seed function exists to wait for mouse movement to add more entropy before generating an address seed: function (evt) { if (!evt) var evt = window.event; var timeStamp = new Date().getTime(); // seeding is over now we generate and display the address if (ninja.seeder.seedCount == ninja.seeder.seedLimit) { ninja.seeder.seedCount++; ninja.seeder.seedingOver(); } // seed mouse position X and Y when mouse movements are greater than 40ms apart. else if ((ninja.seeder.seedCount < ninja.seeder.seedLimit) && evt && (timeStamp - ninja.seeder.lastInputTime) > 40) { SecureRandom.seedTime(); SecureRandom.seedInt16((evt.clientX * evt.clientY)); ninja.seeder.showPoint(evt.clientX, evt.clientY); ninja.seeder.seedCount++; ninja.seeder.lastInputTime = new Date().getTime(); ninja.seeder.showPool(); } }, // seed function exists to wait for mouse movement to add more entropy before generating an address seedKeyPress: function (evt) { if (!evt) var evt = window.event; // seeding is over now we generate and display the address if (ninja.seeder.seedCount == ninja.seeder.seedLimit) { ninja.seeder.seedCount++; ninja.seeder.seedingOver(); } // seed key press character else if ((ninja.seeder.seedCount < ninja.seeder.seedLimit) && evt.which) { var timeStamp = new Date().getTime(); // seed a bunch (minimum seedLimit) of times SecureRandom.seedTime(); SecureRandom.seedInt8(evt.which); var keyPressTimeDiff = timeStamp - ninja.seeder.lastInputTime; SecureRandom.seedInt8(keyPressTimeDiff); ninja.seeder.seedCount++; ninja.seeder.lastInputTime = new Date().getTime(); ninja.seeder.showPool(); } }, showPool: function () { var poolHex; if (SecureRandom.poolCopyOnInit != null) { poolHex = Crypto.util.bytesToHex(SecureRandom.poolCopyOnInit); document.getElementById("seedpool").innerHTML = poolHex; document.getElementById("seedpooldisplay").innerHTML = poolHex; } else { poolHex = Crypto.util.bytesToHex(SecureRandom.pool); document.getElementById("seedpool").innerHTML = poolHex; document.getElementById("seedpooldisplay").innerHTML = poolHex; } var percentSeeded = Math.round((ninja.seeder.seedCount / ninja.seeder.seedLimit) * 100) + "%"; document.getElementById("mousemovelimit").innerHTML = percentSeeded; for (var wIndex in ninja.seeder.seederDependentWallets) { document.getElementById(ninja.seeder.seederDependentWallets[wIndex]).innerHTML = percentSeeded; } }, showPoint: function (x, y) { var div = document.createElement("div"); div.setAttribute("class", "seedpoint"); div.style.top = y + "px"; div.style.left = x + "px"; document.body.appendChild(div); ninja.seeder.seedPoints.push(div); }, removePoints: function () { for (var i = 0; i < ninja.seeder.seedPoints.length; i++) { document.body.removeChild(ninja.seeder.seedPoints[i]); } ninja.seeder.seedPoints = []; }, seedingOver: function () { ninja.seeder.isStillSeeding = false; // run sync unit tests ninja.status.unitTests(); // open selected tab var walletType = ninja.tab.whichIsOpen(); if (walletType == null) { ninja.tab.select("singlewallet"); } else { ninja.tab.select(walletType) } document.getElementById("generate").style.display = "none"; // update labels for dependent wallets var culture = (ninja.getQueryString()["culture"] == null ? "en" : ninja.getQueryString()["culture"]); ninja.translator.translate(culture); ninja.seeder.removePoints(); } }; </script> <script type="text/javascript"> (function (ninja) { var qrC = ninja.qrCode = { // determine which type number is big enough for the input text length getTypeNumber: function (text) { var lengthCalculation = text.length * 8 + 12; // length as calculated by the QRCode if (lengthCalculation < 72) { return 1; } else if (lengthCalculation < 128) { return 2; } else if (lengthCalculation < 208) { return 3; } else if (lengthCalculation < 288) { return 4; } else if (lengthCalculation < 368) { return 5; } else if (lengthCalculation < 480) { return 6; } else if (lengthCalculation < 528) { return 7; } else if (lengthCalculation < 688) { return 8; } else if (lengthCalculation < 800) { return 9; } else if (lengthCalculation < 976) { return 10; } return null; }, createCanvas: function (text, sizeMultiplier) { sizeMultiplier = (sizeMultiplier == undefined) ? 2 : sizeMultiplier; // default 2 // create the qrcode itself var typeNumber = qrC.getTypeNumber(text); var qrcode = new QRCode(typeNumber, QRCode.ErrorCorrectLevel.H); qrcode.addData(text); qrcode.make(); var width = qrcode.getModuleCount() * sizeMultiplier; var height = qrcode.getModuleCount() * sizeMultiplier; // create canvas element var canvas = document.createElement('canvas'); var scale = 10.0; canvas.width = width * scale; canvas.height = height * scale; canvas.style.width = width + 'px'; canvas.style.height = height + 'px'; var ctx = canvas.getContext('2d'); ctx.scale(scale, scale); // compute tileW/tileH based on width/height var tileW = width / qrcode.getModuleCount(); var tileH = height / qrcode.getModuleCount(); // draw in the canvas for (var row = 0; row < qrcode.getModuleCount() ; row++) { for (var col = 0; col < qrcode.getModuleCount() ; col++) { ctx.fillStyle = qrcode.isDark(row, col) ? "#000000" : "#ffffff"; ctx.fillRect(col * tileW, row * tileH, tileW, tileH); } } // return just built canvas return canvas; }, // show QRCodes with canvas // parameter: keyValuePair // example: { "id1": "string1", "id2": "string2"} // "id1" is the id of a div element where you want a QRCode inserted. // "string1" is the string you want encoded into the QRCode. showQrCode: function (keyValuePair, sizeMultiplier) { for (var key in keyValuePair) { var value = keyValuePair[key]; try { if (document.getElementById(key)) { document.getElementById(key).innerHTML = ""; document.getElementById(key).appendChild(qrC.createCanvas(value, sizeMultiplier)); } } catch (e) { } } } }; })(ninja); </script> <script type="text/javascript"> (function (ninja) { var status = ninja.status = function() { var cryptoCase = ""; if (window.crypto && window.crypto.getRandomValues) { document.getElementById("statuscrypto").innerHTML = "&#10004;"; //✔ cryptoCase = "good"; } else { document.getElementById("statuscrypto").innerHTML = "&times;"; //× cryptoCase = "bad"; } var protocolCase = ""; switch (window.location.protocol) { case 'file:': document.getElementById("statusprotocol").innerHTML = "&#10004;"; //✔ protocolCase = "good"; break; case 'http:': case 'https:': document.getElementById("statusprotocol").innerHTML = "&#9888;"; //⚠ protocolCase = "bad"; break; default: } var unitTestsCase = ""; var unitTests = function () { var result = ninja.unitTests.runSynchronousTests(); if (result.passCount == result.testCount) { document.getElementById("statusunittests").innerHTML = "&#10004;"; //✔ unitTestsCase = "good"; } else { document.getElementById("statusunittests").innerHTML = "&times;"; //× unitTestsCase = "bad"; } }; var showCrypto = function () { document.getElementById('statuscrypto' + cryptoCase).style.display = 'block'; }; var showProtocol = function () { document.getElementById('statusprotocol' + protocolCase).style.display = 'block'; }; var showUnitTests = function () { if(unitTestsCase != "") document.getElementById('statusunittests' + unitTestsCase).style.display = 'block'; }; var showKeyPool = function () { document.getElementById('statuskeypoolgood').style.display = 'block'; document.getElementById("keypooltextarea").value = Bitcoin.KeyPool.toString(); }; return { unitTests: unitTests, showCrypto: showCrypto, showProtocol: showProtocol, showUnitTests: showUnitTests, showKeyPool: showKeyPool }; }(); })(ninja); ninja.tab = { select: function (walletTab) { // detect type: normally an HtmlElement/object but when string then get the element if (typeof walletTab === 'string') { walletTab = document.getElementById(walletTab); } var walletType = walletTab.getAttribute("id"); if (walletTab.className.indexOf("selected") == -1) { // unselect all tabs for (var wType in ninja.wallets) { document.getElementById(wType).className = "tab"; ninja.wallets[wType].close(); } // don't open tab if entropy still being collected // exceptions: brainwallet detailwallet if (ninja.seeder.isStillSeeding == false || walletType == "brainwallet" || walletType == "detailwallet") { walletTab.className += " selected"; document.getElementById("generate").style.display = "none"; ninja.wallets[walletTab.getAttribute("id")].open(); } else if (ninja.seeder.isStillSeeding == true && !(walletType == "brainwallet" || walletType == "detailwallet")) { document.getElementById("generate").style.display = "block"; } } }, whichIsOpen: function () { var isOpen; for (var wType in ninja.wallets) { isOpen = ninja.wallets[wType].isOpen(); if (isOpen) { return wType; } } return null; } }; ninja.getQueryString = function () { var result = {}, queryString = location.search.substring(1), re = /([^&=]+)=([^&]*)/g, m; while (m = re.exec(queryString)) { result[decodeURIComponent(m[1])] = decodeURIComponent(m[2]); } return result; }; // use when passing an Array of Functions ninja.runSerialized = function (functions, onComplete) { onComplete = onComplete || function () { }; if (functions.length === 0) onComplete(); else { // run the first function, and make it call this // function when finished with the rest of the list var f = functions.shift(); f(function () { ninja.runSerialized(functions, onComplete); }); } }; ninja.forSerialized = function (initial, max, whatToDo, onComplete) { onComplete = onComplete || function () { }; if (initial === max) { onComplete(); } else { // same idea as runSerialized whatToDo(initial, function () { ninja.forSerialized(++initial, max, whatToDo, onComplete); }); } }; // use when passing an Object (dictionary) of Functions ninja.foreachSerialized = function (collection, whatToDo, onComplete) { var keys = []; for (var name in collection) { keys.push(name); } ninja.forSerialized(0, keys.length, function (i, callback) { whatToDo(keys[i], callback); }, onComplete); }; </script> <script type="text/javascript"> (function (ninja) { var translator = ninja.translator = { currentCulture: "en", autoDetectTranslation: function () { // window.navigator.language for Firefox / Chrome / Opera Safari // window.navigator.userLanguage for IE var language = window.navigator.language || window.navigator.userLanguage; if (!this.translate(language)) { // Try to remove part after dash, for example cs-CZ -> cs language = language.su
    https://whatsonchain.com/tx/0425606c6609397c4bb17791da93c8692a90f61631981a5ad359c69c91e86546
    Partial data displayed. To get full data click on Download.