]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/BIP39.git/blobdiff - src/js/index.js
Add a button to remove the "change" in the derivation path for ethereum
[perso/Immae/Projets/Cryptomonnaies/BIP39.git] / src / js / index.js
index 32825b2bb2ac282fdbbe699cf24bd5b80360f015..68c74f6912f0ac7d97940d5d611ffd30384ced55 100644 (file)
@@ -15,6 +15,7 @@
     var showPrivKey = true;
     var showQr = false;
     var litecoinUseLtub = true;
+    var isDefaultBip44ChangeValue = true;
 
     var entropyTypeAutoDetect = true;
     var entropyChangeTimeoutEvent = null;
@@ -47,6 +48,8 @@
     DOM.entropyWeakEntropyOverrideWarning = DOM.entropyContainer.find(".weak-entropy-override-warning");
     DOM.entropyFilterWarning = DOM.entropyContainer.find(".filter-warning");
     DOM.phrase = $(".phrase");
+    DOM.splitMnemonic = $(".splitMnemonic");
+    DOM.showSplitMnemonic = $(".showSplitMnemonic");
     DOM.phraseSplit = $(".phraseSplit");
     DOM.phraseSplitWarn = $(".phraseSplitWarn");
     DOM.passphrase = $(".passphrase");
@@ -74,6 +77,7 @@
     DOM.bip44accountXprv = $("#bip44 .account-xprv");
     DOM.bip44accountXpub = $("#bip44 .account-xpub");
     DOM.bip44change = $("#bip44 .change");
+    DOM.defaultBip44ChangeValue = $("#bip44 .default-bip44-change-value");
     DOM.bip49unavailable = $("#bip49 .unavailable");
     DOM.bip49available = $("#bip49 .available");
     DOM.bip49path = $("#bip49-path");
     DOM.bip84accountXprv = $("#bip84 .account-xprv");
     DOM.bip84accountXpub = $("#bip84 .account-xpub");
     DOM.bip84change = $("#bip84 .change");
+    DOM.bip85 = $('.bip85');
+    DOM.showBip85 = $('.showBip85');
+    DOM.bip85Field = $('.bip85Field');
+    DOM.bip85application = $('#bip85-application');
+    DOM.bip85mnemonicLanguage = $('#bip85-mnemonic-language');
+    DOM.bip85mnemonicLanguageInput = $('.bip85-mnemonic-language-input');
+    DOM.bip85mnemonicLength = $('#bip85-mnemonic-length');
+    DOM.bip85mnemonicLengthInput = $('.bip85-mnemonic-length-input');
+    DOM.bip85index = $('#bip85-index');
+    DOM.bip85indexInput = $('.bip85-index-input');
+    DOM.bip85bytes = $('#bip85-bytes');
+    DOM.bip85bytesInput = $('.bip85-bytes-input');
     DOM.bip141unavailable = $("#bip141 .unavailable");
     DOM.bip141available = $("#bip141 .available");
     DOM.bip141path = $("#bip141-path");
         DOM.entropyMnemonicLength.on("change", entropyChanged);
         DOM.entropyTypeInputs.on("change", entropyTypeChanged);
         DOM.phrase.on("input", delayedPhraseChanged);
+        DOM.showSplitMnemonic.on("change", toggleSplitMnemonic);
         DOM.passphrase.on("input", delayedPhraseChanged);
         DOM.generate.on("click", generateClicked);
         DOM.more.on("click", showMore);
         DOM.seed.on("input", delayedSeedChanged);
         DOM.rootKey.on("input", delayedRootKeyChanged);
+        DOM.showBip85.on('change', toggleBip85);
         DOM.litecoinUseLtub.on("change", litecoinUseLtubChanged);
         DOM.bip32path.on("input", calcForDerivationPath);
         DOM.bip44account.on("input", calcForDerivationPath);
+        DOM.bip44change.on("input", modifiedDefaultBip44ChangeValue);
         DOM.bip44change.on("input", calcForDerivationPath);
+        DOM.defaultBip44ChangeValue.on("click", resetDefaultBip44ChangeValue);
         DOM.bip49account.on("input", calcForDerivationPath);
         DOM.bip49change.on("input", calcForDerivationPath);
         DOM.bip84account.on("input", calcForDerivationPath);
         DOM.bip84change.on("input", calcForDerivationPath);
+        DOM.bip85application.on('input', calcBip85);
+        DOM.bip85mnemonicLanguage.on('change', calcBip85);
+        DOM.bip85mnemonicLength.on('change', calcBip85);
+        DOM.bip85index.on('input', calcBip85);
+        DOM.bip85bytes.on('input', calcBip85);
         DOM.bip141path.on("input", calcForDerivationPath);
         DOM.bip141semantics.on("change", tabChanged);
         DOM.tab.on("shown.bs.tab", tabChanged);
         var passphrase = DOM.passphrase.val();
         calcBip32RootKeyFromSeed(phrase, passphrase);
         calcForDerivationPath();
+        calcBip85();
         // Show the word indexes
         showWordIndexes();
         writeSplitPhrase(phrase);
         }
         // Calculate and display
         calcForDerivationPath();
+        calcBip85();
     }
 
     function rootKeyChanged() {
         // Calculate and display
         calcBip32RootKeyFromBase58(rootKeyBase58);
         calcForDerivationPath();
+        calcBip85();
     }
 
     function litecoinUseLtubChanged() {
         phraseChanged();
     }
 
+    function toggleSplitMnemonic() {
+        if (DOM.showSplitMnemonic.prop("checked")) {
+            DOM.splitMnemonic.removeClass("hidden");
+        }
+        else {
+            DOM.splitMnemonic.addClass("hidden");
+        }
+    }
+
+    function toggleBip85() {
+      if (DOM.showBip85.prop('checked')) {
+        DOM.bip85.removeClass('hidden');
+        calcBip85();
+      } else {
+        DOM.bip85.addClass('hidden');
+      }
+    }
+
+    function toggleBip85Fields() {
+      if (DOM.showBip85.prop('checked')) {
+        DOM.bip85mnemonicLanguageInput.addClass('hidden');
+        DOM.bip85mnemonicLengthInput.addClass('hidden');
+        DOM.bip85bytesInput.addClass('hidden');
+
+        var app = DOM.bip85application.val();
+        if (app === 'bip39') {
+          DOM.bip85mnemonicLanguageInput.removeClass('hidden');
+          DOM.bip85mnemonicLengthInput.removeClass('hidden');
+        } else if (app === 'hex') {
+          DOM.bip85bytesInput.removeClass('hidden');
+        }
+      }
+    }
+
+    function calcBip85() {
+      if (!DOM.showBip85.prop('checked')) {
+        return
+      }
+
+      toggleBip85Fields();
+
+      var app = DOM.bip85application.val();
+
+      var phrase = DOM.phrase.val();
+      var passphrase = DOM.passphrase.val();
+      if (!phrase) {
+        return;
+      }
+      try {
+        var master = libs.bip85.BIP85.fromMnemonic(phrase, passphrase);
+
+        var result;
+
+        const index = parseInt(DOM.bip85index.val(), 10);
+
+        if (app === 'bip39') {
+          const language = parseInt(DOM.bip85mnemonicLanguage.val(), 10);
+          const length = parseInt(DOM.bip85mnemonicLength.val(), 10);
+
+          result = master.deriveBIP39(language, length, index).toMnemonic();
+        } else if (app === 'wif') {
+          result = master.deriveWIF(index).toWIF();
+        } else if (app === 'xprv') {
+          result = master.deriveXPRV(index).toXPRV();
+        } else if (app === 'hex') {
+          const bytes = parseInt(DOM.bip85bytes.val(), 10);
+
+          result = master.deriveHex(bytes, index).toEntropy();
+        }
+
+        hideValidationError();
+        DOM.bip85Field.val(result);
+      } catch (e) {
+        showValidationError('BIP85: ' + e.message);
+        DOM.bip85Field.val('');
+      }
+    }
+
     function calcForDerivationPath() {
         clearDerivedKeys();
         clearAddressesList();
             var purpose = parseIntNoNaN(DOM.bip44purpose.val(), 44);
             var coin = parseIntNoNaN(DOM.bip44coin.val(), 0);
             var account = parseIntNoNaN(DOM.bip44account.val(), 0);
-            var change = parseIntNoNaN(DOM.bip44change.val(), 0);
-            var path = "m/";
-            path += purpose + "'/";
-            path += coin + "'/";
-            path += account + "'/";
-            path += change;
+            var change = parseIntNoNaN(DOM.bip44change.val(), "");
+            var path = "m";
+            path += "/" + purpose + "'";
+            path += "/" + coin + "'";
+            path += "/" + account + "'";
+            if (change !== "") {
+              path += "/" + change;
+            }
             DOM.bip44path.val(path);
             var derivationPath = DOM.bip44path.val();
             console.log("Using derivation path from BIP44 tab: " + derivationPath);
                     var checksumAddress = libs.ethUtil.toChecksumAddress(hexAddress);
                     address = libs.ethUtil.addHexPrefix(checksumAddress);
                     pubkey = libs.ethUtil.addHexPrefix(pubkey);
+                    if (hasPrivkey) {
+                        privkey = libs.ethUtil.bufferToHex(keyPair.d.toBuffer(32));
+                    }
+                }
+                //TRX is different
+                if (networks[DOM.network.val()].name == "TRX - Tron") {
+                    keyPair = new libs.bitcoin.ECPair(keyPair.d, null, { network: network, compressed: false });
+                    var pubkeyBuffer = keyPair.getPublicKeyBuffer();
+                    var ethPubkey = libs.ethUtil.importPublic(pubkeyBuffer);
+                    var addressBuffer = libs.ethUtil.publicToAddress(ethPubkey);
+                    address = libs.bitcoin.address.toBase58Check(addressBuffer, 0x41);
+                    if (hasPrivkey) {
+                        privkey = keyPair.d.toBuffer().toString('hex');
+                    }
+                }
+
+                // RSK values are different
+                if (networkIsRsk()) {
+                    var pubkeyBuffer = keyPair.getPublicKeyBuffer();
+                    var ethPubkey = libs.ethUtil.importPublic(pubkeyBuffer);
+                    var addressBuffer = libs.ethUtil.publicToAddress(ethPubkey);
+                    var hexAddress = addressBuffer.toString('hex');
+                    // Use chainId based on selected network
+                    // Ref: https://developers.rsk.co/rsk/architecture/account-based/#chainid
+                    var chainId;
+                    var rskNetworkName = networks[DOM.network.val()].name;
+                    switch (rskNetworkName) {
+                        case "R-BTC - RSK":
+                            chainId = 30;
+                            break;
+                        case "tR-BTC - RSK Testnet":
+                            chainId = 31;
+                            break;
+                        default:
+                            chainId = null;
+                    }
+                    var checksumAddress = toChecksumAddressForRsk(hexAddress, chainId);
+                    address = libs.ethUtil.addHexPrefix(checksumAddress);
+                    pubkey = libs.ethUtil.addHexPrefix(pubkey);
                     if (hasPrivkey) {
                         privkey = libs.ethUtil.bufferToHex(keyPair.d.toBuffer());
                     }
                     var ring = libs.handshake.KeyRing.fromPublic(keyPair.getPublicKeyBuffer())
                     address = ring.getAddress().toString();
                 }
+
                 // Stellar is different
                 if (networks[DOM.network.val()].name == "XLM - Stellar") {
                     var purpose = parseIntNoNaN(DOM.bip44purpose.val(), 44);
                     privkey = keypair.secret();
                     pubkey = address = keypair.publicKey();
                 }
+
+                // Nano currency
+                if (networks[DOM.network.val()].name == "NANO - Nano") {
+                    var nanoKeypair = libs.nanoUtil.getKeypair(index, seed);
+                    privkey = nanoKeypair.privKey;
+                    pubkey = nanoKeypair.pubKey;
+                    address = nanoKeypair.address;
+                }
+
                 if ((networks[DOM.network.val()].name == "NAS - Nebulas")) {
                     var privKeyBuffer = keyPair.d.toBuffer(32);
                     var nebulasAccount = libs.nebulas.Account.NewAccount();
                          address = libs.bchaddrSlp.toSlpAddress(address);
                      }
                  }
+
+                // ZooBC address format may vary
+                if (networks[DOM.network.val()].name == "ZBC - ZooBlockchain") {  
+                    
+                    var purpose = parseIntNoNaN(DOM.bip44purpose.val(), 44);
+                    var coin = parseIntNoNaN(DOM.bip44coin.val(), 0);
+                    var path = "m/";
+                        path += purpose + "'/";
+                        path += coin + "'/" + index + "'";
+                    var result = libs.zoobcUtil.getKeypair(path, seed);
+    
+                    let publicKey = result.pubKey.slice(1, 33);
+                    let privateKey = result.key;
+    
+                    privkey = privateKey.toString('hex');
+                    pubkey = publicKey.toString('hex');
+    
+                    indexText = path;
+                    address = libs.zoobcUtil.getZBCAddress(publicKey, 'ZBC');
+                }
+
                 // Segwit addresses are different
                 if (isSegwit) {
                     if (!segwitAvailable) {
 
               if (networks[DOM.network.val()].name == "EOS - EOSIO") {
                     address = ""
-                    pubkey = eosUtil.bufferToPublic(keyPair.getPublicKeyBuffer());
-                    privkey = eosUtil.bufferToPrivate(keyPair.d.toBuffer(32));
+                    pubkey = EOSbufferToPublic(keyPair.getPublicKeyBuffer());
+                    privkey = EOSbufferToPrivate(keyPair.d.toBuffer(32));
+                }
+
+                if (networks[DOM.network.val()].name == "FIO - Foundation for Interwallet Operability") {
+                    address = ""
+                    pubkey = FIObufferToPublic(keyPair.getPublicKeyBuffer());
+                    privkey = FIObufferToPrivate(keyPair.d.toBuffer(32));
+                }
+
+                if (networks[DOM.network.val()].name == "ATOM - Cosmos Hub") {
+                    address = CosmosBufferToAddress(keyPair.getPublicKeyBuffer());
+                    pubkey = CosmosBufferToPublic(keyPair.getPublicKeyBuffer());
+                    privkey = keyPair.d.toBuffer().toString("base64");
                 }
 
                 //Groestlcoin Addresses are different
         var numberOfBits = entropy.binaryStr.length;
         var timeToCrack = "unknown";
         try {
-            var z = libs.zxcvbn(entropy.base.parts.join(""));
+            var z = libs.zxcvbn(entropy.base.events.join(""));
             timeToCrack = z.crack_times_display.offline_fast_hashing_1e10_per_second;
             if (z.feedback.warning != "") {
                 timeToCrack = timeToCrack + " - " + z.feedback.warning;
         DOM.entropyFiltered.html(entropy.cleanHtml);
         DOM.entropyType.text(entropyTypeStr);
         DOM.entropyCrackTime.text(timeToCrack);
-        DOM.entropyEventCount.text(entropy.base.ints.length);
+        DOM.entropyEventCount.text(entropy.base.events.length);
         DOM.entropyBits.text(numberOfBits);
         DOM.entropyWordCount.text(wordCount);
         DOM.entropyBinary.text(spacedBinaryStr);
             // Detect duplicates
             var dupes = [];
             var dupeTracker = {};
-            for (var i=0; i<entropy.base.parts.length; i++) {
-                var card = entropy.base.parts[i];
+            for (var i=0; i<entropy.base.events.length; i++) {
+                var card = entropy.base.events[i];
                 var cardUpper = card.toUpperCase();
                 if (cardUpper in dupeTracker) {
                     dupes.push(card);
                     || (name == "ESN - Ethersocial Network")
                     || (name == "VET - VeChain")
                     || (name == "ERE - EtherCore")
+                    || (name == "BSC - Binance Smart Chain")
+    }
+
+    function networkIsRsk() {
+        var name = networks[DOM.network.val()].name;
+        return (name == "R-BTC - RSK")
+            || (name == "tR-BTC - RSK Testnet");
     }
 
     function networkHasSegwit() {
         return DOM.bip141tab.hasClass("active");
     }
 
+    function setBip44ChangeValue() {
+        if (isDefaultBip44ChangeValue) {
+            if (networkIsEthereum()) {
+                DOM.bip44change.val("");
+            } else {
+                DOM.bip44change.val(0);
+            }
+        }
+    }
+
+    function modifiedDefaultBip44ChangeValue() {
+        isDefaultBip44ChangeValue = false;
+    }
+
+    function resetDefaultBip44ChangeValue() {
+        isDefaultBip44ChangeValue = true;
+        setBip44ChangeValue();
+    }
+
     function setHdCoin(coinValue) {
         DOM.bip44coin.val(coinValue);
         DOM.bip49coin.val(coinValue);
         DOM.bip84coin.val(coinValue);
+        setBip44ChangeValue();
     }
 
     function showSegwitAvailable() {
                 setHdCoin(357);
             },
         },
+        {
+            name: "ATOM - Cosmos Hub",
+            onSelect: function() {
+                network = libs.bitcoin.networks.bitcoin;
+                setHdCoin(118);
+            },
+        },
         {
             name: "AUR - Auroracoin",
             onSelect: function() {
                 setHdCoin(183);
             },
         },
+        {
+            name: "BSC - Binance Smart Chain",
+            onSelect: function() {
+                network = libs.bitcoin.networks.bitcoin;
+                setHdCoin(60);
+            },
+        },
         {
             name: "BSV - BitcoinSV",
             onSelect: function() {
                 setHdCoin(186);
             },
         },
+        {
+            name: "CRP - CranePay",
+            onSelect: function() {
+                network = libs.bitcoin.networks.cranepay;
+                setHdCoin(2304);
+            },
+        },
+
         {
             name: "CRW - Crown (Legacy)",
             onSelect: function() {
                 setHdCoin(40);
             },
         },
+        {
+            name: "FIO - Foundation for Interwallet Operability",
+            onSelect: function() {
+                network = libs.bitcoin.networks.bitcoin;
+                setHdCoin(235);
+            },
+        },
+        {
+            name: "FIRO - Firo (Zcoin rebrand)",
+            onSelect: function() {
+                network = libs.bitcoin.networks.firo;
+                setHdCoin(136);
+            },
+        },
         {
             name: "FIX - FIX",
             onSelect: function() {
                 setHdCoin(184);
             },
         },
+        {
+            name: "NANO - Nano",
+            onSelect: function() {
+                network = network = libs.nanoUtil.dummyNetwork;
+                setHdCoin(165);
+            },
+        },
         {
             name: "NAV - Navcoin",
             onSelect: function() {
             },
         },
         {
-            name: "RBTC - RSK",
+            name: "R-BTC - RSK",
             onSelect: function() {
-                network = libs.bitcoin.networks.rubycoin;
+                network = libs.bitcoin.networks.rsk;
                 setHdCoin(137);
             },
         },
         {
-            name: "tRBTC - RSK Testnet",
+            name: "tR-BTC - RSK Testnet",
             onSelect: function() {
-                network = libs.bitcoin.networks.rubycoin;
+                network = libs.bitcoin.networks.rsktestnet;
                 setHdCoin(37310);
             },
         },
                 setHdCoin(4);
             },
         },
+        {
+            name: "RITO - Ritocoin",
+            onSelect: function() {
+                network = libs.bitcoin.networks.ritocoin;
+                setHdCoin(19169);
+            },
+        },
         {
             name: "RVR - RevolutionVR",
             onSelect: function() {
               setHdCoin(19165);
             },
         },
+        {
+            name: "SCRIBE - Scribe",
+            onSelect: function() {
+                network = libs.bitcoin.networks.scribe;
+                setHdCoin(545);
+            },
+        },
     {
           name: "SLS - Salus",
           onSelect: function() {
                 setHdCoin(159);
             },
         },
+        {
+            name: "TRX - Tron",
+            onSelect: function() {
+                setHdCoin(195);
+            },
+        },
         {
             name: "TWINS - TWINS",
             onSelect: function() {
             },
         },
         {
-            name: "XZC - Zcoin",
+            name: "XZC - Zcoin (rebranded to Firo)",
             onSelect: function() {
                 network = libs.bitcoin.networks.zcoin;
                 setHdCoin(136);
             },
         },
+        {
+            name: "ZBC - ZooBlockchain",
+            onSelect: function () {
+            network = libs.bitcoin.networks.zoobc;
+            setHdCoin(883);
+            },
+        },
         {
             name: "ZCL - Zclassic",
             onSelect: function() {
         }
     ]
 
+    // RSK - RSK functions - begin
+    function stripHexPrefix(address) {
+        if (typeof address !== "string") {
+            throw new Error("address parameter should be a string.");
+        }
+
+        var hasPrefix = (address.substring(0, 2) === "0x" ||
+            address.substring(0, 2) === "0X");
+
+        return hasPrefix ? address.slice(2) : address;
+    };
+
+    function toChecksumAddressForRsk(address, chainId = null) {
+        if (typeof address !== "string") {
+            throw new Error("address parameter should be a string.");
+        }
+
+        if (!/^(0x)?[0-9a-f]{40}$/i.test(address)) {
+            throw new Error("Given address is not a valid RSK address: " + address);
+        }
+
+        var stripAddress = stripHexPrefix(address).toLowerCase();
+        var prefix = chainId != null ? chainId.toString() + "0x" : "";
+        var keccakHash = libs.ethUtil.keccak256(prefix + stripAddress)
+            .toString("hex")
+            .replace(/^0x/i, "");
+        var checksumAddress = "0x";
+
+        for (var i = 0; i < stripAddress.length; i++) {
+            checksumAddress +=
+                parseInt(keccakHash[i], 16) >= 8 ?
+                stripAddress[i].toUpperCase() :
+                stripAddress[i];
+        }
+
+        return checksumAddress;
+    }
+
+    // RSK - RSK functions - end
+
     // ELA - Elastos functions - begin
     function displayBip44InfoForELA() {
         if (!isELA()) {