diff options
| author | Guilhem Moulin <guilhem.moulin@fripost.org> | 2012-04-15 16:32:19 +0200 | 
|---|---|---|
| committer | Guilhem Moulin <guilhem.moulin@fripost.org> | 2012-04-15 16:32:19 +0200 | 
| commit | b1fe11c6c9ae79bd8714ba7e627cff1665198fd4 (patch) | |
| tree | bc9582837922b4a84f03b10118fbb1647964f70d /lib/Fripost | |
| parent | 82f9c2a71b02c8b5580ae80e2e46e97b348b5b28 (diff) | |
Use S-SHA1 by default.
Diffstat (limited to 'lib/Fripost')
| -rwxr-xr-x | lib/Fripost/Password.pm | 96 | 
1 files changed, 86 insertions, 10 deletions
| diff --git a/lib/Fripost/Password.pm b/lib/Fripost/Password.pm index 038d835..595502d 100755 --- a/lib/Fripost/Password.pm +++ b/lib/Fripost/Password.pm @@ -9,24 +9,77 @@ Password.pm - Generate passwords  =cut -our $VERSION = '0.01'; +our $VERSION = '0.02'; -use Data::Dumper; -use Digest::MD5;  use Exporter;  use MIME::Base64; +use String::MkPasswd qw/mkpasswd/; -our @EXPORT = qw/smd5 make_salt/; +use constant { +    CLEARTEXT => 0, +    CRYPT     => 1, +    MD5       => 2, +    SHA1      => 3, +}; + +our @EXPORT = qw/hash CLEARTEXT CRYPT MD5 SHA1 mkpasswd/;  our @ISA = qw(Exporter); -sub smd5 { -    my $pw = shift; -    my $salt = shift || &make_salt(); -    return "{SMD5}" . pad_base64( MIME::Base64::encode( Digest::MD5::md5( $pw . $salt ) . $salt, '' ) ); + +# Hashes the given password using the given hashing function and salt. +# If the scheme is `undef', the best available one (currently SHA-1) is +# chosen. +# If `$salt' is the empty string, no salt is used (unless the scheme is +# CRYPT - since it requires salt). +# If `$salt' is `undef', the salt is automatically generated, using the +# subroutine `&make_salt' below. +sub hash ($$$) { + +    my ($h, $salt, $pw) = @_; +    $h //= SHA1; + +    # Treat the schemes that don't use Digest::.. separetely. +    if ( $h == CLEARTEXT ) { +        return $pw; +    } +    elsif ( $h == CRYPT ) { +        $salt = &make_salt() if not (defined $salt) or $salt eq ''; +        $salt = sprintf ( '$1$%.8s', MIME::Base64::encode( $salt ) ); +        return '{CRYPT}' . crypt( $pw, $salt ); +    } + +    $salt //= &make_salt(); +    my $hash_function; +    my $str; + +    if ( $h == MD5 ) { +        use Digest::MD5 qw /md5/; +        $hash_function = "Digest::MD5::md5"; +        $str = 'MD5'; +        $str = 'SMD5' if &is_salted( $salt ); +    } +    elsif ( $h == SHA1 ) { +        use Digest::SHA qw /sha1/; +        $hash_function = "Digest::SHA::sha1"; +        $str = 'SHA'; +        $str = 'SSHA' if &is_salted( $salt ); +    } +    else { +        die "Error: Unknown scheme `" .$h. "'.\n"; +    } + +    no strict "refs"; +    return '{' .$str. '}' . +        pad_base64( MIME::Base64::encode( &$hash_function( $pw . $salt ) . $salt +                                        , '' ) );  } +sub is_salted { return ( not ( defined $_[0] ) or $_[0] ne '' ) }; + + +# Generate (random) salt, with a (random) length of 23 to 31 bytes.  sub make_salt { -    my $len   = 8 + int( rand(8) ); +    my $len   = 31 - int( rand(8) );      my @bytes = ();      for my $i ( 1 .. $len ) {          push( @bytes, rand(255) ); @@ -34,6 +87,14 @@ sub make_salt {      return pack( 'C*', @bytes );  } +sub random_string { +    my ($len, $range) = @_; +    return join '', @$range[ map {rand $#$range} (1..$len) ]; +} + + +# Add trailing `='s to the input string to ensure its length is a +# multiple of 4.  sub pad_base64 {      my $b64_digest = shift;      while ( length($b64_digest) % 4 ) { @@ -42,10 +103,23 @@ sub pad_base64 {      return $b64_digest;  } -=head1 AUTHOR + +# Our policy for automatically generated passwords. +sub mkpasswd { +    return String::MkPasswd::mkpasswd( +        -length => 20, +        -minnum => 5, +        -minspecial => 3 +    ); +} + + +=head1 AUTHORS  Stefan Kangas C<< <skangas at skangas.se> >> +Guilhem Moulin C<< <guilhem at fripost.org> >> +  =head1 BUGS  Please report any bugs to C<< <skangas at skangas.se> >> @@ -56,6 +130,8 @@ Copyright (c) 2010 Dominik Schulz (dominik.schulz@gauner.org). All rights reserv  Copyright 2010,2011 Stefan Kangas, all rights reserved. +Copyright 2012 Guilhem Moulin, all rights reserved. +  =head1 LICENSE  This program is free software; you can redistribute it and/or modify it under | 
