#!/usr/bin/perl -w # genpass - Flexible password generator # 2012-04-22 Created by Brian Katzung, Kappa Computer Solutions, LLC. # http://www.kappacs.com/ # # This software has been placed in the public domain by the author. # This software is supplied without warranty of merchantability or fitness # for any purpose. Use at your own risk. # # Parameters: # a[$min] Include (at least $min) lowercase letters # A[$min] Include (at least $min) uppercase letters # 0[$min] or d[$min] # Include (at least $min) decimal digits # h[$min] Include (at least $min) lowercase hexadecimal digits # H[$min] Include (at least $min) uppercase hexadecimal digits # '['$chars']'[$min] # Include (at least $min) from listed $chars (ranges OK) # $length Make passwords exactly $length characters long # $min-$max Make passwords between $min and $max characters long # x$count Generate $count passwords use strict; use List::Util 'shuffle'; # Minimum and maximum password length my ($min_len, $max_len) = (16, 16); my $num_pas = 1; # Number of passwords to generate my @sets; # Character sets to use for password composition ###################################################################### # Functions # # Return a random character from a character set # sub get_char { my ($set) = @_; return $set->[int(rand(scalar @$set))]; } # # Generate character set ranges # sub get_charset { my ($str) = @_; my @parts = split(/(.-.)/, $str); my @set = (); foreach (@parts) { if (/^(.)-(.)$/) { push(@set, $1 .. $2); } elsif (length) { push(@set, split(//)); } } return \@set; } # # Generate a password # sub gen_password { my @chars; my @combined = (); foreach (@sets) { for (my $i = 0; $i < $_->[0]; ++$i) { push(@chars, get_char($_->[1])); } push(@combined, @{$_->[1]}); } my $len = $min_len + int(rand($max_len - $min_len + 1)); while (@chars < $len) { push(@chars, get_char(\@combined)); } print shuffle(@chars), "\n"; } ###################################################################### # Main program # # Process arguments to choose character sets and quantities # foreach (@ARGV) { my $min; if (/^a(\d*)/) { # lower alpha $min = $1 || 1; push(@sets, [ $min, [ 'a' .. 'z' ] ]); } elsif (/^x(\d+)/) { # # of passwords $num_pas = $1; } elsif (/^A(\d*)/) { # upper alpha $min = 0 + "0$1"; push(@sets, [ $min, [ 'A' .. 'Z' ] ]); } elsif (/^[0d](\d*)/) { # numeric/decimal $min = 0 + "0$1"; push(@sets, [ $min, [ '0' .. '9' ] ]); } elsif (/^h(\d*)/) { # hexadecimal (lower) $min = 0 + "0$1"; push(@sets, [ $min, [ '0' .. '9', 'a' .. 'f' ] ]); } elsif (/^H(\d*)/) { # hexadecimal (upper) $min = 0 + "0$1"; push(@sets, [ $min, [ '0' .. '9', 'A' .. 'F' ] ]); } elsif (/^\[(.*)\](\d*)$/) { # specific charset $min = 0 + "0$2"; #push(@sets, [ $min, [ split(//, $1) ] ]); push(@sets, [ $min, get_charset($1) ]); } elsif (/^(\d+)(?:-(\d+))?/) { # min/max length $min_len = $1; $max_len = $2 || $min_len; } } # # Check usage # if (!@sets) { print "usage: $0 [a[min]] [A[min]] [0[min]] [h[min]] [H[min]]\n", "\t[[charset][min]] [min[-max]] [xcount]\n"; exit 1; } # # Generate passwords # for (my $i = 0; $i < $num_pas; ++$i) { gen_password(); } # END