📜 ⬆️ ⬇️

Microsoft password strength estimation algorithm (Part 1)

I searched for information on password strength estimation algorithms, found a topic on Habré with a link to Microsoft Password Checker . As it turned out, the durability check is performed using a small JS script, so there was a desire to document the checking algorithm in detail. Someone may need to clarify why this or that conclusion is made, and someone - to improve the algorithm.

In the wake of the discussion on Habré, I will collect the main theses.
  1. The check is implemented as passwdcheck.js .
  2. Experiments have shown that the test does not take into account some of the simplest things that greatly reduce resistance.
  3. Recommendations from Microsoft for creating memorable complex passwords.
So,

Analysis of the code showed that it contains not one, but as many as two password strength analyzers - the current, fairly simplified, and the old more profound.

Let's start with the current one, according to which the analyzer is working now. In the second part will be the analysis of the old.
Below is the source code of this algorithm in JS (I removed the extra debugging comments that were in the text).
')
 var alpha = "abcdefghijklmnopqrstuvwxyz"; var upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; var upper_punct = "~`!@#$%^&*()-_+="; var digits = "1234567890"; var totalChars = 0x7f - 0x20; var alphaChars = alpha.length; var upperChars = upper.length; var upper_punctChars = upper_punct.length; var digitChars = digits.length; var otherChars = totalChars - (alphaChars + upperChars + upper_punctChars + digitChars); function GEId(sID) { return document.getElementById(sID); } function calculateBits(passWord) { if (passWord.length < 0) { return 0; } var fAlpha = false; var fUpper = false; var fUpperPunct = false; var fDigit = false; var fOther = false; var charset = 0; for (var i = 0; i < passWord.length; i++) { var char = passWord.charAt(i); if (alpha.indexOf(char) != -1) fAlpha = true; else if (upper.indexOf(char) != -1) fUpper = true; else if (digits.indexOf(char) != -1) fDigit = true; else if (upper_punct.indexOf(char) != -1) fUpperPunct = true; else fOther = true; } if (fAlpha) charset += alphaChars; if (fUpper) charset += upperChars; if (fDigit) charset += digitChars; if (fUpperPunct) charset += upper_punctChars; if (fOther) charset += otherChars; var bits = Math.log(charset) * (passWord.length / Math.log(2)); return Math.floor(bits); } function DispPwdStrength(iN, sHL) { if (iN > 4) { iN = 4; } for (var i = 0; i < 5; i++) { var sHCR = "pwdChkCon0"; if (i <= iN) { sHCR = sHL; } if (i > 0) { GEId("idSM" + i).className = sHCR; } GEId("idSMT" + i).style.display = ((i == iN) ? "inline" : "none"); } } function EvalPwdStrength(oF, sP) { var bits = calculateBits(sP); if (bits >= 128) { DispPwdStrength(4, 'pwdChkCon4'); } else if (bits < 128 && bits >= 64) { DispPwdStrength(3, 'pwdChkCon3'); } else if (bits<64 && bits>=56) { DispPwdStrength(2, 'pwdChkCon2'); } else if (bits<56) { DispPwdStrength(1, 'pwdChkCon1'); } else { DispPwdStrength(0, 'pwdChkCon0'); } } 

Conclusion : trivial does not mean good. This algorithm does not take into account many aspects of the strength of passwords - for example, dictionary attacks or repeated characters.

Continued, see Part 2 .

Source: https://habr.com/ru/post/116331/


All Articles