├── README ├── icon.png ├── icon_128.png ├── icon_64.png ├── manifest.json ├── popup.css ├── popup.html └── popup.js /README: -------------------------------------------------------------------------------- 1 | Create passwords for different websites (or anything else) using a single 2 | secret key (if you lose your password for a website, you can regenerate it if 3 | you remember your secret key.) 4 | 5 | Algorithm 6 | --------- 7 | 8 | password = base64(pbkdf2(secret, username@url)) 9 | 10 | (return first max password length characters) 11 | PBKDF2 uses SHA-256, 5000 iterations. 12 | 13 | License 14 | -------- 15 | 16 | The MIT License 17 | 18 | Copyright (c) 2010-2012 Dmitry Chestnykh 19 | 20 | Permission is hereby granted, free of charge, to any person obtaining a copy 21 | of this software and associated documentation files (the "Software"), to deal 22 | in the Software without restriction, including without limitation the rights 23 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 24 | copies of the Software, and to permit persons to whom the Software is 25 | furnished to do so, subject to the following conditions: 26 | 27 | The above copyright notice and this permission notice shall be included in 28 | all copies or substantial portions of the Software. 29 | 30 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 31 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 32 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 33 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 34 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 35 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 36 | THE SOFTWARE. 37 | 38 | Includes portions of sjcl (BSD License, see source). 39 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dchest/cryptopass/c0397af267a1133cdaa6d0b1c8ec6d34c56ba417/icon.png -------------------------------------------------------------------------------- /icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dchest/cryptopass/c0397af267a1133cdaa6d0b1c8ec6d34c56ba417/icon_128.png -------------------------------------------------------------------------------- /icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dchest/cryptopass/c0397af267a1133cdaa6d0b1c8ec6d34c56ba417/icon_64.png -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CryptoPass", 3 | "version": "1.12", 4 | "manifest_version": 2, 5 | "description" : "Generate different passwords from single master password using cryptographically strong method (PBKDF2 with SHA-256).", 6 | "icons": { 7 | "128": "icon_128.png", 8 | "64": "icon_64.png" 9 | }, 10 | "permissions": [ 11 | "activeTab" 12 | ], 13 | "browser_action": { 14 | "default_title": "CryptoPass", 15 | "default_icon": "icon.png", 16 | "default_popup": "popup.html" 17 | }, 18 | "content_security_policy": "default-src 'self'" 19 | } 20 | 21 | -------------------------------------------------------------------------------- /popup.css: -------------------------------------------------------------------------------- 1 | body { 2 | font: 10pt "Lucida Grande", Helvetica, Arial, sans-serif; 3 | width: 350px; 4 | border-radius: 10px; 5 | color: #303942; 6 | margin-right: 20px; 7 | user-select: none; 8 | -webkit-user-select: none; 9 | cursor: default; 10 | } 11 | table { 12 | margin: 0; 13 | width: 100%; 14 | } 15 | .label { 16 | text-align: right; 17 | padding-right: 5px; 18 | } 19 | #secret, #url, #username, #result { 20 | width: 100%; 21 | } 22 | .length, #length { 23 | font-size: 8pt; 24 | color: #999; 25 | } 26 | .centered { 27 | text-align: center; 28 | } 29 | #result-box { 30 | display: none; 31 | text-align: center; 32 | } 33 | #warning { 34 | display: none; 35 | font-size: 10px; 36 | color: #cc0011; 37 | padding: 3px 0; 38 | text-align: center; 39 | margin-top: -10px; 40 | } 41 | input { 42 | border: 1px solid rgba(0, 0, 0, 0.25); 43 | padding: 3px 3px; 44 | border-radius: 2px; 45 | outline: none; 46 | } 47 | input:focus { 48 | border-color: #4D90FE; 49 | } 50 | .buttons { 51 | text-align: right; 52 | } 53 | button { 54 | /* 55 | background: #f4f4f4 -webkit-gradient(linear,left top,left bottom, 56 | color-stop(0, #fafafa),color-stop(1, #ccc)); 57 | border: 1px solid #aaa; 58 | border-radius: 5px; 59 | padding: 3px 10px; 60 | margin-top: 3px; 61 | text-shadow: 0 1px #f4f4f4; 62 | */ 63 | background-image: -webkit-linear-gradient(#e8e8e8, #e8e8e8 38%, #d8d8d8); 64 | background-color: rgba(0, 0, 0, 0.3); 65 | box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95); 66 | color: black; 67 | text-shadow: 0 1px 0 #F0F0F0; 68 | border: 1px solid rgba(0, 0, 0, 0.25); 69 | border-radius: 2px; 70 | margin: 0 1px 0 0; 71 | outline: none; 72 | } 73 | button:focus { 74 | border-color: #4D90FE; 75 | } 76 | button:hover { 77 | background-image: -webkit-linear-gradient(#F0F0F0, #F0F0F0 38%, #E0E0E0); 78 | border: 1px solid rgba(0, 0, 0, 0.3); 79 | } 80 | button:active { 81 | /*background: #f4f4f4 -webkit-gradient(linear,left top,left bottom, 82 | color-stop(1, #ddd),color-stop(0, #bbb)) 83 | */ 84 | background-image: none; 85 | background-color: rgba(0, 0, 0, 0.15); 86 | box-shadow: none; 87 | } 88 | .gray { 89 | color:#666; 90 | } 91 | .working { 92 | font-size: 9pt; 93 | color: #ccc; 94 | } 95 | -------------------------------------------------------------------------------- /popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | CryptoPass 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 31 | 35 |
Secret
Username
URL
Length 29 | characters 30 | 32 | 33 | 34 |
36 |
37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /popup.js: -------------------------------------------------------------------------------- 1 | /* SJCL LICENSE 2 | * 3 | * Copyright 2009-2010 Emily Stark, Mike Hamburg, Dan Boneh. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are 8 | * met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above 14 | * copyright notice, this list of conditions and the following 15 | * disclaimer in the documentation and/or other materials provided 16 | * with the distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 28 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * The views and conclusions contained in the software and documentation 31 | * are those of the authors and should not be interpreted as representing 32 | * official policies, either expressed or implied, of the authors. 33 | */ 34 | 35 | // sjcl.js 36 | 37 | /** @fileOverview Javascript cryptography implementation. 38 | * 39 | * Crush to remove comments, shorten variable names and 40 | * generally reduce transmission size. 41 | * 42 | * @author Emily Stark 43 | * @author Mike Hamburg 44 | * @author Dan Boneh 45 | */ 46 | 47 | "use strict"; 48 | /*jslint indent: 2, bitwise: false, nomen: false, plusplus: false, white: false, regexp: false */ 49 | /*global document, window, escape, unescape */ 50 | 51 | /** @namespace The Stanford Javascript Crypto Library, top-level namespace. */ 52 | var sjcl = { 53 | /** @namespace Symmetric ciphers. */ 54 | cipher: {}, 55 | 56 | /** @namespace Hash functions. Right now only SHA256 is implemented. */ 57 | hash: {}, 58 | 59 | /** @namespace Block cipher modes of operation. */ 60 | mode: {}, 61 | 62 | /** @namespace Miscellaneous. HMAC and PBKDF2. */ 63 | misc: {}, 64 | 65 | /** 66 | * @namespace Bit array encoders and decoders. 67 | * 68 | * @description 69 | * The members of this namespace are functions which translate between 70 | * SJCL's bitArrays and other objects (usually strings). Because it 71 | * isn't always clear which direction is encoding and which is decoding, 72 | * the method names are "fromBits" and "toBits". 73 | */ 74 | codec: {}, 75 | 76 | /** @namespace Exceptions. */ 77 | exception: { 78 | /** @class Ciphertext is corrupt. */ 79 | corrupt: function(message) { 80 | this.toString = function() { return "CORRUPT: "+this.message; }; 81 | this.message = message; 82 | }, 83 | 84 | /** @class Invalid parameter. */ 85 | invalid: function(message) { 86 | this.toString = function() { return "INVALID: "+this.message; }; 87 | this.message = message; 88 | }, 89 | 90 | /** @class Bug or missing feature in SJCL. */ 91 | bug: function(message) { 92 | this.toString = function() { return "BUG: "+this.message; }; 93 | this.message = message; 94 | }, 95 | 96 | /** @class Something isn't ready. */ 97 | notReady: function(message) { 98 | this.toString = function() { return "NOT READY: "+this.message; }; 99 | this.message = message; 100 | } 101 | } 102 | }; 103 | 104 | // pbkdf2.js 105 | 106 | /** @fileOverview Password-based key-derivation function, version 2.0. 107 | * 108 | * @author Emily Stark 109 | * @author Mike Hamburg 110 | * @author Dan Boneh 111 | */ 112 | 113 | /** Password-Based Key-Derivation Function, version 2.0. 114 | * 115 | * Generate keys from passwords using PBKDF2-HMAC-SHA256. 116 | * 117 | * This is the method specified by RSA's PKCS #5 standard. 118 | * 119 | * @param {bitArray|String} password The password. 120 | * @param {bitArray|String} salt The salt. Should have lots of entropy. 121 | * @param {Number} [count=1000] The number of iterations. Higher numbers make the function slower but more secure. 122 | * @param {Number} [length] The length of the derived key. Defaults to the 123 | output size of the hash function. 124 | * @param {Object} [Prff=sjcl.misc.hmac] The pseudorandom function family. 125 | * @return {bitArray} the derived key. 126 | */ 127 | sjcl.misc.pbkdf2 = function (password, salt, count, length, Prff) { 128 | count = count || 1000; 129 | 130 | if (length < 0 || count < 0) { 131 | throw sjcl.exception.invalid("invalid params to pbkdf2"); 132 | } 133 | 134 | if (typeof password === "string") { 135 | password = sjcl.codec.utf8String.toBits(password); 136 | } 137 | 138 | if (typeof salt === "string") { 139 | salt = sjcl.codec.utf8String.toBits(salt); 140 | } 141 | 142 | Prff = Prff || sjcl.misc.hmac; 143 | 144 | var prf = new Prff(password), 145 | u, ui, i, j, k, out = [], b = sjcl.bitArray; 146 | 147 | for (k = 1; 32 * out.length < (length || 1); k++) { 148 | u = ui = prf.encrypt(b.concat(salt,[k])); 149 | 150 | for (i=1; i bs) { 186 | key = Hash.hash(key); 187 | } 188 | 189 | for (i=0; i>>7 ^ a>>>18 ^ a>>>3 ^ a<<25 ^ a<<14) + 421 | (b>>>17 ^ b>>>19 ^ b>>>10 ^ b<<15 ^ b<<13) + 422 | w[i&15] + w[(i+9) & 15]) | 0; 423 | } 424 | 425 | tmp = (tmp + h7 + (h4>>>6 ^ h4>>>11 ^ h4>>>25 ^ h4<<26 ^ h4<<21 ^ h4<<7) + (h6 ^ h4&(h5^h6)) + k[i]); // | 0; 426 | 427 | // shift register 428 | h7 = h6; h6 = h5; h5 = h4; 429 | h4 = h3 + tmp | 0; 430 | h3 = h2; h2 = h1; h1 = h0; 431 | 432 | h0 = (tmp + ((h1&h2) ^ (h3&(h1^h2))) + (h1>>>2 ^ h1>>>13 ^ h1>>>22 ^ h1<<30 ^ h1<<19 ^ h1<<10)) | 0; 433 | } 434 | 435 | h[0] = h[0]+h0 | 0; 436 | h[1] = h[1]+h1 | 0; 437 | h[2] = h[2]+h2 | 0; 438 | h[3] = h[3]+h3 | 0; 439 | h[4] = h[4]+h4 | 0; 440 | h[5] = h[5]+h5 | 0; 441 | h[6] = h[6]+h6 | 0; 442 | h[7] = h[7]+h7 | 0; 443 | } 444 | }; 445 | 446 | 447 | 448 | // codecString.js 449 | 450 | /** @fileOverview Bit array codec implementations. 451 | * 452 | * @author Emily Stark 453 | * @author Mike Hamburg 454 | * @author Dan Boneh 455 | */ 456 | 457 | /** @namespace UTF-8 strings */ 458 | sjcl.codec.utf8String = { 459 | /** Convert from a bitArray to a UTF-8 string. */ 460 | fromBits: function (arr) { 461 | var out = "", bl = sjcl.bitArray.bitLength(arr), i, tmp; 462 | for (i=0; i>> 24); 467 | tmp <<= 8; 468 | } 469 | return decodeURIComponent(escape(out)); 470 | }, 471 | 472 | /** Convert from a UTF-8 string to a bitArray. */ 473 | toBits: function (str) { 474 | str = unescape(encodeURIComponent(str)); 475 | var out = [], i, tmp=0; 476 | for (i=0; i 503 | * These objects are the currency accepted by SJCL's crypto functions. 504 | *

505 | * 506 | *

507 | * Most of our crypto primitives operate on arrays of 4-byte words internally, 508 | * but many of them can take arguments that are not a multiple of 4 bytes. 509 | * This library encodes arrays of bits (whose size need not be a multiple of 8 510 | * bits) as arrays of 32-bit words. The bits are packed, big-endian, into an 511 | * array of words, 32 bits at a time. Since the words are double-precision 512 | * floating point numbers, they fit some extra data. We use this (in a private, 513 | * possibly-changing manner) to encode the number of bits actually present 514 | * in the last word of the array. 515 | *

516 | * 517 | *

518 | * Because bitwise ops clear this out-of-band data, these arrays can be passed 519 | * to ciphers like AES which want arrays of words. 520 | *

521 | */ 522 | sjcl.bitArray = { 523 | /** 524 | * Array slices in units of bits. 525 | * @param {bitArray} a The array to slice. 526 | * @param {Number} bstart The offset to the start of the slice, in bits. 527 | * @param {Number} bend The offset to the end of the slice, in bits. If this is undefined, 528 | * slice until the end of the array. 529 | * @return {bitArray} The requested slice. 530 | */ 531 | bitSlice: function (a, bstart, bend) { 532 | a = sjcl.bitArray._shiftRight(a.slice(bstart/32), 32 - (bstart & 31)).slice(1); 533 | return (bend === undefined) ? a : sjcl.bitArray.clamp(a, bend-bstart); 534 | }, 535 | 536 | /** 537 | * Extract a number packed into a bit array. 538 | * @param {bitArray} a The array to slice. 539 | * @param {Number} bstart The offset to the start of the slice, in bits. 540 | * @param {Number} length The length of the number to extract. 541 | * @return {Number} The requested slice. 542 | */ 543 | extract: function(a, bstart, blength) { 544 | // FIXME: this Math.floor is not necessary at all, but for some reason 545 | // seems to suppress a bug in the Chromium JIT. 546 | var x, sh = Math.floor((-bstart-blength) & 31); 547 | if ((bstart + blength - 1 ^ bstart) & -32) { 548 | // it crosses a boundary 549 | x = (a[bstart/32|0] << (32 - sh)) ^ (a[bstart/32+1|0] >>> sh); 550 | } else { 551 | // within a single word 552 | x = a[bstart/32|0] >>> sh; 553 | } 554 | return x & ((1< 0 && len) { 600 | a[l-1] = sjcl.bitArray.partial(len, a[l-1] & 0x80000000 >> (len-1), 1); 601 | } 602 | return a; 603 | }, 604 | 605 | /** 606 | * Make a partial word for a bit array. 607 | * @param {Number} len The number of bits in the word. 608 | * @param {Number} x The bits. 609 | * @param {Number} [0] _end Pass 1 if x has already been shifted to the high side. 610 | * @return {Number} The partial word. 611 | */ 612 | partial: function (len, x, _end) { 613 | if (len === 32) { return x; } 614 | return (_end ? x|0 : x << (32-len)) + len * 0x10000000000; 615 | }, 616 | 617 | /** 618 | * Get the number of bits used by a partial word. 619 | * @param {Number} x The partial word. 620 | * @return {Number} The number of bits used by the partial word. 621 | */ 622 | getPartial: function (x) { 623 | return Math.round(x/0x10000000000) || 32; 624 | }, 625 | 626 | /** 627 | * Compare two arrays for equality in a predictable amount of time. 628 | * @param {bitArray} a The first array. 629 | * @param {bitArray} b The second array. 630 | * @return {boolean} true if a == b; false otherwise. 631 | */ 632 | equal: function (a, b) { 633 | if (sjcl.bitArray.bitLength(a) !== sjcl.bitArray.bitLength(b)) { 634 | return false; 635 | } 636 | var x = 0, i; 637 | for (i=0; i= 32; shift -= 32) { 655 | out.push(carry); 656 | carry = 0; 657 | } 658 | if (shift === 0) { 659 | return out.concat(a); 660 | } 661 | 662 | for (i=0; i>>shift); 664 | carry = a[i] << (32-shift); 665 | } 666 | last2 = a.length ? a[a.length-1] : 0; 667 | shift2 = sjcl.bitArray.getPartial(last2); 668 | out.push(sjcl.bitArray.partial(shift+shift2 & 31, (shift + shift2 > 32) ? carry : out.pop(),1)); 669 | return out; 670 | }, 671 | 672 | /** xor a block of 4 words together. 673 | * @private 674 | */ 675 | _xor4: function(x,y) { 676 | return [x[0]^y[0],x[1]^y[1],x[2]^y[2],x[3]^y[3]]; 677 | } 678 | }; 679 | 680 | // codecBase64.js 681 | 682 | /** @fileOverview Bit array codec implementations. 683 | * 684 | * @author Emily Stark 685 | * @author Mike Hamburg 686 | * @author Dan Boneh 687 | */ 688 | 689 | /** @namespace Base64 encoding/decoding */ 690 | sjcl.codec.base64 = { 691 | /** The base64 alphabet. 692 | * @private 693 | */ 694 | _chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", 695 | 696 | /** Convert from a bitArray to a base64 string. */ 697 | fromBits: function (arr, _noEquals, _url) { 698 | var out = "", i, bits=0, c = sjcl.codec.base64._chars, ta=0, bl = sjcl.bitArray.bitLength(arr); 699 | if (_url) { 700 | c = c.substr(0,62) + '-_'; 701 | } 702 | for (i=0; out.length * 6 < bl; ) { 703 | out += c.charAt((ta ^ arr[i]>>>bits) >>> 26); 704 | if (bits < 6) { 705 | ta = arr[i] << (6-bits); 706 | bits += 26; 707 | i++; 708 | } else { 709 | ta <<= 6; 710 | bits -= 6; 711 | } 712 | } 713 | while ((out.length & 3) && !_noEquals) { out += "="; } 714 | return out; 715 | }, 716 | 717 | /** Convert from a base64 string to a bitArray */ 718 | toBits: function(str, _url) { 719 | str = str.replace(/\s|=/g,''); 720 | var out = [], i, bits=0, c = sjcl.codec.base64._chars, ta=0, x; 721 | if (_url) { 722 | c = c.substr(0,62) + '-_'; 723 | } 724 | for (i=0; i 26) { 730 | bits -= 26; 731 | out.push(ta ^ x>>>bits); 732 | ta = x << (32-bits); 733 | } else { 734 | bits += 6; 735 | ta ^= x << (32-bits); 736 | } 737 | } 738 | if (bits&56) { 739 | out.push(sjcl.bitArray.partial(bits&56, ta, 1)); 740 | } 741 | return out; 742 | } 743 | }; 744 | 745 | sjcl.codec.base64url = { 746 | fromBits: function (arr) { return sjcl.codec.base64.fromBits(arr,1,1); }, 747 | toBits: function (str) { return sjcl.codec.base64.toBits(str,1); } 748 | }; 749 | 750 | // **** Password generation **** 751 | 752 | function makePassword() { 753 | var secret = document.getElementById('secret').value; 754 | var username = document.getElementById('username').value; 755 | var url = document.getElementById('url').value; 756 | var length = document.getElementById('length').value; 757 | var salt = username + '@' + url; 758 | var binLength = Math.ceil(length/4*3); 759 | return sjcl.codec.base64.fromBits(sjcl.misc.pbkdf2(secret, salt, 5000, binLength * 8)).substring(0, length); 760 | } 761 | 762 | 763 | function toggleDiv(id) 764 | { 765 | var infoStyle = document.getElementById(id).style; 766 | if (infoStyle.display == "block") 767 | infoStyle.display = "none"; 768 | else 769 | infoStyle.display = "block"; 770 | } 771 | 772 | function showDiv(id) 773 | { 774 | var infoStyle = document.getElementById(id).style; 775 | infoStyle.display = "block"; 776 | } 777 | 778 | function hideDiv(id) 779 | { 780 | var infoStyle = document.getElementById(id).style; 781 | infoStyle.display = "none"; 782 | } 783 | 784 | function getHostname(str) { 785 | if (str == null || str == undefined) 786 | return ""; 787 | var re = new RegExp('^(?:f|ht)tp(?:s)?\://(?:www.)?([^/]+)', 'im'); 788 | var match = str.match(re); 789 | if (match != null && match.length > 0) 790 | return match[1].toString(); 791 | else 792 | return ""; 793 | } 794 | 795 | function showPleaseWait() { 796 | document.querySelector("#result-box").innerHTML = "Please wait..."; 797 | showDiv('result-box'); 798 | } 799 | 800 | function generatePassword(event) 801 | { 802 | showPleaseWait(); 803 | setTimeout(function() { 804 | document.querySelector("#result-box").innerHTML = 805 | '

Your password (copy and paste it):
'+ 806 | '

'+ 807 | '
Secret should contain at least 16 characters for better security.
'; 808 | var result_field = document.getElementById('result'); 809 | result_field.value = makePassword(); 810 | if (document.querySelector('#secret').value.length < 16) 811 | showDiv('warning'); 812 | else 813 | hideDiv('warning'); 814 | result_field.select(); 815 | }, 0); 816 | event.preventDefault(); 817 | event.stopPropagation(); 818 | return false; 819 | } 820 | 821 | 822 | function fillPassword() { 823 | showPleaseWait(); 824 | document.querySelector("#main-form").style.display = "none"; 825 | setTimeout(function() { 826 | var username = document.getElementById('username').value || ""; 827 | var password = makePassword(); 828 | chrome.tabs.executeScript(null, {code: 829 | "(function() { " + 830 | " var forms = document.forms; " + 831 | " for (var i = 0; i < forms.length; i++) { " + 832 | " var form = forms[i]; " + 833 | " /* Check that form action domain is the same as document's. */ " + 834 | " var a = document.createElement('a'); a.href = form.action; " + 835 | " if (a.hostname !== document.domain) { continue; } /* skip this form */ " + 836 | " var inputs = form.getElementsByTagName('input'); " + 837 | " for (var j = 0; j < inputs.length; j++) { " + 838 | " var input = inputs[j]; " + 839 | " if (input.type.toLowerCase() === 'password') { " + 840 | " input.value = decodeURIComponent(\"" + encodeURIComponent(password) + "\"); " + 841 | " } else if (input.name.toLowerCase().match(/login|username|email|user/) " + 842 | " && input.type.toLowerCase().match(/text|email|tel/)) { " + 843 | " input.value = decodeURIComponent(\"" + encodeURIComponent(username) + "\"); " + 844 | " } " + 845 | " } " + 846 | " } " + 847 | "})(); " 848 | }); 849 | document.querySelector("#result-box").innerHTML = "Done!"; 850 | setTimeout(function() { 851 | window.close(); 852 | }, 500); 853 | }, 50); 854 | event.preventDefault(); 855 | return false; 856 | } 857 | 858 | var hashColors = ["#CC0000", "#0000CC", "#00CC00", "#CC33CC", "#FF6600", "#66CCCC", 859 | "#3399FF", "#CC6666", "#999999"]; 860 | 861 | function colorPasswordField() { 862 | var secretElement = document.querySelector('#secret'); 863 | var secret = secretElement.value; 864 | var color; 865 | if (secret.length > 8) { 866 | var h = 5381; 867 | for (var i = 0; i < secret.length; i++) { 868 | h = (((h << 5) + h) + secret.charCodeAt(i)) & 0xffffffff; 869 | } 870 | color = hashColors[h % hashColors.length]; 871 | } else { 872 | color = "black"; 873 | } 874 | secretElement.style.color = color; 875 | } 876 | 877 | 878 | document.addEventListener('DOMContentLoaded', function () { 879 | document.querySelector('#main-form').addEventListener('submit', fillPassword); 880 | document.querySelector('#show-button').addEventListener('click', generatePassword); 881 | document.querySelector('#fill-button').addEventListener('click', fillPassword); 882 | document.querySelector('#secret').addEventListener('keydown', colorPasswordField); 883 | document.querySelector('#secret').addEventListener('input', colorPasswordField); 884 | 885 | // Put website URL into box. 886 | chrome.tabs.getCurrent(function(tab) { 887 | chrome.tabs.query({active: true, windowId: chrome.windows.WINDOW_ID_CURRENT}, function(tabs) { 888 | document.querySelector('#url').value = getHostname(tabs[0].url); 889 | }); 890 | }); 891 | 892 | document.querySelector('#secret').focus(); 893 | }); 894 | --------------------------------------------------------------------------------