Author Topic: Patch against 1.6.2 to implement hash on disk  (Read 14148 times)

John Lenz

  • Guest
Patch against 1.6.2 to implement hash on disk
« on: June 14, 2007, 12:38:23 AM »
Here is a patch I developed to store a hash of the master password on disk, and then display if the current password matches.   (One of the things on the feature request list...)

 Only visable in advanced options, but if the hash is stored when prompting for the password on the cool key, it won't accept a bad password.  The advanced options accepts "bad" passwords, just displays a message about not matching the hash on disk and allows you to overwrite the value.


Looks like the forum is murdering the patch... send me an email and I can send the patch somewhere else.

Code: [Select]
Index: passwordmaker/chrome/content/passwdmaker/advanced-options.xul
===================================================================
--- passwordmaker.orig/chrome/content/passwdmaker/advanced-options.xul 2007-06-13 16:55:07.000000000 -0500
+++ passwordmaker/chrome/content/passwdmaker/advanced-options.xul 2007-06-13 18:06:20.000000000 -0500
@@ -131,6 +131,11 @@
   accesskey="N"   

   tooltip="Download settings now"

   oncommand="onUpdownload('download', true);"/>           

+

+<command id="setHashedMasterPassword"

+  label="Set Hashed Master Password"

+  tooltip="Store Hashed Master Password to disk"

+  oncommand="onSetHashedMasterPassword();"/>

   

 <keyset>

   <key id="esc-key" keycode="VK_ESCAPE" command="closeCmd"/>

@@ -280,7 +285,13 @@
           <row observes="isFolderCmd" align="center">

             <hbox align="center"><button command="clipboardCopyCmd"/></hbox>

             <hbox align="center"><button command="closeCmd"/></hbox>         

-          </row>         

+          </row>

+          <row observes="isFolderCmd" align="center"> <hbox align="center">

+               <label id="passwordMatches" tooltip="" />

+          </hbox></row>

+          <row observes="isFolderCmd" align="center"> <hbox align="center">

+               <button command="setHashedMasterPassword"/>

+          </hbox></row>

         </rows>

       </grid>

     </hbox>

Index: passwordmaker/chrome/content/passwdmaker/mpw.js
===================================================================
--- passwordmaker.orig/chrome/content/passwdmaker/mpw.js 2007-06-13 16:32:11.000000000 -0500
+++ passwordmaker/chrome/content/passwdmaker/mpw.js 2007-06-13 18:19:02.000000000 -0500
@@ -83,6 +83,19 @@
     }

   },

 

+  calculateMasterPasswordHash : function (clearTextMasterPassword, salt) {

+    var hash = PasswordMaker_SHA256.rstr_sha256(clearTextMasterPassword, salt);

+    return PasswordMaker_HashUtils.rstr2any(hash, passwordMaker.DEFAULT_CHARSET);

+  },

+

+  storeMasterPasswordHashedVal : function(clearTextMasterPassword) {

+    var salt = this._makeKey32();

+    PwdMkr_RDFUtils.updateTarget(passwordMaker.globalSettingsSubjectRes, passwordMaker.masterPasswordSaltRes, salt);

+   

+    var hashed = this.calculateMasterPasswordHash(clearTextMasterPassword, salt);

+    PwdMkr_RDFUtils.updateTarget(passwordMaker.globalSettingsSubjectRes, passwordMaker.masterPasswordHashedRes, hashed);

+  },

+

   encrypt : function(clearText) {

     if (clearText == null || clearText == "")

       return null;

@@ -101,9 +114,13 @@
     var params = {inn:{passwordStorageLBValue:

                        PwdMkr_RDFUtils.getTarget(passwordMaker.globalSettingsSubjectRes, passwordMaker.masterPasswordStoragePredicateRes),

                        passwordMaker:passwordMaker,

-                       settings:passwordMaker.readAccountSettings(subjectRes)},

+                       settings:passwordMaker.readAccountSettings(subjectRes),

+                       salt:PwdMkr_RDFUtils.getTarget(passwordMaker.globalSettingsSubjectRes, passwordMaker.masterPasswordSaltRes),

+                       hashed:PwdMkr_RDFUtils.getTarget(passwordMaker.globalSettingsSubjectRes, passwordMaker.masterPasswordHashedRes),

+                       hashFunction:this.calculateMasterPasswordHash,

+                      },

                   out:null};

-

+

     // Return null or a decrypted password

     window.openDialog("chrome://passwdmaker/chrome/passwordprompt.xul",

      "", "chrome, dialog, modal, resizable=yes", params).focus();

@@ -114,4 +131,4 @@
     }

     return null;

   }

-};
\ No newline at end of file
+};

Index: passwordmaker/chrome/content/passwdmaker/passwdmaker.js
===================================================================
--- passwordmaker.orig/chrome/content/passwdmaker/passwdmaker.js 2007-06-13 16:30:05.000000000 -0500
+++ passwordmaker/chrome/content/passwdmaker/passwdmaker.js 2007-06-13 16:49:17.000000000 -0500
@@ -46,6 +46,8 @@
   masterPasswordPredicateRes : null, //http://passwordmaker.mozdev.org/rdf#masterPassword

   masterPasswordKeyPredicateRes : null,

   masterPasswordStoragePredicateRes : null,

+  masterPasswordSaltRes : null,

+  masterPasswordHashedRes : null,

   maskMasterPasswordPredicateRes : null,

   autoClearClipboardPredicateRes : null,

   autoClearClipboardSecondsPredicateRes : null,

@@ -129,6 +131,8 @@
     this.masterPasswordPredicateRes = PwdMkr_RDFUtils.makePredicate("masterPassword");

     this.masterPasswordKeyPredicateRes = PwdMkr_RDFUtils.makePredicate("masterPasswordKey");

     this.masterPasswordStoragePredicateRes = PwdMkr_RDFUtils.makePredicate("masterPasswordStorage");

+    this.masterPasswordSaltRes = PwdMkr_RDFUtils.makePredicate("masterPasswordSalt");

+    this.masterPasswordHashedRes = PwdMkr_RDFUtils.makePredicate("masterPasswordHashed");

     this.maskMasterPasswordPredicateRes = PwdMkr_RDFUtils.makePredicate("maskMasterPassword");

     this.autoClearClipboardPredicateRes = PwdMkr_RDFUtils.makePredicate("autoClearClipboard");

     this.autoClearClipboardSecondsPredicateRes = PwdMkr_RDFUtils.makePredicate("autoClearClipboardSeconds");

@@ -1372,4 +1376,4 @@
   isUsingPFF : function() {

     return PasswordMakerPrefsWrapper.getChar("settings") == this.PFF;

   } 

-};
\ No newline at end of file
+};

Index: passwordmaker/chrome/content/passwdmaker/passwdmakerOverlay.js
===================================================================
--- passwordmaker.orig/chrome/content/passwdmaker/passwdmakerOverlay.js 2007-06-13 17:50:37.000000000 -0500
+++ passwordmaker/chrome/content/passwdmaker/passwdmakerOverlay.js 2007-06-13 18:05:03.000000000 -0500
@@ -20,7 +20,7 @@
 **/

 

 // References to the UI elements

-var passwordMaster, passwordMaster2, passwordGenerated, passwordStorageLB, passwordMaker,

+var passwordMaster, passwordMaster2, passwordGenerated, passwordStorageLB, passwordMaker, passwordMatches,

   createTreeFolderBtn, newAccountCmd, usingURL, confirmMPWCB;

 

 var NONE_CLICK_ACCOUNT_SETTINGS="[none - click account settings to set]";

@@ -39,6 +39,7 @@
   passwordMaster = document.getElementById("passwordMaster");

   passwordMaster2 = document.getElementById("passwordMaster2");

   passwordGenerated = document.getElementById("passwordGenerated");

+  passwordMatches = document.getElementById("passwordMatches");

   passwordStorageLB = document.getElementById("passwordStorageLB");

   createTreeFolderBtn = document.getElementById("createTreeFolderBtn");

   newAccountCmd = document.getElementById("newAccountCmd");

@@ -163,6 +164,7 @@
 }

 

 function generatepassword() {

+  passwordMatches.value = "";

   if (passwordMaster.value == "") {

     passwordGenerated.value = passwordMaker.ENTER_MPW;

     return;

@@ -184,6 +186,28 @@
     cells[13].getAttribute("label"), // charset

     cells[14].getAttribute("label"), // prefix

     cells[15].getAttribute("label")); // suffix

+

+  if (passwordMatches) {

+    var salt = PwdMkr_RDFUtils.getTarget(passwordMaker.globalSettingsSubjectRes, passwordMaker.masterPasswordSaltRes);

+    var hash = PwdMkr_RDFUtils.getTarget(passwordMaker.globalSettingsSubjectRes, passwordMaker.masterPasswordHashedRes);

+    var newHash = PwdMkr_MPW.calculateMasterPasswordHash(passwordMaster.value, salt);

+

+    if (hash) {

+       if (hash == newHash) {

+         passwordMatches.value = "Master Password matches stored hash value";

+       } else {

+         passwordMatches.value = "Master Password does not match stored hash.";

+       }

+    } else {

+      passwordMatches.value = "Master Password hash is not stored on disk."

+    }

+  }

+}

+

+function onSetHashedMasterPassword() {

+  if (passwordMaster.value == passwordMaster2.value) {

+    PwdMkr_MPW.storeMasterPasswordHashedVal(passwordMaster.value);

+  }

 }

 

 function importSettings() {

@@ -336,4 +360,4 @@
   passwordStorageLB.value = previousPasswordStorageLBValue = passwordMaker._getLiteral(passwordMaker.globalSettingsSubjectRes, passwordMaker.masterPasswordStoragePredicateRes);

   _update(quiet);

   generatepassword(); 

-}
\ No newline at end of file
+}

Index: passwordmaker/chrome/content/passwdmaker/passwordprompt.js
===================================================================
--- passwordmaker.orig/chrome/content/passwdmaker/passwordprompt.js 2007-06-13 16:42:30.000000000 -0500
+++ passwordmaker/chrome/content/passwdmaker/passwordprompt.js 2007-06-13 18:18:59.000000000 -0500
@@ -18,7 +18,7 @@
   along with this library; if not, write to the Free Software Foundation,

   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

 **/

-var passwordMaster, passwordMaster2, passwordStorageLB, confirmationRow,

+var passwordMaster, passwordMaster2, passwordStorageLB, confirmationRow, passwordSalt, passwordHashedVal, hashFunction,

   passwordMaker; // do not make local to onOK()--used in onPasswordStorageLBChanged();

 

 function onOK() {

@@ -28,6 +28,16 @@
      passwordMaster.focus();

     return false;

   }

+  else if (passwordHashedVal) {

+    // check if the entered password matches the hashed value

+    var newHash = hashFunction(passwordMaster.value, passwordSalt);

+    if (newHash != passwordHashedVal) {

+       passwordMaker.prompts.alert(this, "PasswordMaker", "The master password is not correct.");

+       passwordMaster.value = "";

+       passwordMaster.focus();

+       return false;

+    }

+  }

   else if (passwordMaster.value == "") {

     // mpw can't be empty

     passwordMaker.prompts.alert(this, "PasswordMaker", "The master password cannot be empty.");

@@ -61,6 +71,14 @@
   confirmationRow.hidden =

     passwordMaker._getLiteral(passwordMaker.globalSettingsSubjectRes, passwordMaker.confirmMPWPredicateRes) != "true";

 

+  passwordSalt = window.arguments[0].inn.salt;

+  passwordHashedVal = window.arguments[0].inn.hashed;

+  hashFunction = window.arguments[0].inn.hashFunction;

+

+  if (passwordHashedVal) {

+    confirmationRow.hidden = true;

+  }

+

   var settings = window.arguments[0].inn.settings;

   if (settings) {

     var accountsTree = document.getElementById("accountsTree");


John Lenz

  • Guest
Re: Patch against 1.6.2 to implement hash on disk
« Reply #1 on: June 14, 2007, 12:41:18 AM »
I guess the forum doesn't display email addresses... Oh well my address is at <removed>
« Last Edit: June 14, 2007, 01:12:54 AM by miquelfire »

Offline Miquel 'Fire' Burns

  • Administrator
  • *****
  • Posts: 1157
  • Programmer
Re: Patch against 1.6.2 to implement hash on disk
« Reply #2 on: June 14, 2007, 01:14:23 AM »
The forums shows an e-mail address actually. Not sure what normal members and guests see, but admins do see your e-mail.
"I'm not drunk, just sleep deprived."

Offline tanstaafl

  • God Member
  • ******
  • Posts: 1363
Re: Patch against 1.6.2 to implement hash on disk
« Reply #3 on: June 14, 2007, 12:27:55 PM »
Here is a patch I developed to store a hash of the master password on disk, and then display if the current password matches.   (One of the things on the feature request list...)

 Only visable in advanced options, but if the hash is stored when prompting for the password on the cool key, it won't accept a bad password.  The advanced options accepts "bad" passwords, just displays a message about not matching the hash on disk and allows you to overwrite the value.
Cool! This is something I'd love to see implemented... thanks!

Question: is this check on a per Account basis? This is how the Feature Request reads, and is how it needs to work in its final version. I use different Master Passwords for different Account Groups, and sometimes a different MPW for different accounts in the same group.

Thanks again for the contrib!

Offline Eric H. Jung

  • grimholtz
  • Administrator
  • *****
  • Posts: 3353
Re: Patch against 1.6.2 to implement hash on disk
« Reply #4 on: June 14, 2007, 12:42:44 PM »
John, I cannot see your email address. Did you use a valid one to register? If so, I can look it up in the admin console.

Offline tanstaafl

  • God Member
  • ******
  • Posts: 1363
Re: Patch against 1.6.2 to implement hash on disk
« Reply #5 on: June 14, 2007, 12:45:24 PM »
I can see it when I mouse-over the mail/envelope icon just underneath his username on the left... you can't see it?

Offline Eric H. Jung

  • grimholtz
  • Administrator
  • *****
  • Posts: 3353
Re: Patch against 1.6.2 to implement hash on disk
« Reply #6 on: June 14, 2007, 05:06:55 PM »
Yes, thanks. I didn't see that mail icon.

Offline tanstaafl

  • God Member
  • ******
  • Posts: 1363
Store Hash of MPW on disk
« Reply #7 on: June 20, 2007, 09:57:35 PM »
Pasting this from an email exchange... this is Johns reply to a question from me...

********************

Quote
Ok, still waiting for a comment from John - any chance - since you opened this can of worms -  ;)  - of continuing work on the patch to make it feature complete - ie, work on a per-account basis?

Thanks again for the contrib...

Sorry, have been busy this weekend....

Here is a better description:

In the (advanced) account settings page, you still type in the password twice, and there is just a label that says something like:

"Master Password does not match stored hash"

or

"Master Password matches stored hash"

or

"Master Password not hashed on disk"

and there is a button to store the hash to disk.  This hash is stored in the global settings, so the same for all accounts.  It is a SHA256 hash of a random salt plus the master password.

In the password prompt dialog (when hitting Alt-` for example), if there is a master password stored on disk, only one password input box shows up, and you get an error if the password does not match the hash (since
you are only imputing it once...).  But if no hash is on disk, the two input boxes show up like normal.

Note, this is currently a problem if you use multiple passwords, but only if you store the hash.  If you never store the hash, then on the options screen it will just tell you no hash on disk, and in the password prompt (Alt-`) it will have two password boxes just like before.


So there are two things needed to get different hashes for different accounts

1) Store the hash on a per account basis, with a default hash in the general settings that the hash falls back to.  Then on the Alt-` screen, we do know the account so the check can query the specific account for
the hash, then look for a default hash, and if neither is found use the current method of prompting twice.

This way, people like me with only one master password just set the default and never set the specific accounts, so the hash always falls back.

The Alt-` would then still error on a bad hash match.

2) On the account setting page, the label is updated in the generatepassword() function, which is called whenever the account selection changes.  The label then would implement the same checking
(first check specific account, then the default).

Lastly, the account settings would then need two buttons, one to store a hash in the currently selected account, and one to store a hash in the global settings.

John
« Last Edit: June 20, 2007, 10:18:26 PM by tanstaafl »

Offline tanstaafl

  • God Member
  • ******
  • Posts: 1363
Re: Store Hash of MPW on disk
« Reply #8 on: June 20, 2007, 09:58:15 PM »
Hi John,

Thanks for the reply...

Quote
In the password prompt dialog (when hitting Alt-` for example), if there is a master password stored on disk, only one password input box shows up, and you get an error if the password does not match the hash (since you are only imputing it once...).  But if no hash is on disk, the two input boxes show up like normal.

Ok, I'm assuming you said 'two input boxes' only because you have 'Confirm MPW...' set in the Global options... I don't, so I should only see the one input box, right?

If your change actually forces this 'Confirm MPW'), I would ask that this honor the Global option, and not make me enter it twice...

Quote
Note, this is currently a problem if you use multiple passwords, but only if you store the hash.  If you never store the hash, then on the options screen it will just tell you no hash on disk, and in the password prompt (Alt-`) it will have two password boxes just like before.

Gotcha...

Quote
So there are two things needed to get different hashes for different accounts

1) Store the hash on a per account basis, with a default hash in the general settings that the hash falls back to.  Then on the Alt-` screen, we do know the account so the check can query the specific account for the hash, then look for a default hash, and if neither is found use the current method of prompting twice.

This way, people like me with only one master password just set the default and never set the specific accounts, so the hash always falls back.

The Alt-` would then still error on a bad hash match.

2) On the account setting page, the label is updated in the generatepassword() function, which is called whenever the account selection changes.  The label then would implement the same checking (first check specific account, then the default).

Lastly, the account settings would then need two buttons, one to store a hash in the currently selected account, and one to store a hash in the global settings.

Ok, but let me pose a question...

Instead of doing all of this on a per account basis - which 'sounds' simple, but I imagine isn't - would it be easier to simply allow me to store multiple hashes, and just let me associate a particular hash with any given account? So, for each account, the default would be the 'Default' hash, with a drop-down selector to choose a different one (but the drop down would be greyed out if only one hash had been saved)...

Just thinking out loud, trying to see if there is an easier way to get it done that will satisfy the goal.

Now, the most critical question... ;)

Is either of these something that you think will take a lot of work? Since you already have the preliminary for doing this for just one MPW, how much more is needed to get it working on a per account basis?

Many thanks again for doing this! It will definitely be a major improvement for usability.

Offline Eric H. Jung

  • grimholtz
  • Administrator
  • *****
  • Posts: 3353
Re: Patch against 1.6.2 to implement hash on disk
« Reply #9 on: June 20, 2007, 10:23:16 PM »
Quote from: tanstaafl
Instead of doing all of this on a per account basis - which 'sounds' simple, but I imagine isn't - would it be easier to simply allow me to store multiple hashes, and just let me associate a particular hash with any given account? So, for each account, the default would be the 'Default' hash, with a drop-down selector to choose a different one (but the drop down would be greyed out if only one hash had been saved)...
I think this would be a UI nightmare. Users wouldn't understand this easily, and there's really no point to it if it's just a work-around for the ultimate goal of what you're asking for.

I would love if John were to write the code supporting multiple MPWs stored on disk.

Offline tanstaafl

  • God Member
  • ******
  • Posts: 1363
Re: Patch against 1.6.2 to implement hash on disk
« Reply #10 on: June 20, 2007, 10:35:39 PM »
Whatever the code doctor decides/recommends! ;)

Offline Eric H. Jung

  • grimholtz
  • Administrator
  • *****
  • Posts: 3353
Re: Patch against 1.6.2 to implement hash on disk
« Reply #11 on: July 08, 2007, 03:31:02 AM »
This has been merged into the trunk and released in PasswordMaker 1.7 beta 1. Look for the download link soon!

PasswordMaker Forums

Re: Patch against 1.6.2 to implement hash on disk
« Reply #11 on: July 08, 2007, 03:31:02 AM »