Skip to content

Instantly share code, notes, and snippets.

@wheresjames
Last active October 27, 2016 12:09
Show Gist options
  • Save wheresjames/bdfe1d7b8ed6964afcfb172c5a165e83 to your computer and use it in GitHub Desktop.
Save wheresjames/bdfe1d7b8ed6964afcfb172c5a165e83 to your computer and use it in GitHub Desktop.
Password strength checker
<?php
function ClassifyChar( $ch )
{
if ( ( 'a' <= $ch && 'z' >= $ch ) || ' ' == $ch )
return 'lower';
if ( 'A' <= $ch && 'Z' >= $ch )
return 'upper';
if ( '0' <= $ch && '9' >= $ch )
return 'number';
if ( false === strpos( "`~!@#$%^&*()_-+={}|[]\\:\";',./<>?", $ch ) )
return 'symbol';
return 'other';
}
function CalcPasswordStrength( $pw )
{
if ( !strlen( $pw ) )
return 0;
$score = array( "lower"=>26, "upper"=>26, "number"=>10, "symbol"=>35, "other"=>20 );
$dist = array(); $used = array();
for ( $i = 0; $i < strlen( $pw ); $i++ )
if ( !isset( $used[ $pw[ $i ] ] ) )
{ $used[ $pw[ $i ] ] = 1;
$c = ClassifyChar( $pw[ $i ] );
if ( !isset( $dist[ $c ] ) )
$dist[ $c ] = $score[ $c ] / 2;
else
$dist[ $c ] = $score[ $c ];
}
$total = 0;
foreach( $dist as $k => $v )
$total += $v;
$used = array();
$strength = 1;
for ( $i = 0; $i < strlen( $pw ); $i++ )
{
if ( !isset( $used[ $pw[ $i ] ] ) )
$used[ $pw[ $i ] ] = 1;
else
$used[ $pw[ $i ] ]++;
if ( $total > $used[ $pw[ $i ] ] )
$strength *= $total / $used[ $pw[ $i ] ];
}
return (int)( log( $strength ) );
}
<!DOCTYPE html>
<meta charset="utf-8">
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<style>
body
{
min-width: 600px;
padding: 2em;
}
.form-control[type='password']
{
width: 100%;
}
.password-group .form-control-feedback
{
top: 0;
right: 15px;
}
.outerbox
{
border: 2px dashed #ccc;
padding: 1em;
margin: 1em;
}
#showPassword
{
font-size: 1.5em;
font-weight: bold;
border: 1px solid #888;
border-radius: 5px;
padding: 1em;
height: 4em;
background: #ccc;
color: #000;
}
.help-block.with-errors
{
height: 2em;
}
</style>
<body>
<div class="outerbox">
<form id="signup" data-toggle="validator" role="form" onsubmit="return false;">
<div class="new-user">
<div class="form-group password-group">
<label for="password" class="control-label">Password</label>
<div class="form-inline row">
<div class="form-group has-feedback col-sm-6">
<input type="password" data-strength-check="1" data-strength-check-error="Password is too weak" class="form-control" id="password" placeholder="Password" required>
<span class="glyphicon form-control-feedback" aria-hidden="true"></span>
<div class="help-block with-errors"></div>
</div>
<div class="form-group has-feedback col-sm-6">
<input type="password" class="form-control" id="password2" data-match="#password" data-match-error="Passwords do not match" placeholder="Confirm" required>
<span class="glyphicon form-control-feedback" aria-hidden="true"></span>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="progress">
<span id="passwordStrength" class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></span>
</div>
<div id="showPassword">
</div>
</div>
</div>
</form>
</div>
</div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/1000hz-bootstrap-validator/0.11.5/validator.min.js"></script>
<script>
function ClassifyChar( ch )
{
if ( ( 'a' <= ch && 'z' >= ch ) || ' ' == ch )
return 'lower';
if ( 'A' <= ch && 'Z' >= ch )
return 'upper';
if ( '0' <= ch && '9' >= ch )
return 'number';
if ( 0 <= "`~!@#$%^&*()_-+={}|[]\\:\";',./<>?".indexOf( ch ) )
return 'symbol';
return 'other';
}
function CalcPasswordStrength( pw )
{
if ( !pw.length )
return 0;
var score = { "lower":26, "upper":26, "number":10, "symbol":35, "other":20 };
var dist = {}, used = {};
for ( var i = 0; i < pw.length; i++ )
if ( undefined === used[ pw[ i ] ] )
{ used[ pw[ i ] ] = 1;
var c = ClassifyChar( pw[ i ] );
if ( undefined === dist[ c ] )
dist[ c ] = score[ c ] / 2;
else
dist[ c ] = score[ c ];
}
var total = 0;
$.each( dist, function( k, v ) { total += v; } );
used = {};
var strength = 1;
for ( var i = 0; i < pw.length; i++ )
{
if ( undefined === used[ pw[ i ] ] )
used[ pw[ i ] ] = 1;
else
used[ pw[ i ] ]++;
if ( total > used[ pw[ i ] ] )
strength *= total / used[ pw[ i ] ];
}
return parseInt( Math.log( strength ) );
}
$("#password").keyup( function( e )
{
var ctrl = '#passwordStrength';
var strength = CalcPasswordStrength( $("#password").val() );
var percent = Math.max(15, Math.min(100, parseInt( strength )));
$('#showPassword').text($("#password").val());
$(ctrl).width( '' + percent + '%' );
$(ctrl).removeClass( 'progress-bar-success progress-bar-warning progress-bar-danger' );
if ( 40 > strength )
$(ctrl).text( 'Weak' ),
$(ctrl).addClass( 'progress-bar-danger' );
else if ( 60 > strength )
$(ctrl).text( 'Good' ),
$(ctrl).addClass( 'progress-bar-warning' );
else if ( 90 > strength )
$(ctrl).text( 'Strong' ),
$(ctrl).addClass( 'progress-bar-success' );
else
$(ctrl).text( 'Very Strong' ),
$(ctrl).addClass( 'progress-bar-success' );
$(ctrl).attr( 'data-strength', strength );
$(this).attr( 'data-strength', strength );
});
$('#signup').validator({
custom:
{
'strength-check': function($el) { if ( !$el.val().length ) return 0; return ( 40 > CalcPasswordStrength( $el.val() ) );}
},
errors:
{
'strength-check': "Password is too weak"
}
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment