Password-Entropy-Calculator/index.html

1102 lines
37 KiB
HTML

<html><head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="description" content="Password Strength Tester : Calculates the entropy of a password">
<style>
a,
b,
body,
center,
code,
div,
form,
h1,
h2,
h3,
h4,
h5,
h6,
header,
html,
i,
object,
p,
s,
section,
span,
strong,
table,
tbody,
td,
time,
tr,
var {
margin: 0;
padding: 0;
border: 0;
font: inherit;
vertical-align: baseline
}
header,
section {
display: block
}
table {
border-collapse: collapse;
border-spacing: 0
}
#charset {
border: hidden
}
body {
box-sizing: border-box;
color: #373737;
background: #212121;
font-size: 16px;
font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif;
line-height: 1.5;
-webkit-font-smoothing: antialiased
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 10px 0;
font-weight: 700;
color: #222;
font-family: 'Lucida Grande', Calibri, Helvetica, Arial, sans-serif;
letter-spacing: -1px
}
h1 {
font-size: 36px;
font-weight: 700
}
h2 {
padding-bottom: 10px;
font-size: 32px;
background: url(../images/bg_hr.png) repeat-x bottom
}
h3 {
font-size: 24px
}
h4 {
font-size: 21px
}
h5 {
font-size: 18px
}
h6 {
font-size: 16px
}
p {
margin: 10px 0 10px 0
}
a {
text-decoration: none;
color: #007edf;
text-shadow: none;
transition: color .5s ease;
transition: text-shadow .5s ease;
-webkit-transition: color .5s ease;
-webkit-transition: text-shadow .5s ease;
-moz-transition: color .5s ease;
-moz-transition: text-shadow .5s ease;
-o-transition: color .5s ease;
-o-transition: text-shadow .5s ease;
-ms-transition: color .5s ease;
-ms-transition: text-shadow .5s ease
}
a:focus,
a:hover {
text-decoration: underline
}
strong {
font-weight: 700
}
code {
width: 100%;
color: #222;
background-color: #fff;
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
font-size: 14px;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px
}
code {
padding: 3px;
margin: 0 3px;
box-shadow: 0 0 10px rgba(0, 0, 0, .1)
}
#info {
border: 2px solid #373737;
text-align: left
}
td {
padding: 10px;
border: 1px solid #373737
}
form {
background: #f2f2f2;
padding: 20px
}
.outer {
width: 100%
}
.inner {
position: relative;
max-width: 640px;
padding: 20px 10px;
margin: 0 auto
}
#header_wrap {
background: #212121;
background: -moz-linear-gradient(top, #373737, #212121);
background: -webkit-linear-gradient(top, #373737, #212121);
background: -ms-linear-gradient(top, #373737, #212121);
background: -o-linear-gradient(top, #373737, #212121);
background: linear-gradient(top, #373737, #212121)
}
#header_wrap .inner {
padding: 50px 10px 30px 10px
}
#project_title {
margin: 0;
color: #fff;
font-size: 42px;
font-weight: 700;
text-shadow: #111 0 0 10px
}
#main_content_wrap {
background: #f2f2f2;
border-top: 1px solid #111;
border-bottom: 1px solid #111
}
#main_content {
padding-top: 40px;
height: 1100px
}
@media screen and (max-width:480px) {
body {
font-size: 14px
}
.inner {
min-width: 320px;
max-width: 480px
}
#project_title {
font-size: 32px
}
h1 {
font-size: 28px
}
h2 {
font-size: 24px
}
h3 {
font-size: 21px
}
h4 {
font-size: 18px
}
h5 {
font-size: 14px
}
h6 {
font-size: 12px
}
code {
min-width: 320px;
max-width: 480px;
font-size: 11px
}
}
</style>
<title>Password Strength Tester</title>
<script>
// fid-umd {"name":"PasswordStrength","jslint":1}
/*global module, exports, define, modulejs, YUI, console */
(function (name, root, factory) {
"use strict";
function isObject(x) { return typeof x === "object"; }
if ((typeof module)[0] === "o" && isObject(module.exports)) {
module.exports = factory();
} else if ((typeof exports)[0] === "o") {
exports[name] = factory();
} else if (isObject(root.define) && root.define.amd) {
root.define(name, [], factory);
} else if (isObject(root.modulejs)) {
root.modulejs.define(name, factory);
} else if (isObject(root.YUI)) {
root.YUI.add(name, function (Y) { Y[name] = factory(); });
} else {
root[name] = factory();
}
}("PasswordStrength", this, function () {
"use strict";
// fid-umd end
/**
* Shim the Math object to support log2 if it does not already.
*/
if (!Math.log2) {
Math.log2 = function (n) {
return Math.log(n) / Math.log(2);
};
}
/**
* Iterates over an object
*
* @param {Object} obj
* @param {Function(key,value)} callback
*/
function objectForEach(obj, callback) {
Object.keys(obj).forEach(function (key) {
callback(key, obj[key]);
});
}
/**
* Turns a list of characters into a regular expression that will match
* whatever you pass in. There may be trouble generating the pattern,
* so here we are escaping every character that isn't alphanumeric.
*
* @param {string} letters
* @param {string} flags (defaults to "")
* @return {RegExp} pattern
*/
function safeCharMatcher(letters, flags) {
return new RegExp("[" + letters.replace(/[\W_]/g, function (x) { return "\\" + x; }) + "]", flags || "");
}
/**
* Determine the strength of a password.
*
* Usage:
*
* ps = new PasswordStrength();
*
* // Improve checks by adding additional data files - optional
* ps.addCommonPasswords(pass); // data/common-passwords.json
* ps.addTrigraphMap(tri); // data/trigraphs.json
*
* // Calculate password strength
* stats = ps.check("my password");
*
* @return {PasswordStrength} instance
*/
function PasswordStrength() {
if (!(this instanceof PasswordStrength)) {
return new PasswordStrength();
}
this.CommonPasswords = null;
this.trigraph = null;
var Use33 = document.getElementById("33");
if (Use33.checked == true){
window.SymbolCharsets = " !#$%∞&'()*+,./:;<=>?@[]^_`{|}~-\""
} else {
window.SymbolCharsets = " !#$%&'()*+,./:;<=>?@[]^_`{|}~-\""
}
this.Charsets = {
Number: "0123456789",
Lowercase: "abcdefghijklmnopqrstuvwxyz",
Uppercase: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
Symbol: window.SymbolCharsets
};
window.Charsetscheck = this.Charsets
/**
* Sets CommonPassword property with what a user passes in.
* Uses it if it's an array, processes it into an array if it's a
* string and throws an error if it's not a format we can work with.
*
* Returns the PasswordCheck object so it can be chained
*
* @param {(Array|string)} passwords
* @return {PasswordStrength} PasswordStrength
*/
this.addCommonPasswords = function (passwords) {
if (passwords) {
if (Array.isArray(passwords)) {
this.CommonPasswords = passwords;
} else if (typeof passwords === "string") {
this.CommonPasswords = passwords.split(/\r\n|\r|\n/);
} else {
throw new Error("Format does not match any expected format.");
}
} else {
this.CommonPasswords = [];
}
return this;
};
/**
* TrigraphMap is an ojbect representing entries of 3 letter
* combinations and how often they appear.
*
* {
* "_ty": 123,
* "tyl": 22,
* "yle": 19,
* "ler": 5,
* "er_": 543
* }
*
* For further explanation on the numbers, check out the documentation
* in the data folder.
*
* @typedef {Object} PasswordStrength~trigraphMap
* @property {number} * Frequencies of that letter combo.
*/
/**
* Returns the PasswordStrength object so it can be chained
*
* TA: Again, define Object better. Make a type for
* PasswordStrength~trigraphMap.
*
* @param {PasswordStrength~trigraphMap} trigraphMap
* @return {PasswordStrength} PasswordStrength
*/
this.addTrigraphMap = function (trigraphMap) {
if (trigraphMap) {
if (trigraphMap && typeof trigraphMap === "object" && !Array.isArray(trigraphMap)) {
this.trigraph = trigraphMap;
} else {
throw new Error("Format does not match any expected format.");
}
} else {
this.trigraph = null;
}
return this;
};
/**
* charsetGroups is an object of different group of defined characters
* used in figuring out how many characters per group as well as
* what characters fall into each group. It is based on a
* PasswordStrength instance's `this.Charsets` object. When a password
* has a character that matches one of the character sets in the
* PasswordStrength instance's sets, this sets that key to `true`.
*
* The "other" key is all letters that did not match another set.
*
* Example for the password "abcd£1234":
*
* {
* lower: true,
* upper: false,
* number: true,
* punctuation: false,
* symbol: false,
* other: "£"
* }
*
* @typedef {Object} PasswordStrength~charsetGroups
* @property {string} other Characters that did not match another set
* @property {boolean} * All of the rest of the sets just set flags
*/
/**
* Gets the character set size of the current password.
* This breaks up the each character set and tests the password
* to see which set they belong in.
*
* @param {string} passToCheck
* @return {PasswordStrength~charsetGroups} groups
*/
this.charsetGroups = function (passToCheck) {
var groups;
groups = {};
objectForEach(this.Charsets, function (key, value) {
groups[key] = safeCharMatcher(value).test(passToCheck);
});
groups.other = this.otherChars(passToCheck);
return groups;
};
/**
* Calculates the size of each flag found for a password,
* and will get the flags if a password was passed in.
*
* @param {PasswordStrength~charsetGroups} groups
* @return {number} result
*/
this.Charsetsize = function (groups) {
var size;
size = 0;
objectForEach(this.Charsets, function (key, value) {
/*jslint unparam:true*/
if (groups[key]) {
size += value.length;
}
});
if (typeof groups.other === "string") {
size += groups.other.length;
}
return size;
};
/**
* Statistics is and object with information about the current state of
* the password.
*
* @typedef {Object} PasswordStrength~statistics
* @property {number} Charsetsize size of the characters from each
* group the characters fall into.
* @property {boolean} CommonPassword
* @property {number} PasswordLength the length of the current password
* @property {number} ShannonEntropyBits
* @property {string} strength how the strong the calculated password is
* estimated to be
* @property {(null|number)} TrigraphEntropyBits
*/
/**
* Calculates a bunch of statistics about a given password.
*
* TA: Define PasswordStrength~statistics
*
* @param {string} password
* @return {PasswordStrength~statistics}
*/
this.check = function (currentPassword) {
var result;
result = {
Charsetsize: 0,
CommonPassword: false,
PasswordLength: 0,
ShannonEntropyBits: 0,
StrengthCode: null,
TrigraphEntropyBits: 0,
Charsets: 0
};
// For undefined and if we get an empty value
if (!currentPassword || !currentPassword.length) {
if (this.trigraph) {
result.TrigraphEntropyBits = 0;
result.StrengthCode = "None";
result.Charsets = "None";
}
if (window.CommonPassword = true) {
result.CommonPassword = "yes";
}
return result;
}
result.CommonPassword = this.checkCommonPasswords(currentPassword);
result.Charsets = this.charsetGroups(currentPassword);
result.Charsetsize = this.Charsetsize(result.Charsets);
result.ShannonEntropyBits = this.shannonScore(currentPassword);
result.PasswordLength = currentPassword.length;
result.TrigraphEntropyBits = this.checkTrigraph(currentPassword, result.Charsetsize);
result.StrengthCode = this.determineStrength(result);
return result;
};
/**
* This checks to see if the password is in the common list of
* passwords. If in the common passwords lists, sets the warn flag.
*
* @param {string} passToCheck
* @return {boolean}
*/
this.checkCommonPasswords = function (passToCheck) {
var i, CommonPasswordsLength, CommonPasswordsList;
passToCheck = passToCheck.toLowerCase();
if (this.CommonPasswords && this.CommonPasswords.length) {
CommonPasswordsList = this.CommonPasswords;
CommonPasswordsLength = this.CommonPasswords.length;
for (i = 0; i < CommonPasswordsLength; i += 1) {
if (CommonPasswordsList[i] === passToCheck) {
return true;
}
}
return false;
}
return null;
};
/**
* Compares the password to the trigraph to get the rating of how
* guessable the password is.
*
* @param {string} passToCheck
* @param {number} Charsetsize
* @return {number} entropy in bits
*/
this.checkTrigraph = function (passToCheck, Charsetsize) {
var score, i, str;
if (!this.trigraph) {
return null;
}
score = 1;
passToCheck = passToCheck.toLowerCase().replace(/[\W_]/gi, " ").trim();
passToCheck = "_" + passToCheck + "_";
for (i = 0; i < passToCheck.length - 2; i += 1) {
str = passToCheck.substr(i, 3);
if (this.trigraph[str]) {
// Less than fully random
score *= (1.0 - (this.trigraph[str] / 10000)) * Charsetsize;
} else {
// Fully random selection
score *= Charsetsize;
}
}
return Math.log2(score);
};
/**
* Takes parameters and calculates the strength of a given password
* from a list of codes set. This will use the trigraph entropy bits if
* available and fallback to the shannon entropy bits which we should
* always have.
*
* @param {Object} status
* @return {string} StrengthCode
*/
this.determineStrength = function (status) {
var StrengthCode, entropyBits,
StrengthCode = "";
if (!status.TrigraphEntropyBits) {
entropyBits = status.ShannonEntropyBits;
} else {
entropyBits = status.TrigraphEntropyBits;
}
if (entropyBits <= 20) {
StrengthCode = "<font color=red>Extremely Weak</font>"; // Keep out a typical attacker for minutes
} else if (entropyBits <= 32) {
StrengthCode = "<font color=red>Very Weak</font>"; // Crackable by a typical home computer in a week.
} else if (entropyBits <= 48) {
StrengthCode = "<font color=red>Weak</font>"; // Crackable by a typical home computer in a week.
} else if (entropyBits <= 64) {
StrengthCode = "<font color=brown>Reasonable</font>"; // A specialized computer could get this in one year.
} else if (entropyBits <= 80) {
StrengthCode = "<font color=green>Strong</font>"; // Resistant to a large, coordinated attack (botnet) for over a year.
} else if (entropyBits <= 500) {
// Nearly impossible to brute force, given more than all of the computing power in the world,
// optimized algorithms, specialized hardware and a thousand years.
StrengthCode = "<font color=blue>Very Strong</font>";
} else if (entropyBits <= 1023) {
// Nearly impossible to brute force, given more than all of the computing power in the world,
// optimized algorithms, specialized hardware and thousands years.
StrengthCode = "<font color=orange>Insanely Strong</font>";
} else {
// impossible,
StrengthCode = "<font color=purple>404 Incomprehensibly Strong</font>";
}
return StrengthCode;
};
/**
* Calls function to see if there are other characters used
* which we don't explicitly check for.
*
* @param {string} passToCheck
* @return {string} result
*/
this.otherChars = function (passToCheck) {
var chars, hash, pattern;
chars = "";
objectForEach(this.Charsets, function (key, value) {
/*jslint unparam:true*/
chars += value;
});
pattern = safeCharMatcher(chars, 'g');
hash = {};
passToCheck.replace(pattern, '').split('').forEach(function (letter) {
hash[letter] = true;
});
return Object.keys(hash).join('');
};
/**
* Calculate the Shannon Entropy value of a password. This is really
* the number of bits necessary to represent the possible characters
* times the length of the password.
*
* Reworked from code under a MIT license.
* entropy.js MIT License © 2014 James Abney http://github.com/jabney
*
* @param {string} pass Password to evaluate
* @return {number} Bits of entropy
*/
this.shannonScore = function (pass) {
var freq, passLength, sum;
function countFrequencies() {
var c, h, i;
h = {}; // Hash for collecting frequencies
for (i = 0; i < passLength; i += 1) {
c = pass.charAt(i);
if (!h[c]) {
h[c] = 1;
} else {
h[c] += 1;
}
}
return h;
}
sum = 0;
passLength = pass.length;
freq = countFrequencies();
objectForEach(freq, function (key, value) {
/*jslint unparam:true*/
var score;
score = value / passLength;
sum -= score * Math.log2(score);
});
return sum * passLength;
};
}
return PasswordStrength;
// fid-umd post
}));
// fid-umd post-end
</script>
<script>
window.onload = function () {
"use strict";
var commonXhttp, frequencyXhttp, passwordField, CustomScenarioField, passwordInfo, passwordStatistics, passwordStrength;
function recalc(test3) {
var ps, stats, Charsetsize, PasswordLengthtext, CommonPassword, CommonPasswordvalue, PasswordLength, ShannonEntropyBits, TrigraphEntropyBits, StrengthCode, Charsets;
ps = passwordStrength.check(passwordField.value);
window.ps = passwordStrength.check(passwordField.value);
stats = "";
Charsets = "";
var test3;
window.Charsetsize = ps.Charsetsize;
window.UseGRC = document.getElementById("grc");
window.Use33 = document.getElementById("33");
if (window.Use33.checked == true){
window.passwordStrength.Charsets = {
Number: "0123456789",
Lowercase: "abcdefghijklmnopqrstuvwxyz",
Uppercase: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
Symbol: " !#$%∞&'()*+,./:;<=>?@[]^_`{|}~-\""
};
window.Use33.checked = true;
} else {
window.passwordStrength.Charsets = {
Number: "0123456789",
Lowercase: "abcdefghijklmnopqrstuvwxyz",
Uppercase: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
Symbol: " !#$%&'()*+,./:;<=>?@[]^_`{|}~-\""
};
window.Use33.checked = false;
}
ShannonEntropyBits = 0;
TrigraphEntropyBits = 0;
PasswordLengthtext = "";
if (ps) {
Object.keys(ps).forEach(function (key) {
if (ps[key] && typeof ps[key] === "object") {
Charsets += "<br><b>" + key + ":" + "</b>";
Object.keys(ps[key]).forEach(function (innerKey) {
Charsets += "<br><b>&nbsp;&nbsp;" + innerKey + ": </b>" + ps[key][innerKey];
});
} else {
stats += key + ": " + ps[key];
}
window.ExactSearchSpaceSize = Math.pow(window.Charsetsize, ps.PasswordLength);
window.ESSS = Math.pow(window.Charsetsize, ps.PasswordLength);
function grc(len)
{
if(len < 1)
{
return 0 ;
}
if (len == 1)
{
return window.ESSS;
}
return Math.pow(window.Charsetsize, len - 1) + grc(len - 1);
}
window.GRCESSS = grc(ps.PasswordLength)
window.UseGRC = document.getElementById("grc");
if (window.UseGRC.checked == true){
window.ESSS = window.GRCESSS;
window.ExactSearchSpaceSize = window.GRCESSS;
}
function numberWithCommas(num) {
var num_parts = num.toString().split(".");
num_parts[0] = num_parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return num_parts.join(".");
}
window.PossibleCombinations = numberWithCommas(window.ESSS)
function getTime(rate){
var s = window.ExactSearchSpaceSize/rate;
var decimalYears = s/(3600*24*365);
var years = Math.floor(decimalYears);
var decimalMonths =(decimalYears-years)*12;
var months = Math.floor(decimalMonths);
var decimalDays = (decimalMonths-months)*30;
var days = Math.floor(decimalDays);
var decimalHours = (decimalDays-days)*24;
var hours = Math.floor(decimalHours);
var decimalMinutes = (decimalHours-hours)*60;
var minutes = Math.floor(decimalMinutes);
var decimalSeconds = (decimalMinutes-minutes)*60;
var seconds = Math.floor(decimalSeconds);
var decimalMilliseconds = (decimalSeconds)*1000;
var milliseconds = Math.floor(decimalMilliseconds);
var decimalMicroseconds = (decimalMilliseconds)*1000;
var microseconds = Math.floor(decimalMicroseconds);
var decimalNanoseconds = (decimalMicroseconds)*1000;
var nanoseconds = Math.floor(decimalNanoseconds);
var time = [];
if(years > 0){
if(years == 1)
time.push("1 year, ");
else
time.push(numberWithCommas(years) + " years, ");
}
if(months > 0){
if(months == 1)
time.push("1 month, ");
else
time.push(months + " months, ");
}
if(days > 0){
if(days == 1)
time.push("1 day, ");
else
time.push(days + " days, ");
}
if(hours > 0){
if(hours == 1)
time.push("1 hour, ");
else
time.push(hours + " hours, ");
}
if(minutes > 0){
if(minutes == 1)
time.push("1 minute, ");
else
time.push(minutes + " minutes, ");
}
if(seconds > 0){
if(seconds == 1)
time.push("1 second, ");
else
time.push(seconds + " seconds, ");
window.seconds = seconds
}
if(milliseconds > 0){
if(milliseconds == 1)
time.push("1 Milisecond, ");
else
if(seconds > 1) {
var fixmilliseconds = (seconds * 1000) - milliseconds;
milliseconds = fixmilliseconds - (fixmilliseconds * 2);
time.push(milliseconds + " Milliseconds, ");
}else{
time.push(milliseconds + " Milliseconds, ");
}
}
if(microseconds > 0){
if(microseconds == 1)
time.push("1 Microsecond, ");
else
if(milliseconds > 1) {
var fixmicroseconds = (milliseconds * 1000) - microseconds;
microseconds = fixmicroseconds - (fixmicroseconds * 2);
time.push(microseconds + " Microseconds, ");
}else{
time.push(microseconds + " Microseconds, ");
}
}
if(nanoseconds > 0){
if(nanoseconds == 1)
time.push("1 Nanosecond, ");
else
if(microseconds > 1) {
var fixnanoseconds = (microseconds * 1000) - nanoseconds;
nanoseconds = fixnanoseconds - (fixnanoseconds * 2);
time.push(nanoseconds + " Nanoseconds, ");
}else{
time.push(nanoseconds + " Nanoseconds, ");
}
}
if(time.length <= 0)
time = "Less Then a Nanosecond, ";
else if(time.length == 1)
time = time[0];
else
time = time[0] + time[1];
return time.substring(0,time.length-2);
}
window.CustomScenarioNumber = getTime(document.getElementById('customscenario').value)
if(document.getElementById('customscenario').value == ""){
window.CustomScenarioNumber = "Guesses Per Second Not Specified."
}
window.OnlineAttackScenarioNumber = getTime(1000)
window.PasswordDepotsExampleScenarioNumber = getTime(2000000000)
window.OfflineFastAttackScenarioNumber = getTime(100000000000)
window.DistributedScenarioNumber = getTime(800000000000)
window.MassiveCrackingArrayScenarioNumber = getTime(100000000000000)
document.getElementById('length').innerHTML = '<td class="txt" style="color: black;">Password Length: ' + ps.PasswordLength + "</td>";
ShannonEntropyBits = "<br><b>" + "ShannonEntropyBits: </b>" + ps.ShannonEntropyBits.toFixed(2);
TrigraphEntropyBits = "<br><b>" + "TrigraphEntropyBits: </b>" + ps.TrigraphEntropyBits.toFixed(2);
var CustomScenario = "<br><b>" + "Custom Scenario: </b>" + window.CustomScenarioNumber;
var OnlineAttackScenario = "<br><b>" + "GRC.com Online Attack Example Scenario: </b>" + window.OnlineAttackScenarioNumber;
var PasswordDepotsExampleScenario = "<br><b>" + "Password-Depot.de Example Scenario: </b>" + window.PasswordDepotsExampleScenarioNumber;
var OfflineFastAttackScenario = "<br><b>" + "GRC.com Offline Fast Attack Example Scenario: </b>" + window.OfflineFastAttackScenarioNumber;
var DistributedScenario ="<br><b>" + "Distributed.net May 8, 2012 Scenario: </b>" + window.DistributedScenarioNumber;
var MassiveCrackingArrayScenario ="<br><b>" + "GRC.com Massive Cracking Array Example: </b>" + window.MassiveCrackingArrayScenarioNumber;
StrengthCode = "<br><b>" + "Strength Code: </b>" + ps.StrengthCode;
var tableStart = '<table id="info" cellpadding="0" cellspacing="0" class="r_box" align="center"><td>';
var tableEnd = '</td></table>';
var SearchTitle = "<b>" + "[Time Required to Exhaustively Search All Possible Combinations]"
var PC = "<br><b>" + "All Possible combinations: </b>" + window.PossibleCombinations;
if(ps.CommonPassword == true){
CommonPasswordvalue = "<br><b>" + "WARNING: </b>" + "<font color=black>[</font><font color=red>Common Password!</font><font color=black>]</font>";
StrengthCode = "<br><b>" + "Strength Code: </b>" + "<font color=red>Extremely Weak</font>";
}else{CommonPasswordvalue = ""}
if (ps.PasswordLength <= 4) {
PasswordLengthtext = "<br><b>" + "WARNING: </b>" + "<font color=black>[</font><font color=red>Very Short Password!</font><font color=black>]</font>";
}else if (ps.PasswordLength <= 7) {
PasswordLengthtext = "<br><b>" + "WARNING: </b>" + "<font color=black>[</font><font color=red>Short Password!</font><font color=black>]</font>";}
if (ps.TrigraphEntropyBits == "Infinity") {
TrigraphEntropyBits = "<br><b>" + "EntropyBits: </b>" + "∞";
ShannonEntropyBits = "";
AverageBits = "";
}
Charsetsize = "<b>" + "Charsetsize: </b>" + window.Charsetsize;
if (ps.Charsets.Uppercase == true){document.getElementById('upper').innerHTML = '<td class="txt" style="color: green;">Uppercase</td>'}else{document.getElementById('upper').innerHTML = '<td class="txt" style="color: black;">Uppercase</td>'}
if (ps.Charsets.Lowercase == true){document.getElementById('lower').innerHTML = '<td class="txt" style="color: green;">Lowercase</td>'}else{document.getElementById('lower').innerHTML = '<td class="txt" style="color: black;">Lowercase</td>'}
if (ps.Charsets.Number == true){document.getElementById('number').innerHTML = '<td class="txt" style="color: green;">Number</td>'}else{document.getElementById('number').innerHTML = '<td class="txt" style="color: black;">Number</td>'}
if (ps.Charsets.Symbol == true){document.getElementById('symbol').innerHTML = '<td class="txt" style="color: green;">Symbol</td>'}else{document.getElementById('symbol').innerHTML = '<td class="txt" style="color: black;">Symbol</td>'}
stats = Charsetsize + ShannonEntropyBits + TrigraphEntropyBits + CommonPasswordvalue + PasswordLengthtext + StrengthCode + PC + tableStart + SearchTitle + CustomScenario + OnlineAttackScenario + PasswordDepotsExampleScenario + OfflineFastAttackScenario + DistributedScenario + MassiveCrackingArrayScenario + tableEnd;
});
}
if (ps.PasswordLength <= 0) {
passwordStatistics.innerHTML = "Enter a password to see its strength.";
}else{passwordStatistics.innerHTML = stats;
}
}
function setReadyStateChange(xhr, passwordStrengthMethod, elementId) {
xhr.onreadystatechange = function () {
var result;
if (xhr.readyState == 4) {
if (xhr.status == 200) {
passwordStrength[passwordStrengthMethod](JSON.parse(xhr.responseText));
document.getElementById(elementId).style.display = 'none';
recalc();
} else {
document.getElementById(elementId).innerHTML = "Unable to load (" + elementId + "): " + xhr.status;
}
}
};
}
passwordField = document.getElementById('PasswordField');
var recalculatebutton = document.getElementById('recalculate');
var use33checkbox = document.getElementById('33');
var UseGRCbox = document.getElementById("grc");
CustomScenarioField = document.getElementById('customscenario');
passwordInfo = document.getElementById('PasswordInfo');
passwordStatistics = document.getElementById('PasswordStatistics');
commonXhttp = new XMLHttpRequest();
setReadyStateChange(commonXhttp, 'addCommonPasswords', 'commonXhttp');
commonXhttp.open("GET", "https://raw.githubusercontent.com/tests-always-included/password-strength/master/data/common-passwords.json", true);
commonXhttp.send();
frequencyXhttp = new XMLHttpRequest();
setReadyStateChange(frequencyXhttp, 'addTrigraphMap', 'frequencyXhttp');
frequencyXhttp.open("GET", "https://raw.githubusercontent.com/tests-always-included/password-strength/master/data/trigraphs.json", true);
frequencyXhttp.send();
function wait(ms){
var start = new Date().getTime();
var end = start;
while(end < start + ms) {
end = new Date().getTime();
}
}
passwordStrength = new window.PasswordStrength();
passwordField.onkeyup = recalc;
CustomScenarioField.onkeyup = recalc;
recalculatebutton.onclick = recalc;
window.recalc = recalc;
// Expose this object so the console can diagnose and debug
// issues.
window.passwordStrength = passwordStrength;
};
</script>
</head>
<body>
<!-- HEADER -->
<div id="header_wrap" class="outer">
<header class="inner">
<h1 id="project_title">Password Entropy Calculator</h1>
</header>
</div>
<!-- MAIN CONTENT -->
<div id="main_content_wrap" class="outer">
<section id="main_content" class="inner">
<p id="commonXhttp" style="display: none;">Loading common words ...</p>
<p id="frequencyXhttp" style="display: none;">Loading frequency table ...</p>
<p>Calculates the relative strength of a password. This is accomplished by using several techniques. Primarily this relies on letter trigraphs, which check each set of 3 characters in a given password. This also calculates the entropy bits based on Claude Shannon's technique on determining the number of bits required to represent a set of characters and multiplying it by the length of the password. There is also a check to see if a password is contained in a list of common passwords.<p>
<p>As a bonus there's also a "Search Space" or (Total Possible Combinations) Calculator, inspired by <a href="https://www.grc.com/haystack.htm" target="_blank">GRC's Interactive Brute Force Password “Search Space” Calculator.</a></p>
<p>Try some of the calculations from Password.Depot.de if you'd like.</p>
<p>Side note: Password.Depot.de's calculation for 94^9 is incorrect. Google it lol</p>
Custom Scenario = <input id="customscenario" type="number" autocomplete="off" autofocus="autofocus" style="background-color: white; width: 20%; cursor: auto;"> Guesses Per Second.
<p>GRC's Online Attack Example Scenario = 1 Thousand Guesses Per Second.</p>
<p><a href="https://www.password-depot.de/en/know-how/brute-force-attacks.htm" target="_blank">Password-Depot.de</a> Example Scenario = 2 Billion Guesses Per Second.</p>
<p>GRC's Offline Fast Attack Example Scenario = 100 Billion Guesses Per Second.</p>
<p><a href="https://www.distributed.net/Main_Page" target="_blank">Distributed.net</a> May 8, 2012 Scenario = 800 Billion Guesses Per Second.</p>
<p>GRC's Massive Cracking Array Example Scenario = 100 Trillion Guesses Per Second.</p>
<div id="PasswordInfo">
Type your password in here:
<form _lpchecked="1">
<input id="PasswordField" type="password" autocomplete="off" autofocus="autofocus" style="background-color: white; width: 66%; margin-left: -10px; cursor: auto;"> <input id="recalculate" type="button" value="Recalculate">
</form>
<input id="grc" type="checkbox">Use GRC's Algorithm.
<input id="33" type="checkbox">Use 33 Symbol Charset (GRC Uses This).
<table id="charset">
<tr>
<td id="charset"><table id="info" border="0" cellpadding="0" cellspacing="0"><tbody><tr id="upper"><td class="txt" style="color: black;">Uppercase</td></tr></tbody></table></td>
<td id="charset"><table id="info" border="0" cellpadding="0" cellspacing="0"><tbody><tr id="lower"><td class="txt" style="color: black;">Lowercase</td></tr></tbody></table></td>
<td id="charset"><table id="info" border="0" cellpadding="0" cellspacing="0"><tbody><tr id="number"><td class="txt" style="color: black;">Numbers</td></tr></tbody></table></td>
<td id="charset"><table id="info" border="0" cellpadding="0" cellspacing="0"><tbody><tr id="symbol"><td class="txt" style="color: black;">Symbols</td></tr></tbody> </table></td>
<td id="charset"><table id="info" border="0" cellpadding="0" cellspacing="0"><tbody><tr id="length"><td class="txt" style="color: black;">Password Length: 0</td></tr></tbody> </table></td>
</tr>
</table>
<table id="info" border="0" cellpadding="0" cellspacing="0" class="r_box" align="center" style="margin-left: 10px; margin-top: 0px; margin-bottom: 0px; width: 95%;"><tbody><tr><td class="r_box"><span id="PasswordStatistics"></span></td></tr></tbody></table>
</body></html>