From 465f8ed1b317afb1c7aefde04e53118a19be1a18 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Tue, 29 Jan 2013 21:44:24 +0100 Subject: Finished the factoring of localpart-related methods. --- lib/Fripost/Schema/Password.pm | 133 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 lib/Fripost/Schema/Password.pm (limited to 'lib/Fripost/Schema/Password.pm') diff --git a/lib/Fripost/Schema/Password.pm b/lib/Fripost/Schema/Password.pm new file mode 100644 index 0000000..cb2ac49 --- /dev/null +++ b/lib/Fripost/Schema/Password.pm @@ -0,0 +1,133 @@ +package Fripost::Schema::Password; + +use 5.010_000; +use strict; +use warnings; + +=head1 NAME + +Password.pm - Hash and generate passwords + +=cut + +our $VERSION = '0.02'; + +use Exporter 'import'; +use String::MkPasswd; +use Digest::SHA; +use MIME::Base64; + +our @EXPORT_OK = qw/hash pwgen/; + + +=head1 FUNCTIONS + +=over 4 + +=item B ([I]) + +SHA-1 hash the given password. I, if defined and not empty, is +used to salt the password. If I is not defined, a random 4 bytes +salt is used. If I is the empty string, the hash is not salted. + +The used scheme precedes the hash, so the output is ready to be inserted +in a LDAP entry for instance. + +=cut + +sub hash { + my ($pw, $salt) = @_; + + $salt //= &_make_salt(); + my $str = 'SHA'; + $str = 'SSHA' if &_is_salted( $salt ); + + { no strict "refs"; + $str = '{' .$str. '}' . + &_pad_base64( MIME::Base64::encode( + Digest::SHA::sha1( $pw.$salt ) . $salt, + '' ) ); + }; + return $str; +} + + +sub _is_salted { return ( not ( defined $_[0] ) or $_[0] ne '' ) }; + + +# Generate a (random) 4 bytes salt. We only generates 4 bytes here to +# match the other way to hash & salt passwords (`slappasswd' and the +# RoundCube passwords). +sub _make_salt { + my $len = 4; + my @bytes = (); + for my $i ( 1 .. $len ) { + push( @bytes, rand(255) ); + } + return pack( 'C*', @bytes ); +} + + +# 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 ) { + $b64_digest .= '='; + } + return $b64_digest; +} + + +=item B + +Generate a random password that complies to B's password +policy. + +=cut + +sub pwgen { + return String::MkPasswd::mkpasswd( + -length => 12, + -minnum => 2, + -minspecial => 1 + ); +} + +=back + +=cut + + +=head1 AUTHORS + +Stefan Kangas C<< >> + +Guilhem Moulin C<< >> + +=head1 BUGS + +Please report any bugs to C<< >> + +=head1 COPYRIGHT + +Copyright (c) 2010 Dominik Schulz (dominik.schulz@gauner.org). All rights reserved. + +Copyright 2010,2011 Stefan Kangas, all rights reserved. + +Copyright 2012,2013 Guilhem Moulin, all rights reserved. + +=head1 LICENSE + +This program is free software; you can redistribute it and/or modify it under +the same terms as Perl itself. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +=cut + +1; + +__END__ -- cgit v1.2.3