1 2var get_hash; 3 4function remove_accents (str) { 5 return str.replace(/[^\u0000-\u007E]/g, function(a){ 6 return diacriticsMap[a] || a; 7 }); 8} 9 10var CJK_INTERVALS = [ 11 [0x4E00, 0x9FFF, 'CJK Unified Ideographs'], 12 [0x3400, 0x4DBF, 'CJK Unified Ideographs Extension A'], 13 [0x20000, 0x2A6DF, 'CJK Unified Ideographs Extension B'], 14 [0x2A700, 0x2B73F, 'CJK Unified Ideographs Extension C'], 15 [0x2B740, 0x2B81F, 'CJK Unified Ideographs Extension D'], 16 [0xF900, 0xFAFF, 'CJK Compatibility Ideographs'], 17 [0x2F800, 0x2FA1D, 'CJK Compatibility Ideographs Supplement'], 18 [0x3190, 0x319F , 'Kanbun'], 19 [0x2E80, 0x2EFF, 'CJK Radicals Supplement'], 20 [0x2F00, 0x2FDF, 'CJK Radicals'], 21 [0x31C0, 0x31EF, 'CJK Strokes'], 22 [0x2FF0, 0x2FFF, 'Ideographic Description Characters'], 23 [0xE0100, 0xE01EF, 'Variation Selectors Supplement'], 24 [0x3100, 0x312F, 'Bopomofo'], 25 [0x31A0, 0x31BF, 'Bopomofo Extended'], 26 [0xFF00, 0xFFEF, 'Halfwidth and Fullwidth Forms'], 27 [0x3040, 0x309F, 'Hiragana'], 28 [0x30A0, 0x30FF, 'Katakana'], 29 [0x31F0, 0x31FF, 'Katakana Phonetic Extensions'], 30 [0x1B000, 0x1B0FF, 'Kana Supplement'], 31 [0xAC00, 0xD7AF, 'Hangul Syllables'], 32 [0x1100, 0x11FF, 'Hangul Jamo'], 33 [0xA960, 0xA97F, 'Hangul Jamo Extended A'], 34 [0xD7B0, 0xD7FF, 'Hangul Jamo Extended B'], 35 [0x3130, 0x318F, 'Hangul Compatibility Jamo'], 36 [0xA4D0, 0xA4FF, 'Lisu'], 37 [0x16F00, 0x16F9F, 'Miao'], 38 [0xA000, 0xA48F, 'Yi Syllables'], 39 [0xA490, 0xA4CF, 'Yi Radicals'], 40]; 41 42 43function is_cjk(c) 44{ 45 n = c.charCodeAt(0); 46 for(j = 0; j < CJK_INTERVALS.length; j++) 47 { 48 if(n>=CJK_INTERVALS[j][0] && n<=CJK_INTERVALS[j][1]) 49 { 50 return true; 51 } 52 } 53 return false; 54} 55 56function seed_normalize_text(seed) 57{ 58 if(seed == "") 59 { 60 return seed; 61 } 62 var normalized_seed = seed.normalize('NFKD'); 63 normalized_seed = normalized_seed.toLowerCase(); 64 65 normalized_seed = remove_accents(normalized_seed); 66 normalized_seed = normalized_seed.trim().replace(/ {2,}/, ' '); 67 var final_seed = ""; 68 for(i = 0; i < normalized_seed.length; i++) 69 { 70 if(normalized_seed[i] == ' ') 71 { 72 if(is_cjk(normalized_seed[i-1]) && is_cjk(normalized_seed[i+1])) 73 { 74 75 } 76 else 77 { 78 final_seed += normalized_seed[i]; 79 } 80 } 81 else 82 { 83 final_seed += normalized_seed[i]; 84 } 85 } 86 return final_seed; 87} 88function randrange(min, max) { 89 var range = max - min; 90 if (range <= 0) { 91 throw new Exception('max must be larger than min'); 92 } 93 var requestBytes = Math.ceil(Math.log2(range) / 8); 94 if (!requestBytes) { // No randomness required 95 return min; 96 } 97 var maxNum = Math.pow(256, requestBytes); 98 var ar = new Uint8Array(requestBytes); 99 100 while (true) { 101 window.crypto.getRandomValues(ar); 102 103 var val = 0; 104 for (var i = 0;i < requestBytes;i++) { 105 val = (val << 8) + ar[i]; 106 } 107 108 if (val < maxNum - maxNum % range) { 109 return min + (val % range); 110 } 111 } 112} 113 114levensteinDistance = function(a, b){ 115 if(a.length == 0) return b.length; 116 if(b.length == 0) return a.length; 117 118 var matrix = []; 119 120 var i; 121 for(i = 0; i <= b.length; i++){ 122 matrix[i] = [i]; 123 } 124 125 var j; 126 for(j = 0; j <= a.length; j++){ 127 matrix[0][j] = j; 128 } 129 130 // Fill in the rest of the matrix 131 for(i = 1; i <= b.length; i++){ 132 for(j = 1; j <= a.length; j++){ 133 if(b.charAt(i-1) == a.charAt(j-1)){ 134 matrix[i][j] = matrix[i-1][j-1]; 135 } else { 136 matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, 137 Math.min(matrix[i][j-1] + 1, 138 matrix[i-1][j] + 1)); 139 } 140 } 141 } 142 143 return matrix[b.length][a.length]; 144}; 145 146function verify_bip39(seed){ 147 var words = seed.trim().split(" ").map( word => { 148 return seed_words_english.indexOf(word); 149 });
150 151 var i; 152 for(i = 0; i < words.length; i++) 153 { 154 if(!seed_words_english.includes(words[i])){ 155 //invalid seed 156 $("#seed_error").html('<span class="glyphicon glyphicon-exclamation-sign"></span> ÐевеÑнÑй Seed'); 157 $("#seed_error").show(); 158 return false; 159 } 160 } 161 162 if(words.length != 12 && words.length != 24){ 163 $("#seed_error").html('<span class="glyphicon glyphicon-exclamation-sign"></span> ÐевеÑнÑй Seed'); 164 $("#seed_error").show(); 165 return false; 166 } 167 168 var csLen = words.length/3; 169 var payloadLen = words.length*11 - csLen; 170 171 var arr = new Uint8Array(payloadLen/8); 172 for(let i = 0; i < arr.length; i++){ 173 let startWord = Math.floor(i*8/11); 174 let startPos = i*8 % 11; 175 let endWord = Math.floor((i+1)*8/11); 176 let endPos = (i+1)*8 % 11; 177 arr[i] = (words[startWord] << (startPos-3)) | (words[endWord] >> (11-endPos)); 178 } 179 180 // checksum check 181 var ccs = words[words.length-1] & (Math.pow(2,csLen-1)); 182 return window.crypto.subtle.digest({name: "SHA-256"}, arr).then(function (hash) { 183 var h = new Uint8Array(hash); 184 var cs = h[0] >> (8 - csLen); 185 if(cs == ccs){ 186 return true; 187 }else{ 188 return false; 189 } 190 }); 191} 192 193function fix_bip39(seed){ 194 var words = seed.trim().split(" ").map( word => { 195 let ind = seed_words_english.indexOf(word); 196 if(ind == -1){ 197 ind = 0; 198 let distance = Infinity; 199 for (let i = 0; i < seed_words_english.length; i++) { 200 let curDistance = levensteinDistance(word, seed_words_english[i]); 201 if(curDistance < distance){ 202 distance = curDistance; 203 ind = i; 204 } 205 } 206 } 207 return ind; 208 }); 209 210 if(words.length % 3 != 0) 211 { 212 return false; 213 } 214 215 var csLen = words.length/3; 216 var payloadLen = words.length*11 - csLen; 217 218 var arr = new Uint8Array(payloadLen/8); 219 for(let i = 0; i < arr.length; i++){ 220 let startWord = Math.floor(i*8/11); 221 let startPos = i*8 % 11; 222 let endWord = Math.floor((i+1)*8/11); 223 let endPos = (i+1)*8 % 11; 224 arr[i] = (words[startWord] << (startPos-3)) | (words[endWord] >> (11-endPos)); 225 } 226 227 var ccs = words[words.length-1] & (Math.pow(2,csLen-1)); 228 return window.crypto.subtle.digest({name: "SHA-256"}, arr).then(function (hash) { 229 var h = new Uint8Array(hash); 230 var cs = h[0] >> (8 - csLen); 231 words[words.length-1] = words[words.length-1] - ccs + cs; 232 var newseed = words.map( w => { return seed_words_english[w]; }).join(" "); 233 return newseed; 234 }); 235} 236 237function check_seed_hash(prefix){ 238 return function(hash){ 239 return hash.startsWith(prefix); 240 }; 241} 242 243var seed_formats = [ 244 { 245 name: "Standard", 246 verify_hash: check_seed_hash("01") 247 }, 248 { 249 name: "SegWit", 250 verify_hash: check_seed_hash("100") 251 }, 252 { 253 name: "BIP-39", 254 verify_bip39: verify_bip39, 255 } 256] 257 258 259var seed_standard_prefix = "01"; 260var seed_segwit_prefix = "100"; 261 262var seed_enc = new TextEncoder("utf-8"); 263var seed_key; 264 265window.crypto.subtle.importKey( 266 "raw", seed_enc.encode("Seed version"), { name: "HMAC", hash: {name: "SHA-512"} }, false, ["sign", "verify"] 267).then( k => { 268 seed_key = k; 269}); 270function seed_gethash(str){ 271 return window.crypto.subtle.sign("HMAC", seed_key, seed_enc.encode(str)).then(signature => { 272 var b = new Uint8Array(signature); 273 var hash = Array.prototype.map.call(b, x => ('00'+x.toString(16)).slice(-2)).join("") 274 return {str: str, hash: hash}; 275 }); 276} 277 278var bitamp_seed_type = ''; 279 280function check_seed_type(seed){ 281 return seed_gethash(seed).then(seed_hash => 282 { 283 var final_seed_type = ""; 284 seed_formats.some( format => { 285 if("verify_hash" in format) 286 { 287 let isvalid = format.verify_hash(seed_hash.hash); 288 if(isvalid) 289 { 290 final_seed_type = format.name; 291 return true; 292 } 293 } 294 else if("verify_bip39" in format) 295 { 296 if(format.verify_bip39(seed_hash.str)) 297 { 298 final_seed_type = format.name; 299 return true; 300 } 301 } 302 }); 303 if(final_seed_type == "") 304 { 305 if(bitcoinjs.bip39.validateMnemonic(seed)) 306 { 307 final_seed_type = "bip39"; 308 } 309 else 310 { 311 final_seed_type = "Unknown"; 312 } 313 } 314 bitamp_seed_type = final_seed_type; 315 return final_seed_type; 316 });
317} 318var account_address_type=[], 319 account_bip39_number=[]; 320 321var pubkey_a=[]; 322 323function mnemonic_to_seed(mnemonic, passphrase='') 324{ 325 return check_seed_type(mnemonic).then(seed_type_temp => 326 { 327 try 328 { 329 if(seed_type_temp == "Unknown") 330 { 331 return false; 332 } 333 334 335 seed_type = seed_type_temp; 336 337 reserved_data_PBKDF2_ROUNDS = 2048; 338 reserved_data_final_mnemonic = seed_normalize_text(mnemonic); 339 reserved_data_final_passphrase = 'electrum' + seed_normalize_text(passphrase); 340 reserved_data_final_passphrase_bip39 = 'mnemonic' + seed_normalize_text(passphrase); 341 342 reserved_data_seed_output = CryptoJS.PBKDF2(reserved_data_final_mnemonic, reserved_data_final_passphrase.toString('binary'), { hasher: CryptoJS.algo.SHA512, keySize: 512/32, iterations: reserved_data_PBKDF2_ROUNDS }).toString(); 343 reserved_data_seed_output_bip39 = CryptoJS.PBKDF2(reserved_data_final_mnemonic, reserved_data_final_passphrase_bip39.toString('binary'), { hasher: CryptoJS.algo.SHA512, keySize: 512/32, iterations: reserved_data_PBKDF2_ROUNDS }).toString(); 344 345 346 reserved_data_root = bitcoinjs.bip32.fromSeed(bitcoinjs.Buffer.from(reserved_data_seed_output, 'hex')); 347 reserved_data_root_bip39 = bitcoinjs.bip32.fromSeed(bitcoinjs.Buffer.from(reserved_data_seed_output_bip39, 'hex')); 348 349 350 351 account_keys_legacy = []; 352 account_keys_segwit = []; 353 account_keys_p2sh = []; 354 355 account_keys_legacy_change = []; 356 account_keys_segwit_change = []; 357 account_keys_p2sh_change = []; 358 359 account_keys_new = []; 360 361 var final_session_id = ''; 362 account_session_id = null; 363 364 if(seed_type == "bip39") 365 { 366 total_bip39_accounts = 1; 367 } 368 369 //standard 370 for(d = 0; d < 20; d++) 371 { 372 if(seed_type == "bip39") 373 { 374 child = reserved_data_root_bip39.derivePath("m/44'/0'/0'/0/" + d.toString()); 375 } 376 else 377 { 378 child = reserved_data_root.derivePath('m/0/' + d.toString()); 379 } 380 wif = child.toWIF(); 381 public_addr = bitcoinjs.payments.p2pkh({ pubkey: child.publicKey, network: bitcoinjs.networks.bitcoin }).address; 382 account_keys_legacy.push({"private": wif, "public": public_addr}); 383 account_address_type[public_addr] = 0; 384 pubkey_a[public_addr]=bitcoinjs.payments.p2pkh({ pubkey: child.publicKey, network: bitcoinjs.networks.bitcoin }).output; 385 if(seed_type == "bip39") 386 { 387 account_bip39_number[public_addr] = total_bip39_accounts; 388 } 389 account_keys_new.push({"private": wif, "public": public_addr}); 390 if(d == 0 || d == 1) 391 { 392 if(d==1) 393 { 394 final_session_id += ":"; 395 396 }else{ 397 get_hash=public_addr; 398 } 399 final_session_id += public_addr; 400 401 } 402 } 403 404 //standard change 405 for(d = 0; d < 6; d++) 406 { 407 if(seed_type == "bip39") 408 { 409 child = reserved_data_root_bip39.derivePath("m/44'/0'/0'/1/" + d.toString()); 410 } 411 else 412 { 413 child = reserved_data_root.derivePath('m/1/' + d.toString()); 414 } 415 416 wif = child.toWIF(); 417 public_addr = bitcoinjs.payments.p2pkh({ pubkey: child.publicKey, network: bitcoinjs.networks.bitcoin }).address; 418 account_keys_legacy_change.push({"private": wif, "public": public_addr}); 419 account_address_type[public_addr] = 3; 420 pubkey_a[public_addr]=bitcoinjs.payments.p2pkh({ pubkey: child.publicKey, network: bitcoinjs.networks.bitcoin }).output; 421 if(seed_type == "bip39") 422 { 423 account_bip39_number[public_addr] = total_bip39_accounts; 424 } 425 account_keys_new.push({"private": wif, "public": public_addr}); 426 } 427 428 //segwit 429 for(d = 0; d < 20; d++) 430 { 431 if(seed_type == "bip39") 432 { 433 child = reserved_data_root_bip39.derivePath("m/84'/0'/0'/0/" + d.toString()); 434 } 435 else 436 { 437 child = reserved_data_root.derivePath("m/0'/0/" + d.toString()); 438 } 439 wif = child.toWIF(); 440 public_addr = bitcoinjs.payments.p2wpkh({ pubkey: child.publicKey, network: bitcoinjs.networks.bitcoin }).address; 441 account_keys_segwit.push({"private": wif, "public": public_addr}); 442 account_address_type[public_addr] = 1; 443 pubkey_a[public_addr]=bitcoinjs.payments.p2pkh({ pubkey: child.publicKey, network: bitcoinjs.networks.bitcoin }).output; 444 if(seed_type == "bip39") 445 { 446 account_bip39_number[public_addr] = total_bip39_accounts; 447 } 448 account_keys_new.push({"private": wif, "public": public_addr}); 449 if(d == 0 || d == 1) 450 { 451 final_session_id += ":" + public_addr; 452 } 453 } 454 455 //segwit change 456 457 for(d = 0; d < 6; d++) 458 { 459 if(seed_type == "bip39") 460 { 461 child = reserved_data_root_bip39.derivePath("m/84'/0'/0'/1/" + d.toString()); 462 } 463 else 464 { 465 child = reserved_data_root.derivePath("m/0'/1/" + d.toString()); 466 } 467 468 wif = child.toWIF(); 469 public_addr = bitcoinjs.payments.p2wpkh({ pubkey: child.publicKey, network: bitcoinjs.networks.bitcoin }).address; 470 account_keys_segwit_change.push({"private": wif, "public": public_addr}); 471 account_address_type[public_addr] = 4; 472 pubkey_a[public_addr]=bitcoinjs.payments.p2pkh({ pubkey: child.publicKey, network: bitcoinjs.networks.bitcoin }).output; 473 if(seed_type == "bip39") 474 { 475 account_bip39_number[public_addr] = total_bip39_accounts; 476 } 477 account_keys_new.push({"private": wif, "public": public_addr}); 478 } 479 480 //p2sh 481 482 for(d = 0; d < 20; d++) 483 { 484 child = reserved_data_root_bip39.derivePath("m/49'/0'/0'/0/" + d.toString()); 485 wif = child.toWIF(); 486 public_addr = bitcoinjs.payments.p2sh({ redeem: bitcoinjs.payments.p2wpkh({ pubkey: child.publicKey, network: bitcoinjs.networks.bitcoin }) }).address; 487 account_keys_p2sh.push({"private": wif, "public": public_addr}); 488 account_address_type[public_addr] = 2; 489 pubkey_a[public_addr]=bitcoinjs.payments.p2pkh({ pubkey: child.publicKey, network: bitcoinjs.networks.bitcoin }).output; 490 if(seed_type == "bip39") 491 { 492 account_bip39_number[public_addr] = total_bip39_accounts; 493 } 494 account_keys_new.push({"private": wif, "public": public_addr}); 495 496 if(d == 0 || d == 1) 497 { 498 final_session_id += ":" + public_addr; 499 } 500 } 501 502 //p2sh change 503 for(d = 0; d < 6; d++) 504 { 505 child = reserved_data_root_bip39.derivePath("m/49'/0'/0'/1/" + d.toString()); 506 wif = child.toWIF(); 507 public_addr = bitcoinjs.payments.p2sh({ redeem: bitcoinjs.payments.p2wpkh({ pubkey: child.publicKey, network: bitcoinjs.networks.bitcoin }) }).address; 508 account_keys_p2sh_change.push({"private": wif, "public": public_addr}); 509 account_address_type[public_addr] = 5; 510 pubkey_a[public_addr]=bitcoinjs.payments.p2pkh({ pubkey: child.publicKey, network: bitcoinjs.networks.bitcoin }).output; 511 if(seed_type == "bip39") 512 { 513 account_bip39_number[public_addr] = total_bip39_accounts; 514 } 515 account_keys_new.push({"private": wif, "public": public_addr}); 516 } 517 518 temp_account_session_id = final_session_id; 519 520 } 521 catch(e) 522 { 523 console.log(e); 524 return false; 525 } 526 527 528 return true; 529 }); 530}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.