Skip to content

Instantly share code, notes, and snippets.

@mschmitt
Created February 19, 2014 08:45
Show Gist options
  • Save mschmitt/9088238 to your computer and use it in GitHub Desktop.
Save mschmitt/9088238 to your computer and use it in GitHub Desktop.
Helper for generating and checking password hashes.
#!/usr/bin/perl -w
use diagnostics;
use strict;
use POSIX qw(setsid);
use Crypt::Passwd::XS;
use Tk;
# Fork off.
if (1){
fork() && exit;
#print STDERR "\nForked: PID $$\n";
chdir "/";
open STDIN, "</dev/null";
open STDERR, ">/dev/null";
open STDOUT, ">/dev/null";
}
# Some global variables used later
my @salt_chars = ('.', '/', 0..9, 'A'..'Z', 'a'..'z');
my $pw2hash_radiobutton = 'DES';
my $pw2hash_radiobutton_previous = ' ';
my $pw2hash_input_show = '*';
my $pw2hash_input_previous = '';
my $match_hash_pw_input_show = '*';
# UI element definition
my $mw = MainWindow->new();
$mw->title('Shadow Mangler');
$mw->minsize(400,0);
my $pw2hash_frame = $mw->Frame(
);
my $match_hash_frame = $mw->Frame(
);
my $pw2hash_label = $pw2hash_frame->Label(
-text => 'Convert password to hash:'
);
my $pw2hash_input = $pw2hash_frame->Entry(
-show => '*'
);
my $pw2hash_reveal_button = $pw2hash_frame->Checkbutton(
-text => 'Reveal',
-command => \&pw2hash_input_show_toggle
);
my $pw2hash_des_button = $pw2hash_frame->Radiobutton(
-text => 'DES',
-value => 'DES',
-variable => \$pw2hash_radiobutton,
-command => \&pw2hash_do_hash
);
my $pw2hash_md5_button = $pw2hash_frame->Radiobutton(
-text => 'MD5',
-value => 'MD5',
-variable => \$pw2hash_radiobutton,
-command => \&pw2hash_do_hash
);
my $pw2hash_sha512_button = $pw2hash_frame->Radiobutton(
-text => 'SHA-512',
-value => 'SHA-512',
-variable => \$pw2hash_radiobutton,
-command => \&pw2hash_do_hash
);
my $pw2hash_output = $pw2hash_frame->Entry(
-takefocus => 0,
-state => 'readonly'
);
my $match_hash_label = $match_hash_frame->Label(
-text => 'Match password and existing hash:'
);
my $match_hash_pw_input_label = $match_hash_frame->Label(
-text => 'Password:'
);
my $match_hash_pw_input = $match_hash_frame->Entry(
-show => '*'
);
my $match_hash_pw_input_reveal_button = $match_hash_frame->Checkbutton(
-text => 'Reveal',
-command => \&match_hash_pw_input_show_toggle
);
my $match_hash_hash_input_label = $match_hash_frame->Label(
-text => 'Hash:'
);
my $match_hash_hash_input = $match_hash_frame->Entry(
);
my $match_hash_indicator = $match_hash_frame->Label(
-text => 'Not matching',
-foreground => 'red'
);
# UI element positioning - TODO: Arrange more neatly. LOL.
# Internal frames for each application use case
$pw2hash_frame->pack(-side => 'top', -fill => 'both', -padx => 10, -pady => 10);
$match_hash_frame->pack(-side => 'top', -fill => 'both', -padx => 10, -pady => 10);
$pw2hash_label->pack;
$pw2hash_input->pack(-fill => 'x');
$pw2hash_reveal_button->pack;
$pw2hash_des_button->pack;
$pw2hash_md5_button->pack;
$pw2hash_sha512_button->pack;
$pw2hash_output->pack(-fill => 'x');
$match_hash_label->pack;
$match_hash_pw_input_label->pack;
$match_hash_pw_input->pack(-fill => 'x');
$match_hash_pw_input_reveal_button->pack;
$match_hash_hash_input_label->pack;
$match_hash_hash_input->pack(-fill => 'x');
$match_hash_indicator->pack;
# Automatic actions on input fields
foreach ('<KeyRelease>', '<ButtonRelease>', '<<Paste>>'){
$pw2hash_input->bind($_ => \&pw2hash_do_hash);
$match_hash_pw_input->bind($_ => \&match_hash_do_match);
$match_hash_hash_input->bind($_ => \&match_hash_do_match);
}
MainLoop; # It's pretty much downhill from here.
sub pw2hash_input_show_toggle {
if ($pw2hash_input_show){
$pw2hash_input->configure(-show => '');
$pw2hash_input_show = '';
}else{
$pw2hash_input->configure(-show => '*');
$pw2hash_input_show = '*';
}
1;
}
sub pw2hash_do_hash {
# Only recalculate if input or radio button have changed
if ( ($pw2hash_radiobutton ne $pw2hash_radiobutton_previous) or
($pw2hash_input->get() ne $pw2hash_input_previous) ){
$pw2hash_radiobutton_previous = $pw2hash_radiobutton;
$pw2hash_input_previous = $pw2hash_input->get();
if ($pw2hash_radiobutton eq 'DES'){
pw2hash_des();
}elsif($pw2hash_radiobutton eq 'MD5'){
pw2hash_md5();
}elsif($pw2hash_radiobutton eq 'SHA-512'){
pw2hash_sha512();
}
}
1;
}
sub pw2hash_des {
my $salt;
for(1..2) {
$salt .= $salt_chars[int(rand(scalar(@salt_chars)))];
}
my $encrypted_pass = Crypt::Passwd::XS::crypt($pw2hash_input->get(), $salt);
$pw2hash_output->configure(-text => $encrypted_pass);
1;
}
sub pw2hash_md5 {
my $salt = '$1$';
for(1..8) {
$salt .= $salt_chars[int(rand(scalar(@salt_chars)))];
}
my $encrypted_pass = Crypt::Passwd::XS::crypt($pw2hash_input->get(), $salt);
$pw2hash_output->configure(-text => $encrypted_pass);
1;
}
sub pw2hash_sha512 {
my $salt = '$6$';
for(1..8) {
$salt .= $salt_chars[int(rand(scalar(@salt_chars)))];
}
my $encrypted_pass = Crypt::Passwd::XS::crypt($pw2hash_input->get(), $salt);
$pw2hash_output->configure(-text => $encrypted_pass);
1;
}
sub match_hash_pw_input_show_toggle {
if ($match_hash_pw_input_show){
$match_hash_pw_input->configure(-show => '');
$match_hash_pw_input_show = '';
}else{
$match_hash_pw_input->configure(-show => '*');
$match_hash_pw_input_show = '*';
}
1;
}
sub match_hash_do_match {
my ($input_pass, $input_hash) = ($match_hash_pw_input->get(), $match_hash_hash_input->get());
if ($input_pass and $input_hash){
if (Crypt::Passwd::XS::crypt($input_pass, $input_hash) eq $input_hash){
$match_hash_indicator->configure(
-foreground => 'green',
-text => 'Matching'
);
}else{
$match_hash_indicator->configure(
-foreground => 'red',
-text => 'Not Matching'
);
}
}else{
$match_hash_indicator->configure(
-foreground => 'red',
-text => 'Not Matching'
);
}
1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment