├── CNAME ├── LICENSE ├── README.md ├── blank ├── build.py ├── cache.manifest ├── css └── mouseware.css ├── favicon.ico ├── fusionbox.gif ├── index.html ├── js ├── crypto-sha256.js ├── jquery.min.js ├── markovchain.js ├── markovpass.js ├── mouseware.js ├── random.js └── wordlist.js ├── markov.py ├── markov_corpus ├── mountains_of_madness.txt └── pride.txt ├── mouseware.py ├── txt ├── adjective.txt ├── article.txt ├── diceware.txt ├── dirty_adjective.txt ├── dirty_diceware.txt ├── dirty_noun.txt ├── dirty_verb.txt ├── noun.txt └── verb.txt └── words.py /CNAME: -------------------------------------------------------------------------------- 1 | www.mouseware.org -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2011 Gavin Wahl, Colin Thomas-Arnold, Fusionbox. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are 4 | permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of 7 | conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 10 | of conditions and the following disclaimer in the documentation and/or other materials 11 | provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY FUSIONBOX ''AS IS'' AND ANY EXPRESS OR IMPLIED 14 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 15 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FUSIONBOX OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 17 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 18 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 21 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | The views and conclusions contained in the software and documentation are those of the 24 | authors and should not be interpreted as representing official policies, either expressed 25 | or implied, of Fusionbox. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Mouseware uses a cryptographically secure random number generator based on 2 | your mouse movements to generate secure, memorable passwords. Passwords are 3 | generated entirely in the browser, no data is ever sent over the network. The 4 | generated passphrases are similar to those generated by 5 | [Diceware](http://world.std.com/~reinhold/diceware.html) or popularized by 6 | [xkcd](http://xkcd.com/936/), with an emphasis on easy memorization. 7 | 8 | We use SHA256 to process the location and timestamp of every mousemove event. 9 | Random words are then selected from noun, adjective and verb word lists to 10 | construct a random sentence. Shannon entropy is reported to estimate password 11 | strength. To avoid a time-consuming mouse moving session on every page load, 12 | we use localStorage to store a seed and initialize our internal entropy buffer 13 | with it on the next load. 14 | 15 | To increase entropy when desired, options to replace a randomly chosen letter 16 | with a number or symbol are given. Entropy calculation takes these into 17 | account, and increases the reported entropy by the logarithm of the number of 18 | letters considered for replacement. 19 | 20 | Mouseware also provides an alternative markov chain based passphrase generator. 21 | This generator uses a markov chain to generate passphrases that have a similar 22 | structure to normal language, but which doesn't necessarily include actual 23 | English words. These passphrases should be more random for a given length than 24 | the standard mouseware passphrases, but still relatively easy to remember and 25 | to type. This generator also provides an estimated entropy based on the entropy 26 | of the series of nodes visited in the markov chain. Note however, that since 27 | the markov chain generation process makes a series of decisions which is path 28 | dependent, and where the probabilities are not uniform, there is not a simple 29 | mapping from this estimated entropy to the average guesswork required to guess 30 | a passphrase. As a result, the markov chain approach is likely to generate 31 | better passwords for a given length on average. However, if you need very 32 | strong guarantees of the strengths of all passwords, the default algorithm is a 33 | better choice. 34 | -------------------------------------------------------------------------------- /blank: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionbox/mouseware/57fcdd8d0c1a03492c742f43682744f11a6101d1/blank -------------------------------------------------------------------------------- /build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import json 4 | import fileinput 5 | import glob 6 | from os.path import splitext, basename 7 | 8 | import markov 9 | 10 | 11 | def build_wordlist(): 12 | words = {} 13 | 14 | src = "txt/*" 15 | dest = "js/wordlist.js" 16 | 17 | for file in glob.glob(src): 18 | with open(file, 'r') as f: 19 | place = splitext(basename(file))[0] 20 | # using list(set( words )) unique-ifies the words 21 | words[place] = list(set([i.strip() for i in f])) 22 | 23 | with open(dest, 'w') as f: 24 | f.write("var words = ") 25 | json.dump(words, f) 26 | f.write(";") 27 | 28 | 29 | def build_markovchain(): 30 | src = "markov_corpus/*" 31 | dest = "js/markovchain.js" 32 | 33 | with fileinput.input(files=glob.glob(src)) as f: 34 | corpus = markov.get_ngrams(f) 35 | 36 | chain = markov.PassphraseMarkovChain(corpus) 37 | 38 | with open(dest, 'w') as f: 39 | f.write("var markovChain = ") 40 | f.write(chain.to_json()) 41 | f.write(";") 42 | 43 | 44 | if __name__ == "__main__": 45 | build_wordlist() 46 | build_markovchain() 47 | -------------------------------------------------------------------------------- /cache.manifest: -------------------------------------------------------------------------------- 1 | CACHE MANIFEST 2 | # version 18 3 | js/crypto-sha256.js 4 | js/wordlist.js 5 | js/markovchain.js 6 | js/markovpass.js 7 | js/random.js 8 | favicon.ico 9 | fusionbox.gif 10 | js/jquery.min.js 11 | 12 | NETWORK: 13 | * 14 | -------------------------------------------------------------------------------- /css/mouseware.css: -------------------------------------------------------------------------------- 1 | .progress { 2 | width: 300px; 3 | height: 50px; 4 | border: 1px solid black; 5 | margin: 20px auto; 6 | border-radius: 3px; 7 | border: solid 3px #ddd; 8 | background-color: #ddd; 9 | background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.01, #fff), color-stop(1.00, #eee)); 10 | background-image: -moz-linear-gradient(center bottom, #fff 1%, #eee 100%); 11 | } 12 | .progress > div { 13 | background-color: orange; 14 | height: inherit; 15 | width: 0; 16 | } 17 | 18 | body { 19 | width: 100%; 20 | font-family: "Open Sans"; 21 | padding: 0; 22 | margin: 0; 23 | } 24 | html { 25 | padding: 0; 26 | margin: 0; 27 | } 28 | 29 | #container { 30 | text-align: center; 31 | margin: 50px auto; 32 | } 33 | 34 | .password { 35 | font-size: 1.5em; 36 | } 37 | 38 | .entropy { 39 | margin-top: 5px; 40 | color: #666; 41 | } 42 | 43 | #generate button { 44 | margin-top: 20px; 45 | color: #ffffff; 46 | cursor: pointer; 47 | font-size: 24px; 48 | font-weight: bold; 49 | font-family: "Open Sans"; 50 | margin: 5px; 51 | padding: 4px 10px 6px 10px; 52 | text-decoration: none; 53 | -moz-border-radius: 3px; 54 | -webkit-border-radius: 3px; 55 | border-radius: 3px; 56 | border: solid 1px #557766; 57 | background-color: #4BA822; 58 | background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.01, #2B8802), color-stop(1.00, #4BA822)); 59 | background-image: -moz-linear-gradient(center bottom, #2B8802 1%, #4BA822 100%); 60 | text-shadow: #333333 0px 1px 0px; 61 | letter-spacing: -1px; 62 | } 63 | #generate button:hover { 64 | background-color: #56C325; 65 | background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.01, #36a305), color-stop(1.00, #56C325)); 66 | background-image: -moz-linear-gradient(center bottom, #36a305 1%, #56C325 100%); 67 | -moz-box-shadow: 0px 1px 2px #aaaaaa; -webkit-box-shadow: 0px 1px 2px #aaaaaa; box-shadow: 0px 1px 2px #aaaaaa; 68 | } 69 | 70 | .reminder { 71 | color: grey; 72 | opacity: 0; 73 | -webkit-transition-duration: 1s; 74 | -webkit-transition-property: opacity; 75 | -moz-transition-duration: 1s; 76 | -moz-transition-property: opacity; 77 | transition-duration: 1s; 78 | transition-property: opacity; 79 | } 80 | .reminder.visible { 81 | display: block; 82 | opacity: 1; 83 | } 84 | 85 | #options { 86 | background-color: #ddd; 87 | max-width: 300px; 88 | margin: 20px auto; 89 | padding: 10px; 90 | border: 1px #ccc solid; 91 | border-radius: 4px; 92 | } 93 | #options label { 94 | display: block; 95 | text-align: left; 96 | color: #666; 97 | } 98 | 99 | .toggleOptions { 100 | margin-top: 20px; 101 | } 102 | .toggleOptions a { 103 | color: #aaa; 104 | text-decoration: underline; 105 | cursor: pointer; 106 | } 107 | #generate { 108 | margin-bottom: 100px 109 | } 110 | 111 | p { 112 | max-width: 40em; 113 | margin: 25px auto; 114 | text-align: left; 115 | color: #555; 116 | } 117 | a { 118 | color: #18c; 119 | } 120 | a:visited { 121 | color: #6e9cb6; 122 | } 123 | 124 | footer { 125 | position: fixed; 126 | backgrond-color: white; 127 | display: block; 128 | width: 100%; 129 | bottom: 0; 130 | left: 0; 131 | text-align: center; 132 | padding-bottom: 5px; 133 | } 134 | 135 | footer .code { 136 | padding-bottom: 5px; 137 | font-size: .75em; 138 | /* hidden unless on a narrow screen */ 139 | display: none; 140 | } 141 | 142 | @-webkit-keyframes flash { 143 | 50% { color: black; } 144 | } 145 | @-moz-keyframes flash { 146 | 50% { color: black; } 147 | } 148 | @keyframes flash { 149 | 50% { color: black; } 150 | } 151 | p:target { 152 | -webkit-animation: flash 1s 2; 153 | -moz-animation: flash 1s 2; 154 | } 155 | p:target sup { 156 | color: black; 157 | } 158 | .entropy a { 159 | vertical-align: super; 160 | font-size: .75em; 161 | } 162 | 163 | .forkme img { 164 | position: absolute; 165 | top: 0; 166 | right: 0; 167 | border: 0; 168 | } 169 | 170 | @media screen and (max-width: 800px) { 171 | .forkme { 172 | display: none; 173 | } 174 | footer .code { 175 | display: block; 176 | } 177 | } 178 | 179 | @media screen and (max-height: 693px) { 180 | footer { 181 | position: relative; 182 | } 183 | } 184 | 185 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionbox/mouseware/57fcdd8d0c1a03492c742f43682744f11a6101d1/favicon.ico -------------------------------------------------------------------------------- /fusionbox.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionbox/mouseware/57fcdd8d0c1a03492c742f43682744f11a6101d1/fusionbox.gif -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 13 | 14 |58 | Mouseware uses a cryptographically secure random number generator based 59 | on your mouse movements to generate secure, memorable passwords. 60 | Passwords are generated entirely in the browser, no data is ever sent 61 | over the network. The generated passphrases are similar to those 62 | generated by Diceware or 64 | popularized by xkcd, with an 65 | emphasis on easy memorization. 66 |
67 |68 | Mouseware can now optionally use the diceware word list. 69 | Enable secure diceware password 70 | generation. 71 |
72 |73 | Mouseware also provides an alternative markov chain based password 74 | generation method. This method generates passwords that provide a 75 | balance between ease of memorization and randomness by creating 76 | passphrases which feel like english words without being limited to 77 | actual english words. For a given length, the passphrases will on 78 | average be harder to guess, however this method provides weaker 79 | guarantees since the generation method is less uniform, and more 80 | difficult to analyze. 81 |
82 |83 | [1]1000 guesses/second is a worst-case web-based attack. 84 | Typically this is the only type of attack feasible against a secure 85 | website. 86 |
87 |88 | [2]100 billion guesses/second is a worst-case offline attack, 89 | when a hashed password database is stolen by someone with nontrivial 90 | technical and financial resources. 91 |
92 |