Skip to content
This repository was archived by the owner on Jul 27, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*~
*.xpi
.build
.build-mozilla
node_modules
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "content/sha512crypt"]
path = content/sha512crypt
url = git://github.com/mvo5/sha512crypt-node
27 changes: 23 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
# Password Hasher Firefox extension
# PassHash
Password Hasher Firefox extension

This is still available as a Firefox add-on, but not actively maintained.
## What good security practice demands

Please feel free to fork or email about taking over responsibility for the code.
* Strong passwords that are hard to guess.
* Different passwords at each site.
* Periodically changing existing passwords.

## Why you probably aren't practicing good security

* Strong passwords are difficult to remember.
* Juggling a multitude of passwords is a pain.
* Updating passwords compounds the memorization problem.

## How Password Hasher helps

* Strong passwords are automatically generated.
* The same master key produces different passwords at many sites.
* You can quickly upgrade passwords by "bumping" the site tag.
* You can upgrade the master key without updating all sites at once.
* It supports different length passwords.
* It supports special requirements, such as digit and punctuation characters.
* All data is saved to the browser's secure password database.
* It's extremely simple to use!

## Mozilla License
6 changes: 6 additions & 0 deletions README.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
To run the unit-tests do:
$ npm install moncha

then
$ (cd tests; make)

2 changes: 2 additions & 0 deletions REQUIREMENTS
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mocha
nodeunit
22 changes: 0 additions & 22 deletions blurb

This file was deleted.

25 changes: 21 additions & 4 deletions content/passhash-common.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ var PassHashCommon =
opts.hashWordSizeDefault = prefs.getIntPref("optHashWordSizeDefault");
if (prefs.prefHasUserValue("optShortcutKeyCode"))
opts.shortcutKeyCode = prefs.getCharPref("optShortcutKeyCode");
if (prefs.prefHasUserValue("optHashAlgorithm"))
opts.hashAlgorithm = prefs.getCharPref("optHashAlgorithm");
if (!opts.shortcutKeyCode)
{
// Set shortcut key to XUL-defined default.
Expand Down Expand Up @@ -130,6 +132,7 @@ var PassHashCommon =
opts.firstTime = true;
opts.shortcutKeyCode = "";
opts.shortcutKeyMods = "";
opts.hashAlgorithm = "sha512crypt";
return opts;
},

Expand All @@ -152,6 +155,7 @@ var PassHashCommon =
prefs.setIntPref( "optHashWordSizeDefault", opts.hashWordSizeDefault);
prefs.setCharPref("optShortcutKeyCode", opts.shortcutKeyCode);
prefs.setCharPref("optShortcutKeyMods", opts.shortcutKeyMods);
prefs.setCharPref("optHashAlgorithm", opts.hashAlgorithm);
},

loadSecureValue: function(option, name, suffix, valueDefault)
Expand Down Expand Up @@ -303,10 +307,20 @@ var PassHashCommon =
requirePunctuation,
requireMixedCase,
restrictSpecial,
restrictDigits)
{
// Start with the SHA1-encrypted master key/site tag.
var s = b64_hmac_sha1(masterKey, siteTag);
restrictDigits,
hash_algorithm)
{
// Start with the SHA-encrypted master key/site tag.
if (hash_algorithm === "sha512crypt") {
// use the native version if available
if (typeof(b64_sha512crypt_native) !== 'undefined')
var s = b64_sha512crypt_native(masterKey, siteTag);
else
var s = b64_crypt_sha512(masterKey, siteTag);
} else if (hash_algorithm === "sha512")
var s = b64_hmac_sha512(masterKey, siteTag);
else
var s = b64_hmac_sha1(masterKey, siteTag);
// Use the checksum of all characters as a pseudo-randomizing seed to
// avoid making the injected characters easy to guess. Note that it
// isn't random in the sense of not being deterministic (i.e.
Expand Down Expand Up @@ -789,3 +803,6 @@ var PassHashCommon =

//NB: Make sure not to add a comma after the last function for older IE compatibility.
}

if (typeof exports !== 'undefined')
exports.PassHashCommon = PassHashCommon;
32 changes: 30 additions & 2 deletions content/passhash-dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ var PassHash =
restrictSpecial: null,
restrictDigits: null,
hashWordSize: null,
hashAlgorithm: null,

onLoad: function()
{
Expand All @@ -64,6 +65,7 @@ var PassHash =
var ctlRestrictSpecial = document.getElementById("noSpecial");
var ctlRestrictDigits = document.getElementById("digitsOnly");
var ctlHashWordSize = document.getElementById("hashWordSize");
var ctlHashAlgorithm = document.getElementById("hashAlgorithm");

var prefs = PassHashCommon.loadOptions();
this.guessSiteTag = prefs.guessSiteTag;
Expand All @@ -78,6 +80,7 @@ var PassHash =
this.restrictSpecial = false;
this.restrictDigits = false;
this.hashWordSize = prefs.hashWordSizeDefault;
this.hashAlgorithm = prefs.hashAlgorithm;

this.onUnmask();

Expand Down Expand Up @@ -114,6 +117,15 @@ var PassHash =
ctlRestrictDigits.checked = this.restrictDigits;
this.updateCheckboxes();

var menulist = document.getElementById("hashAlgorithm");
for (var i=0;menulist.getItemAtIndex(i) !== null; i++) {
var menuitem = menulist.getItemAtIndex(i);
if (menuitem.value === this.hashAlgorithm) {
menulist.selectedItem = menuitem;
break;
}
}

var btn = document.getElementById("hashWordSize"+this.hashWordSize);
// Protect against bad saved hashWordSize value.
if (btn == null)
Expand Down Expand Up @@ -251,7 +263,8 @@ var PassHash =
this.requirePunctuation,
this.requireMixedCase,
this.restrictSpecial,
this.restrictDigits);
this.restrictDigits,
this.hashAlgorithm);
if (ctlHashWord.value != hashWordOrig)
return 3; // It was modified
return 0; // It was not modified
Expand Down Expand Up @@ -293,6 +306,13 @@ var PassHash =
this.update();
},

onHashAlgorithmChanged: function()
{
var menuitem = document.getElementById("hashAlgorithm").selectedItem;
this.hashAlgorithm = menuitem.value;
this.update();
},

updateCheckboxes: function()
{
document.getElementById("digit").disabled =
Expand Down Expand Up @@ -328,8 +348,11 @@ var PassHash =
return true;
},

parseOptionString: function(s)
parseOptionString: function(full_options)
{
var s = full_options.split("/")[0];
this.hashAlgorithm = full_options.split("/")[1] || "sha1";

this.requireDigit = (s.search(/d/i) >= 0);
this.requirePunctuation = (s.search(/p/i) >= 0);
this.requireMixedCase = (s.search(/m/i) >= 0);
Expand All @@ -355,7 +378,12 @@ var PassHash =
if (this.restrictDigits)
opts += 'g';
opts += this.hashWordSize.toString();
if (this.hashAlgorithm)
opts += "/"+this.hashAlgorithm;
return opts;
}

}

if (typeof exports !== 'undefined')
exports.PassHashDialog = PassHash;
35 changes: 35 additions & 0 deletions content/passhash-dialog.xul
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@
src="passhash-sha1.js"
/>

<script
src="passhash-sha512.js"
/>

<script
src="passhash-sha512crypt-ctypes.js"
/>

<script
src="sha512crypt/sha512.js"
/>

<script
src="sha512crypt/sha512crypt.js"
/>

<script
src="passhash-common.js"
/>
Expand Down Expand Up @@ -230,6 +246,24 @@

</groupbox>

<groupbox
id="algorithmGroup"
>
<caption
label="Hash"
/>
<menulist id="hashAlgorithm"
oncommand="PassHash.onHashAlgorithmChanged();"
>
<menupopup>
<menuitem label="Sha1" value="sha1"/>
<menuitem label="Sha512" value="sha512"/>
<menuitem label="Sha512crypt" value="sha512crypt"/>
</menupopup>
</menulist>
</groupbox>


</vbox>

<groupbox
Expand Down Expand Up @@ -361,6 +395,7 @@

</groupbox>


</hbox>

<spacer
Expand Down
8 changes: 8 additions & 0 deletions content/passhash-portable.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
<!--!content:passhash-sha1.js-->
</script>

<script language="JavaScript" type="text/javascript">
<!--!content:sha512crypt/sha512.js-->
</script>

<script language="JavaScript" type="text/javascript">
<!--!content:sha512crypt/sha512crypt.js-->
</script>

<script language="JavaScript" type="text/javascript">
<!--!content:passhash-common.js-->
</script>
Expand Down
3 changes: 3 additions & 0 deletions content/passhash-sha1.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,6 @@ function binb2b64(binarray)
}
return str;
}

if (typeof exports !== 'undefined')
exports.b64_hmac_sha1 = b64_hmac_sha1;
15 changes: 15 additions & 0 deletions content/passhash-sha512.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

b64_hmac_sha512 = require("../content/sha512crypt/sha512.js").b64_hmac_sha512;
sha512crypt = require("../content/sha512crypt/sha512crypt.js").sha512crypt;

function b64_crypt_sha512(key, data)
{
var s = sha512crypt(key, data);
var split_data = s.split("$");
return split_data[3];
}

if (typeof exports !== 'undefined') {
exports.b64_hmac_sha512 = b64_hmac_sha512;
exports.b64_crypt_sha512 = b64_crypt_sha512;
}
33 changes: 33 additions & 0 deletions content/passhash-sha512crypt-ctypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

Components.utils.import("resource://gre/modules/ctypes.jsm");

function b64_sha512crypt_native(key, salt)
{
return _native_crypt(key, "$6$"+salt);
}

function _native_crypt(js_key, js_salt)
{
// convert the inputs
var key = ctypes.char.array()(js_key);
var salt = ctypes.char.array()(js_salt);

// declare what we need
var lib = ctypes.open("libcrypt.so.1");
var native_crypt = lib.declare("crypt",
ctypes.default_abi,
ctypes.char.ptr, /* return value */
ctypes.char.ptr, /* key */
ctypes.char.ptr /* salt */
);
// call the native code
var raw_result = native_crypt(key, salt);
lib.close();

// convert the output from char* to a js string
var result = raw_result.readString();

// cut of the leading: salt + "$"
var prefix_len = js_salt.length+1
return result.substr(prefix_len, result.length - prefix_len);
}
1 change: 1 addition & 0 deletions content/sha512crypt
Submodule sha512crypt added at 8dddd1
2 changes: 1 addition & 1 deletion install.rdf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<RDF:Description RDF:about="urn:mozilla:install-manifest"
em:id="passhash@mozilla.wijjo.com"
em:name="Password Hasher"
em:version="1.1.7"
em:version="1.2.2"
em:creator="Steve Cooper"
em:description="Better security without bursting your brain"
em:homepageURL="http://wijjo.com/passhash/"
Expand Down
6 changes: 6 additions & 0 deletions tests/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

all: js

js: test*.js
nodejs ../node_modules/.bin/mocha -u tdd $?

Loading