#!/usr/bin/env perl use strict; use warnings; use v5.16; use Getopt::Long; use Digest::MD5; use Digest::SHA; use MIME::Base64; my $debug; GetOptions( 'debug' => \$debug, ); my $domain = $ARGV[0]; my $master = $ARGV[1]; my $len = $ARGV[2] || 10; my $algo = $ARGV[3] || 'md5'; # 'md5' or 'sha512' if (!$domain || !$master) { die("Usage: $0 domain.com master_passwd [length] [md5/sha512]\n"); } my $sgp = supergen_pass($domain, $master, $len, $algo); print "$sgp\n"; ############################################################################### ############################################################################### sub supergen_pass { my ($domain, $master, $length, $algo) = @_; $algo ||= 'md5'; $length ||= 10; $domain = lc($domain); if ($debug) { k("SGP Config: Domain:$domain, Master:$master, Length:$length, Algorithm:$algo"); } my $count = 0; my $hash = $master . ':' . $domain; while (1) { my $hash_str = ''; if ($algo eq 'sha512') { $hash_str = Digest::SHA::sha512($hash); } else { $hash_str = Digest::MD5::md5($hash); } my $b64 = encode_base64($hash_str, ''); $b64 =~ tr|+/=|98A|; # Remove `+` `/` and `=` $hash = $b64; $count++; if ($debug) { k("Round $count: $hash"); } # We loop a MINIMUM of 10 times if ($count < 10) { next; } my $tmp = substr($hash, 0, $length); # Must start with lower case letter # Must contain an uppercase letter # Must contain a digit my $is_valid = ($tmp =~ /^[a-z]/) && ($tmp =~ /[A-Z]/) && ($tmp =~ /[0-9]/); # If it's a valid we stop, otherwise we continue looping UNTIL we are valid if ($is_valid) { last; } } my $ret = substr($hash, 0, $length); return $ret; } ############################################################################### ############################################################################### # Creates methods k() and kd() to print, and print & die respectively BEGIN { if (eval { require Data::Dump::Color }) { *k = sub { Data::Dump::Color::dd(@_) }; } else { require Data::Dumper; *k = sub { print Data::Dumper::Dumper(\@_) }; } sub kd { k(@_); printf("Died at %2\$s line #%3\$s\n",caller()); exit(15); } } # vim: tabstop=4 shiftwidth=4 noexpandtab autoindent softtabstop=4