├── logo.png ├── .gitignore ├── packaging ├── icon.ico ├── icon.icns ├── passphrases.png ├── passphrases.desktop ├── DEBIAN │ └── control ├── SPECS │ └── passphrases.spec └── windows_installer.nsi ├── src ├── images │ ├── icon.png │ ├── background-dark.png │ └── background-light.png ├── sounds │ ├── dice.ogg │ ├── success.ogg │ └── notification.ogg ├── fonts │ └── Open_Sans │ │ ├── bold.woff2 │ │ ├── italic.woff2 │ │ ├── regular.woff2 │ │ ├── opensans.css │ │ └── LICENSE.txt ├── wordlists │ ├── french-diceware.wordlist │ ├── german-diceware.wordlist │ └── securedrop.wordlist ├── package.json ├── js │ ├── about.js │ ├── tabs.js │ ├── common.js │ ├── generate.js │ └── memorize.js ├── css │ └── style.css └── index.html ├── README.md ├── package.json ├── LICENSE.md └── BUILD.md /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/logo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | dist 4 | cache 5 | .DS_Store 6 | *.swp 7 | -------------------------------------------------------------------------------- /packaging/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/packaging/icon.ico -------------------------------------------------------------------------------- /packaging/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/packaging/icon.icns -------------------------------------------------------------------------------- /src/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/src/images/icon.png -------------------------------------------------------------------------------- /src/sounds/dice.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/src/sounds/dice.ogg -------------------------------------------------------------------------------- /src/sounds/success.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/src/sounds/success.ogg -------------------------------------------------------------------------------- /packaging/passphrases.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/packaging/passphrases.png -------------------------------------------------------------------------------- /src/sounds/notification.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/src/sounds/notification.ogg -------------------------------------------------------------------------------- /src/fonts/Open_Sans/bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/src/fonts/Open_Sans/bold.woff2 -------------------------------------------------------------------------------- /src/images/background-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/src/images/background-dark.png -------------------------------------------------------------------------------- /src/fonts/Open_Sans/italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/src/fonts/Open_Sans/italic.woff2 -------------------------------------------------------------------------------- /src/fonts/Open_Sans/regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/src/fonts/Open_Sans/regular.woff2 -------------------------------------------------------------------------------- /src/images/background-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/src/images/background-light.png -------------------------------------------------------------------------------- /src/wordlists/french-diceware.wordlist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/src/wordlists/french-diceware.wordlist -------------------------------------------------------------------------------- /src/wordlists/german-diceware.wordlist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/micahflee/passphrases/HEAD/src/wordlists/german-diceware.wordlist -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Passphrases 2 | 3 | A tool that helps you generate high-entropy passphrases and memorize them using a technique called spaced repetition. 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "passphrases", 3 | "version": "0.0.0", 4 | "devDependencies": { 5 | "fs-extra": "^0.16.5", 6 | "node-webkit-builder": "^1.0.11" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packaging/passphrases.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Encoding=UTF-8 3 | Name=Passphrases 4 | Comment=Generate and memorize high-entropy passphrases 5 | Exec=/usr/bin/passphrases 6 | Terminal=false 7 | Type=Application 8 | Icon=/usr/share/pixmaps/passphrases.png 9 | Categories=Utility; 10 | -------------------------------------------------------------------------------- /packaging/DEBIAN/control: -------------------------------------------------------------------------------- 1 | Package: passphrases 2 | Version: {{version}}-1 3 | Section: base 4 | Priority: optional 5 | Architecture: {{arch}} 6 | Depends: 7 | Maintainer: Micah Lee 8 | Description: Passphrases is a tool that helps you generate high-entropy 9 | passphrases and memorize them using spaced repetition. 10 | -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Passphrases", 3 | "main": "./index.html", 4 | "description": "A tool to generate and help memorize cryptographically secure passphrases.", 5 | "window": { 6 | "title": "Passphrases", 7 | "icon": "./images/icon.png", 8 | "toolbar": false, 9 | "width": 600, 10 | "height": 300, 11 | "min_width": 600, 12 | "min_height": 300, 13 | "max_width": 600, 14 | "max_height": 300 15 | }, 16 | "version": "0.1.0", 17 | "dependencies": { 18 | "jquery": "^2.1.3", 19 | "random-js": "^1.0.4" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/fonts/Open_Sans/opensans.css: -------------------------------------------------------------------------------- 1 | /* normal */ 2 | @font-face { 3 | font-family: 'Open Sans'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: local('Open Sans'), local('OpenSans'), url(regular.woff2) format('woff2'); 7 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; 8 | } 9 | /* bold */ 10 | @font-face { 11 | font-family: 'Open Sans'; 12 | font-style: normal; 13 | font-weight: 800; 14 | src: local('Open Sans Extrabold'), local('OpenSans-Extrabold'), url(bold.woff2) format('woff2'); 15 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; 16 | } 17 | /* italic */ 18 | @font-face { 19 | font-family: 'Open Sans'; 20 | font-style: italic; 21 | font-weight: 400; 22 | src: local('Open Sans Italic'), local('OpenSans-Italic'), url(italic.woff2) format('woff2'); 23 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # Passphrases License 2 | 3 | Passphrases is released under the [MIT license](https://en.wikipedia.org/wiki/MIT_License). 4 | 5 | Copyright © 2015 Micah Lee 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a 8 | copy of this software and associated documentation files (the 9 | "Software"), to deal in the Software without restriction, including 10 | without limitation the rights to use, copy, modify, merge, publish, 11 | distribute, sublicense, and/or sell copies of the Software, and to 12 | permit persons to whom the Software is furnished to do so, subject to 13 | the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included 16 | in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /packaging/SPECS/passphrases.spec: -------------------------------------------------------------------------------- 1 | Name: passphrases 2 | Version: {{version}} 3 | Release: 1%{?dist} 4 | Summary: Passphrases is a tool that helps you generate high-entropy passphrases and memorize them using spaced repition. 5 | 6 | Group: Applications/Productivity 7 | License: MIT 8 | URL: https://github.com/micahflee/passphrases 9 | Source0: %{name}-%{version}.tar.gz 10 | 11 | #BuildRequires: nodejs 12 | #Requires: nodejs 13 | 14 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root 15 | 16 | 17 | %description 18 | Passphrases is a tool that helps you generate high-entropy passphrases and memorize them using spaced repition. 19 | 20 | 21 | %prep 22 | %setup -q 23 | 24 | 25 | %build 26 | # empty 27 | 28 | 29 | %install 30 | rm -rf %{buildroot} 31 | mkdir -p %{buildroot} 32 | 33 | # in builddir 34 | cp -a * %{buildroot} 35 | 36 | 37 | %clean 38 | rm -rf %{buildroot} 39 | 40 | 41 | %files 42 | %defattr(-,root,root,-) 43 | /opt/Passphrases/Passphrases 44 | /opt/Passphrases/icudtl.dat 45 | /opt/Passphrases/libffmpegsumo.so 46 | /opt/Passphrases/nw.pak 47 | /usr/bin/passphrases 48 | /usr/share/applications/passphrases.desktop 49 | /usr/share/pixmaps/passphrases.png 50 | 51 | 52 | %changelog 53 | * Sun Mar 15 2015 Micah Lee 0.1.0 54 | - First build 55 | 56 | -------------------------------------------------------------------------------- /src/js/about.js: -------------------------------------------------------------------------------- 1 | /* Passphrases | https://github.com/micahflee/passphrases 2 | Copyright (C) 2015 Micah Lee 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a 5 | copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included 13 | in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | var $ = require('jquery'); 25 | 26 | $(function(){ 27 | // check the box if sound is enabled 28 | $('.enable-sound').prop('checked', Passphrases.prefs['sound']); 29 | 30 | // toggling sound updates settings 31 | $('.enable-sound').change(function(){ 32 | Passphrases.prefs['sound'] = $(this).prop('checked'); 33 | Passphrases.savePrefs(); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /BUILD.md: -------------------------------------------------------------------------------- 1 | # Build Instructions 2 | 3 | Install [node.js](https://nodejs.org/) and [npm](https://www.npmjs.com/) for your operating system. 4 | 5 | Grab a copy of the source code and install the dependencies: 6 | 7 | ```sh 8 | git clone https://github.com/micahflee/passphrases.git 9 | cd passphrases 10 | npm install 11 | cd src 12 | npm install 13 | cd .. 14 | ``` 15 | 16 | To run the app while developing: 17 | 18 | ```sh 19 | node_modules/.bin/nwbuild -r src 20 | ``` 21 | 22 | To build binaries for the current platform: 23 | 24 | ```sh 25 | node build.js 26 | ``` 27 | 28 | ## Packaging 29 | 30 | If you'd like to completely package Passphrases, including codesigning and building an installer, use the `--package` argument: 31 | 32 | ```sh 33 | node build.js --package 34 | ``` 35 | 36 | Here are platform-specific notes about packaging. 37 | 38 | ### Linux 39 | 40 | At the moment there's no simple way to build a Debian source package and compile it into a binary package. Running `node build.js --package` in Linux at the moment is sort of hacky, but ends up creating binary-only packages (that install to /opt) that can be installed in Debian, Ubuntu, Tails, etc. See [#1](https://github.com/micahflee/passphrases/issues/1) for more information. 41 | 42 | ### Mac OS X 43 | 44 | TODO: Finish OSX packaging. 45 | 46 | ### Windows 47 | 48 | Running `node build.js --package` in Windows does a couple of things. First, it uses nw.js to create a folder that includes `Passphrases.exe`. It also builds an installer, `Passphrases_Setup.exe`, which includes an uninstaller, `uninstall.exe`. It uses Authenticode to codesign all three of these binaries. 49 | 50 | To get started: 51 | 52 | * Go to http://nsis.sourceforge.net/Download and download the latest NSIS. I downloaded nsis-3.0b0-setup.exe. 53 | * Go to http://msdn.microsoft.com/en-us/vstudio/aa496123 and install the latest .NET Framework. I installed .NET Framework 4.5.1. 54 | * Go to http://www.microsoft.com/en-us/download/confirmation.aspx?id=8279 and install the Windows SDK. 55 | * Right click on Computer, go to Properties. Click "Advanced system settings". Click Environment Variables. Under "System variables" double-click on Path to edit it. Add `;C:\Program Files (x86)\NSIS;C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin`. 56 | 57 | You'll also, of course, need a code signing certificate. I roughly followed [this guide](http://blog.assarbad.net/20110513/startssl-code-signing-certificate/) to make one using my StartSSL account. Once you get a code signing key and certificate and covert it to a pfx file, import it into your certificate store. 58 | 59 | -------------------------------------------------------------------------------- /src/js/tabs.js: -------------------------------------------------------------------------------- 1 | /* Passphrases | https://github.com/micahflee/passphrases 2 | Copyright (C) 2015 Micah Lee 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a 5 | copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included 13 | in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | var $ = require('jquery'); 25 | 26 | $(function(){ 27 | // tab functions 28 | function activateGenerate() { 29 | $('.tab-generate').addClass('active'); 30 | $('.content-generate').addClass('active'); 31 | } 32 | function deactivateGenerate() { 33 | $('.tab-generate').removeClass('active'); 34 | $('.content-generate').removeClass('active'); 35 | } 36 | function activateMemorize() { 37 | $('.tab-memorize').addClass('active'); 38 | $('.content-memorize').addClass('active'); 39 | } 40 | function deactivateMemorize() { 41 | $('.tab-memorize').removeClass('active'); 42 | $('.content-memorize').removeClass('active'); 43 | } 44 | function activateAbout() { 45 | $('.tab-about').addClass('active'); 46 | $('.content-about').addClass('active'); 47 | } 48 | function deactivateAbout() { 49 | $('.tab-about').removeClass('active'); 50 | $('.content-about').removeClass('active'); 51 | } 52 | 53 | function clickGenerateTab() { 54 | if(!$('.tab-generate').hasClass('active')) { 55 | activateGenerate(); 56 | deactivateMemorize(); 57 | deactivateAbout(); 58 | }; 59 | } 60 | $('.tab-generate').click(clickGenerateTab); 61 | 62 | function clickMemorizeTab() { 63 | if(!$('.tab-memorize').hasClass('active')) { 64 | activateMemorize(); 65 | deactivateGenerate(); 66 | deactivateAbout(); 67 | 68 | if($('.memorize-input').is(':visible')) { 69 | $('.passphrase-to-memorize').focus(); 70 | } else { 71 | $('.passphrase-test').focus(); 72 | } 73 | }; 74 | } 75 | $('.tab-memorize').click(clickMemorizeTab); 76 | 77 | function clickAboutTab() { 78 | if(!$('.tab-about').hasClass('active')) { 79 | activateAbout(); 80 | deactivateGenerate(); 81 | deactivateMemorize(); 82 | }; 83 | } 84 | $('.tab-about').click(clickAboutTab); 85 | 86 | $('.navigation .tab').hover(function(){ 87 | $(this).addClass('hover'); 88 | }, function(){ 89 | $(this).removeClass('hover'); 90 | }); 91 | 92 | // let the outside world switch to memorize tab 93 | Passphrases.tabMemorize = function(){ 94 | clickMemorizeTab(); 95 | }; 96 | 97 | // start with generate 98 | clickGenerateTab(); 99 | }); 100 | -------------------------------------------------------------------------------- /src/js/common.js: -------------------------------------------------------------------------------- 1 | /* Passphrases | https://github.com/micahflee/passphrases 2 | Copyright (C) 2015 Micah Lee 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a 5 | copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included 13 | in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | var fs = require('fs'); 25 | var $ = require('jquery'); 26 | 27 | var gui = require('nw.gui'); 28 | var win = gui.Window.get(); 29 | 30 | // make shortcut keys like Cmd-Q work in OSX (#4) 31 | if(process.platform === 'darwin') { 32 | var nativeMenuBar = new gui.Menu({ type: "menubar" }); 33 | nativeMenuBar.createMacBuiltin("Passphrases", { 34 | hideEdit: true, 35 | hideWindow: true 36 | }); 37 | win.menu = nativeMenuBar; 38 | } 39 | 40 | Passphrases = {}; 41 | 42 | // load sound effects 43 | var soundEffects = { 44 | 'generate': new Audio("sounds/dice.ogg"), 45 | 'success': new Audio("sounds/success.ogg"), 46 | 'notification': new Audio("sounds/notification.ogg"), 47 | }; 48 | Passphrases.playSound = function(sound) { 49 | if(Passphrases.prefs['sound']) { 50 | soundEffects[sound].play(); 51 | } 52 | } 53 | 54 | // notifications 55 | Passphrases.notify = function(message) { 56 | var options = { 57 | icon: 'images/icon.png', 58 | body: message 59 | }; 60 | 61 | var notification = new Notification("Passphrases", options); 62 | notification.onclick = function () { 63 | win.focus(); 64 | } 65 | notification.onshow = function () { 66 | // auto close after 3 seconds 67 | setTimeout(function() {notification.close();}, 3000); 68 | } 69 | } 70 | 71 | // define default preferences 72 | Passphrases.prefs = { 73 | sound: true, 74 | wordlist: "securedrop", 75 | words: 7 76 | }; 77 | 78 | function getPrefsDirname() { 79 | var dirname; 80 | if(process.platform == 'linux') { 81 | dirname = process.env.HOME + '/.config/PassphrasesApp' 82 | } else if(process.platform == 'darwin') { 83 | dirname = process.env.HOME + '/Library/Application Support/PassphrasesApp' 84 | } else if(process.platform == 'win32') { 85 | dirname = process.env.APPDATA + '\\\\PassphrasesApp' 86 | } 87 | return dirname; 88 | } 89 | function getPrefsFilename() { 90 | if(process.platform == 'win32') { 91 | return getPrefsDirname() + '\\\\passphrases.conf'; 92 | } else { 93 | return getPrefsDirname() + '/passphrases.conf'; 94 | } 95 | } 96 | 97 | function loadPrefs(callback) { 98 | try { 99 | data = fs.readFileSync(getPrefsFilename(), { encoding: 'utf8' }); 100 | Passphrases.prefs = JSON.parse(data); 101 | callback(); 102 | } catch(e) { 103 | Passphrases.savePrefs(callback); 104 | } 105 | } 106 | Passphrases.savePrefs = function(callback) { 107 | // create the prefs dir, if it's not already created 108 | try { 109 | fs.mkdirSync(getPrefsDirname()); 110 | } catch(e) {} 111 | 112 | // save preferences 113 | fs.writeFile(getPrefsFilename(), JSON.stringify(Passphrases.prefs), function(err){ 114 | if(callback) callback(err); 115 | }) 116 | } 117 | loadPrefs(); 118 | 119 | $(function(){ 120 | // make all links open in external browser 121 | $('a').each(function(){ 122 | var url = $(this).attr('href'); 123 | $(this).click(function(){ 124 | gui.Shell.openExternal(url); 125 | return false; 126 | }); 127 | }); 128 | }); 129 | -------------------------------------------------------------------------------- /src/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-image: url('../images/background-light.png'); 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | a { 8 | color: #cc0000; 9 | text-decoration: none; 10 | } 11 | 12 | .wrapper { 13 | color: #000000; 14 | font-family: 'Open Sans', sans-serif; 15 | max-width: 600px; 16 | margin: 0 auto; 17 | } 18 | 19 | .navigation { 20 | display: block; 21 | width: 100%; 22 | list-style: none; 23 | margin: 0; 24 | padding: 0; 25 | background-image: url('../images/background-dark.png'); 26 | text-align: center; 27 | } 28 | .navigation .tab { 29 | display: inline-block; 30 | list-style: none; 31 | padding: 10px 20px; 32 | margin: 0; 33 | text-decoration: none; 34 | cursor: pointer; 35 | font-weight: bold; 36 | color: #cccccc; 37 | font-size: 15px; 38 | } 39 | .navigation .tab.hover { 40 | color: #ffffff; 41 | text-shadow: 0 0 3px #cccccc; 42 | } 43 | .navigation .tab.active { 44 | color: #333333; 45 | background-image: url('../images/background-light.png'); 46 | cursor: auto; 47 | } 48 | .content-wrapper { 49 | padding: 10px 20px; 50 | } 51 | .content { 52 | display: none; 53 | } 54 | .content.active { 55 | display: block; 56 | } 57 | 58 | .generate-top { 59 | text-align: center; 60 | vertical-align: middle; 61 | } 62 | .generate-options { 63 | display: inline-block; 64 | text-align: left; 65 | width: 160px; 66 | vertical-align: top; 67 | padding: 20px 0; 68 | } 69 | .wordlist-description { 70 | display: inline-block; 71 | text-align: left; 72 | color: #666666; 73 | font-size: 12px; 74 | width: 380px; 75 | vertical-align: top; 76 | } 77 | 78 | .passphrase-wrapper { 79 | margin: 10px 0; 80 | background-color: #ffffff; 81 | padding: 5px; 82 | border: 1px solid #999999; 83 | height: 70px; 84 | } 85 | .passphrase { 86 | text-align: center; 87 | font-size: 25px; 88 | font-weight: bold; 89 | position: relative; 90 | top: 50%; 91 | transform: translateY(-50%); 92 | } 93 | 94 | .memorize-input { 95 | text-align: center; 96 | font-size: 20px; 97 | } 98 | .memorize-stats { 99 | text-align: center; 100 | margin-bottom: 20px; 101 | } 102 | .memorize-stat, .memorize-note { 103 | display: inline-block; 104 | margin: 0 20px; 105 | } 106 | .memorize-tries { 107 | font-weight: bold; 108 | color: #009900; 109 | } 110 | 111 | .passphrase-to-memorize, .passphrase-test { 112 | font-size: 20px; 113 | font-family: 'Open Sans', sans-serif; 114 | font-weight: bold; 115 | padding: 15px; 116 | width: 500px; 117 | background-color: #ffffff; 118 | } 119 | .typo { 120 | background-color: #ffcccc; 121 | } 122 | 123 | .memorize-go { 124 | text-align: center; 125 | } 126 | .hint { 127 | height: 20px; 128 | } 129 | .hint-progress-wrapper { 130 | width: 100%; 131 | height: 20px; 132 | background-color: #666666; 133 | border: 2px solid #666666; 134 | } 135 | .hint-progress { 136 | width: 0%; 137 | height: 20px; 138 | background-color: #66ff66; 139 | } 140 | .hint-show { 141 | position: relative; 142 | top: 50%; 143 | transform: translateY(-50%); 144 | font-weight: bold; 145 | font-size: 15px; 146 | color: #000000; 147 | text-align: center; 148 | } 149 | 150 | .memorize-warning { 151 | font-size: 14px; 152 | color: #666666; 153 | } 154 | .memorize-go .cancel-wrapper { 155 | float: right; 156 | } 157 | 158 | .countdown { 159 | text-align: center; 160 | font-size: 40px; 161 | font-weight: bold; 162 | } 163 | 164 | .memorize-ready { 165 | text-align: center; 166 | font-size: 30px; 167 | font-weight: bold; 168 | padding: 15px 0; 169 | } 170 | 171 | .about-license { 172 | font-family: sans-serif; 173 | font-style: italic; 174 | font-size: 13px; 175 | color: #666666; 176 | margin-top: 90px; 177 | text-align: center; 178 | } 179 | 180 | .buttons { 181 | text-align: center; 182 | } 183 | .btn { 184 | display: inline-block; 185 | cursor: pointer; 186 | margin: 5px 10px; 187 | background: #3498db; 188 | background-image: -webkit-linear-gradient(top, #3498db, #2980b9); 189 | background-image: -moz-linear-gradient(top, #3498db, #2980b9); 190 | background-image: -ms-linear-gradient(top, #3498db, #2980b9); 191 | background-image: -o-linear-gradient(top, #3498db, #2980b9); 192 | background-image: linear-gradient(to bottom, #3498db, #2980b9); 193 | -webkit-border-radius: 10; 194 | -moz-border-radius: 10; 195 | border-radius: 10px; 196 | text-shadow: 1px 1px 3px #666666; 197 | font-weight: bold; 198 | color: #ffffff; 199 | font-size: 14px; 200 | padding: 5px 10px 5px 10px; 201 | text-decoration: none; 202 | } 203 | .btn:hover { 204 | background: #3cb0fd; 205 | background-image: -webkit-linear-gradient(top, #3cb0fd, #3498db); 206 | background-image: -moz-linear-gradient(top, #3cb0fd, #3498db); 207 | background-image: -ms-linear-gradient(top, #3cb0fd, #3498db); 208 | background-image: -o-linear-gradient(top, #3cb0fd, #3498db); 209 | background-image: linear-gradient(to bottom, #3cb0fd, #3498db); 210 | text-decoration: none; 211 | } 212 | -------------------------------------------------------------------------------- /packaging/windows_installer.nsi: -------------------------------------------------------------------------------- 1 | !define APPNAME "Passphrases" 2 | !define BINPATH "..\dist\Passphrases" 3 | !define ABOUTURL "https://github.com/micahflee/passphrases" 4 | 5 | # change these with each release 6 | !define INSTALLSIZE 67845 7 | !define VERSIONMAJOR 0 8 | !define VERSIONMINOR 7 9 | !define VERSIONSTRING "0.1.0" 10 | 11 | RequestExecutionLevel admin 12 | 13 | Name "Passphrases" 14 | InstallDir "$PROGRAMFILES\${APPNAME}" 15 | Icon "icon.ico" 16 | 17 | !include LogicLib.nsh 18 | 19 | Page directory 20 | Page instfiles 21 | 22 | !macro VerifyUserIsAdmin 23 | UserInfo::GetAccountType 24 | pop $0 25 | ${If} $0 != "admin" ;Require admin rights on NT4+ 26 | messageBox mb_iconstop "Administrator rights required!" 27 | setErrorLevel 740 ;ERROR_ELEVATION_REQUIRED 28 | quit 29 | ${EndIf} 30 | !macroend 31 | 32 | # in order to codesign uninstall.exe, we need to do some hacky stuff outlined 33 | # here: http://nsis.sourceforge.net/Signing_an_Uninstaller 34 | !ifdef INNER 35 | !echo "Creating uninstall.exe" 36 | OutFile "$%TEMP%\tempinstaller.exe" 37 | SetCompress off 38 | !else 39 | !echo "Creating normal installer" 40 | !system "$\"${NSISDIR}\makensis$\" /DINNER windows_installer.nsi" = 0 41 | !system "$%TEMP%\tempinstaller.exe" = 2 42 | !system "signtool.exe sign /v /d $\"Uninstall Passphrases$\" /a /tr http://www.startssl.com/timestamp $%TEMP%\uninstall.exe" = 0 43 | 44 | # all done, now we can build the real installer 45 | OutFile "..\dist\Passphrases_Setup.exe" 46 | SetCompressor /FINAL /SOLID lzma 47 | !endif 48 | 49 | Function .onInit 50 | !ifdef INNER 51 | WriteUninstaller "$%TEMP%\uninstall.exe" 52 | Quit # bail out early 53 | !endif 54 | 55 | setShellVarContext all 56 | !insertmacro VerifyUserIsAdmin 57 | FunctionEnd 58 | 59 | Section "install" 60 | # application 61 | SetOutPath "$INSTDIR" 62 | File "icon.ico" 63 | File "${BINPATH}\ffmpegsumo.dll" 64 | File "${BINPATH}\icudtl.dat" 65 | File "${BINPATH}\libEGL.dll" 66 | File "${BINPATH}\libGLESv2.dll" 67 | File "${BINPATH}\nw.pak" 68 | File "${BINPATH}\Passphrases.exe" 69 | File "${BINPATH}\LICENSE.md" 70 | 71 | # uninstaller 72 | !ifndef INNER 73 | SetOutPath $INSTDIR 74 | File $%TEMP%\uninstall.exe 75 | !endif 76 | 77 | # start menu 78 | CreateShortCut "$SMPROGRAMS\${APPNAME}.lnk" "$INSTDIR\Passphrases.exe" "" "$INSTDIR\icon.ico" 79 | 80 | # registry information for add/remove programs 81 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}" 82 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" 83 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" 84 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "InstallLocation" "$\"$INSTDIR$\"" 85 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayIcon" "$\"$INSTDIR\icon.ico$\"" 86 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "URLInfoAbout" "$\"${ABOUTURL}$\"" 87 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayVersion" ${VERSIONSTRING} 88 | WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "VersionMajor" ${VERSIONMAJOR} 89 | WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "VersionMinor" ${VERSIONMINOR} 90 | # there is no option for modifying or repairing the install 91 | WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "NoModify" 1 92 | WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "NoRepair" 1 93 | # set the INSTALLSIZE constant (!defined at the top of this script) so Add/Remove Programs can accurately report the size 94 | WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "EstimatedSize" ${INSTALLSIZE} 95 | SectionEnd 96 | 97 | # uninstaller 98 | Function un.onInit 99 | SetShellVarContext all 100 | 101 | #Verify the uninstaller - last chance to back out 102 | MessageBox MB_OKCANCEL "Uninstall ${APPNAME}?" IDOK next 103 | Abort 104 | next: 105 | !insertmacro VerifyUserIsAdmin 106 | FunctionEnd 107 | 108 | !ifdef INNER 109 | Section "uninstall" 110 | Delete "$SMPROGRAMS\${APPNAME}.lnk" 111 | 112 | # remove files 113 | Delete "$INSTDIR\icon.ico" 114 | Delete "$INSTDIR\ffmpegsumo.dll" 115 | Delete "$INSTDIR\icudtl.dat" 116 | Delete "$INSTDIR\libEGL.dll" 117 | Delete "$INSTDIR\libGLESv2.dll" 118 | Delete "$INSTDIR\nw.pak" 119 | Delete "$INSTDIR\Passphrases.exe" 120 | Delete "$INSTDIR\LICENSE.md" 121 | Delete "$INSTDIR\uninstall.exe" 122 | 123 | rmDir "$INSTDIR" 124 | 125 | # remove uninstaller information from the registry 126 | DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" 127 | SectionEnd 128 | !endif -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 26 | 27 | 28 | Passphrases 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 | 42 | 45 | 46 | 47 |
48 | 49 | 50 |
51 |
52 |
53 |
54 | 55 |

56 |
57 | 58 |
59 |
60 |
61 | 62 |
63 |
Generate
64 |
Memorize
65 |
66 |
67 | 68 | 69 |
70 |
71 |

Type in passphrase to start memorizing:

72 |

73 |

74 | 75 |
76 |

77 |
78 |
Start Memorizing
79 |
80 |
81 | 82 |
83 |
84 |
85 |
Tries:
86 |
87 | 88 |
89 |
90 |
91 |
92 |
93 | 94 |

95 | 96 |

97 |
98 | 99 |
100 |

You'll get notified when it's time to try again.

101 | 102 |
103 | 104 |
105 |
Skip Countdown
106 |
107 |
108 | 109 |
110 |

Press space when you are ready

111 |
112 | 113 |
114 |
Cancel
115 |
116 | 117 |

If you haven't memorized your passphrase, don't close this window without writing it down first. This program won't save it for you.

118 |
119 |
120 | 121 | 122 |
123 |

Passphrases is a tool that helps you generate high-entropy passphrases and memorize them using a technique called spaced repetition.

124 | 125 |
126 | 127 |
128 | 129 |

130 | Passphrases is open source software, released under the MIT license | source code
131 | Passphrases does not collect any information or do anything over the Internet 132 |

133 |
134 |
135 |
136 | 137 | 138 | -------------------------------------------------------------------------------- /src/js/generate.js: -------------------------------------------------------------------------------- 1 | /* Passphrases | https://github.com/micahflee/passphrases 2 | Copyright (C) 2015 Micah Lee 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a 5 | copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included 13 | in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | var $ = require('jquery'), 25 | Random = require('random-js'), 26 | fs = require('fs'); 27 | 28 | $(function(){ 29 | // load the wordlists 30 | var wordlists = { 31 | 'securedrop': { 32 | 'name': 'SecureDrop', 33 | 'description': 'English wordlist from the SecureDrop project' 34 | }, 35 | 'english-diceware': { 36 | 'name': 'English Diceware', 37 | 'description': 'Original English Diceware wordlist' 38 | }, 39 | 'catalan-diceware': { 40 | 'name': 'Catalan Diceware', 41 | 'description': 'Diccionari català per Marcel Hernandez - CC-BY 4.0' 42 | }, 43 | 'german-diceware': { 44 | 'name': 'Deutsch Diceware', 45 | 'description': 'Deutsch Wörterbuch, von Benjamin Tenne - GPL' 46 | }, 47 | 'french-diceware': { 48 | 'name': 'Français Diceware', 49 | 'description': 'Dictionnaire français par Matthieu Weber' 50 | }, 51 | 'italian-diceware': { 52 | 'name': 'Italiano Diceware', 53 | 'description': 'Lista di parole Diceware in Italiano by Tarin Gamberini - GPL' 54 | }, 55 | 'japanese-diceware': { 56 | 'name': 'Japanese Diceware', 57 | 'description': 'Japanese Diceware by Hiroshi Yuki & J Greely - CC-BY-SA' 58 | }, 59 | 'dutch-diceware': { 60 | 'name': 'Dutch Diceware', 61 | 'description': 'Nederlands woordenboek door Bart Van den Eynde - GPL' 62 | }, 63 | 'polish-diceware': { 64 | 'name': 'Polski Diceware', 65 | 'description': 'Polski Słownik przez Piotr (DrFugazi) Tarnowski' 66 | }, 67 | 'swedish-diceware': { 68 | 'name': 'Svensk Diceware', 69 | 'description': 'Svensk ordbok av Magnus Bodin' 70 | }, 71 | }; 72 | 73 | var wordlistCount = 0; 74 | $.each(wordlists, function(wordlist){ wordlistCount++; }); 75 | 76 | function populateWordlistsDropdown() { 77 | $.each(wordlists, function(wordlist){ 78 | var $option = $('