Crypt-PasswdMD5-1.40000755001750001750 012222250412 13053 5ustar00ronron000000000000Crypt-PasswdMD5-1.40/Changelog.ini000444001750001750 345712222250412 15611 0ustar00ronron000000000000[Module] Name=Crypt::PasswdMD5 Changelog.Creator=Module::Metadata::Changes V 2.05 Changelog.Parser=Config::IniFiles V 2.78 [V 1.40] Date=2013-09-30T15:32:00 Comments= <. - Fabricate some version #s for this file. - Made Passwd.pm utf-8 so we can use Luis' proper name. - Clean up code formatting. - Clean up Makefile.PL. - Use fake (ASCII) ñ in Makefile.PL to keep Solaris happy. See RT#68478. - Clean up README. - Add Build.PL. - Add Changes and Changelog.ini. - Add META.*. - Adopt Test::More in t/basic.t. - Adopt 'use strict' and 'use warnings' to PasswdMD5.pm and t/basic.t. - Accept patch for new function random_md5_salt(), and tests, from kbrint@rufus.net. With thanx. See RT#37036. - Add xt/author/pod.t. EOT [V 1.30] Date=2004-02-17T11:21:38 Comments= <. - Initial release. EOT Crypt-PasswdMD5-1.40/Changes000444001750001750 304512222250412 14505 0ustar00ronron000000000000Revision history for Perl extension Crypt::PasswdMD5. 1.40 2013-09-30 15:32:00 - No code changes. - Maintenance by Ron Savage . - Fabricate some version #s for this file. - Made Passwd.pm utf-8 so we can use Luis' proper name. - Clean up code formatting. - Clean up Makefile.PL. - Use fake (ASCII) ñ in Makefile.PL to keep Solaris happy. See RT#68478. - Clean up README. - Add Build.PL. - Add Changes and Changelog.ini. - Add META.*. - Adopt Test::More in t/basic.t. - Adopt 'use strict' and 'use warnings' to PasswdMD5.pm and t/basic.t. - Accept patch for new function random_md5_salt(), and tests, from kbrint@rufus.net. With thanx. See RT#37036. - Add xt/author/pod.t. 1.30 2004-02-17 11:21:38 - luismunoz@cpan.org. - Modified the POD so that ABSTRACT can work. - Added usage example for apache_md5_crypt(). 1.20 2004-02-17 11:04:35 - luismunoz@cpan.org. - Added patch for random salts from John Peacock (Thanks John!). - De-MS-DOS-ified the file. - Replaced some '' with q// to make Emacs color highlighting happy. - Added CVS docs. - Completed the missing sections of the POD documentation. - Changed my email address to the Perl-related one for consistency. 1.10 2001-07-06 - luismunoz@cpan.org. - Use Digest::MD5 instead of the (obsolete) MD5. 1.09 2000-10-06 - wrowe@lnd.com. - Export apache_md5_crypt by default. 1.08 1999-04-02 - bryan@eai.com. - Added apache_md5_crypt to create a valid hash for use in .htpasswd files. 1.00 1998-07-10 - Luis E. Muñoz . - Initial release. Crypt-PasswdMD5-1.40/Makefile.PL000444001750001750 167412222250412 15172 0ustar00ronron000000000000use strict; use warnings; use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. use strict; use warnings; use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile ( ($] ge '5.005') ? ( AUTHOR => 'Luis E. Muñoz ', ABSTRACT => 'Provide interoperable MD5-based crypt() functions', ) : (), clean => { FILES => 'blib/* Makefile MANIFEST Crypt-PasswdMD5-*' }, dist => { COMPRESS => 'gzip', SUFFIX => 'gz' }, DISTNAME => 'Crypt-PasswdMD5', NAME => 'Crypt::PasswdMD5', LICENSE => 'perl', PL_FILES => {}, PREREQ_PM => { 'Digest::MD5' => 2.53, 'strict' => 0, 'Test::More' => 0.94, # 'Test::Pod' => 1.45, # Make it optional. See t/pod.t 'warnings' => 0, }, VERSION_FROM => 'lib/Crypt/PasswdMD5.pm', ); Crypt-PasswdMD5-1.40/README000444001750001750 255212222250412 14074 0ustar00ronron000000000000README file for Crypt::PasswdMD5. See also: CHANGES and Changelog.ini. Warning: WinZip 8.1 and 9.0 both contain an 'accidental' bug which stops them recognizing POSIX-style directory structures in valid tar files. You are better off using a reliable tool such as InfoZip: ftp://ftp.info-zip.org/pub/infozip/ 1 Installing from a Unix-like distro ------------------------------------ shell>gunzip Crypt-PasswdMD5-1.40.tgz shell>tar mxvf Crypt-PasswdMD5-1.40.tar On Unix-like systems, assuming you have installed Module::Build V 0.25+: shell>perl Build.PL shell>./Build shell>./Build test shell>./Build install On MS Windows-like systems, assuming you have installed Module::Build V 0.25+: shell>perl Build.PL shell>perl Build shell>perl Build test shell>perl Build install Alternately, without Module::Build, you do this: Note: 'make' on MS Windows-like systems may be called 'nmake' or 'dmake'. shell>perl Makefile.PL shell>make shell>make test shell>su (for Unix-like systems) shell>make install shell>exit (for Unix-like systems) On all systems: Run PasswdMD5.pm through your favourite pod2html translator. 2 Installing from an ActiveState distro --------------------------------------- shell>unzip Crypt-PasswdMD5-1.40.zip shell>ppm install --location=. Crypt-PasswdMD5 shell>del Crypt-PasswdMD5-1.40.ppd shell>del PPM-Crypt-PasswdMD5-1.40.tar.gz Crypt-PasswdMD5-1.40/META.yml000444001750001750 115512222250412 14463 0ustar00ronron000000000000--- abstract: 'Provide interoperable MD5-based crypt() functions' author: - 'Luis E. Muñoz ' build_requires: Test::More: 0.94 configure_requires: Module::Build: 0 dynamic_config: 1 generated_by: 'Module::Build version 0.4005, CPAN::Meta::Converter version 2.131560' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Crypt-PasswdMD5 provides: Crypt::PasswdMD5: file: lib/Crypt/PasswdMD5.pm version: 1.40 requires: Digest::MD5: 2.53 strict: 0 warnings: 0 resources: license: http://dev.perl.org/licenses/ version: 1.40 Crypt-PasswdMD5-1.40/MANIFEST000444001750001750 24412222250412 14321 0ustar00ronron000000000000Build.PL Changelog.ini Changes lib/Crypt/PasswdMD5.pm Makefile.PL MANIFEST This list of files META.json META.yml README t/basic.t t/random.salt.t xt/author/pod.t Crypt-PasswdMD5-1.40/Build.PL000444001750001750 151712222250412 14510 0ustar00ronron000000000000use strict; use warnings; use Module::Build; my $class = Module::Build->subclass(code => <<'EOF'); sub ACTION_authortest { my($self) = @_; $self->depends_on('build'); $self->depends_on('manifest'); $self->depends_on('distmeta'); $self->test_files( qw< t xt/author > ); $self->recursive_test_files(1); $self->depends_on('test'); return; } EOF $class -> new ( module_name => 'Crypt::PasswdMD5', license => 'perl', dist_abstract => 'Provide interoperable MD5-based crypt() functions', dist_author => 'Luis E. Muñoz ', build_requires => { 'Test::More' => 0.94, # 'Test::Pod' => 1.45, # Make it optional. See t/pod.t }, configure_requires => { 'Module::Build' => 0, }, requires => { 'Digest::MD5' => 2.53, 'strict' => 0, 'warnings' => 0, }, ) -> create_build_script(); Crypt-PasswdMD5-1.40/META.json000444001750001750 210512222250412 14627 0ustar00ronron000000000000{ "abstract" : "Provide interoperable MD5-based crypt() functions", "author" : [ "Luis E. Muñoz " ], "dynamic_config" : 1, "generated_by" : "Module::Build version 0.4005, CPAN::Meta::Converter version 2.131560", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Crypt-PasswdMD5", "prereqs" : { "build" : { "requires" : { "Test::More" : "0.94" } }, "configure" : { "requires" : { "Module::Build" : "0" } }, "runtime" : { "requires" : { "Digest::MD5" : "2.53", "strict" : "0", "warnings" : "0" } } }, "provides" : { "Crypt::PasswdMD5" : { "file" : "lib/Crypt/PasswdMD5.pm", "version" : "1.40" } }, "release_status" : "stable", "resources" : { "license" : [ "http://dev.perl.org/licenses/" ] }, "version" : "1.40" } Crypt-PasswdMD5-1.40/xt000755001750001750 012222250412 13506 5ustar00ronron000000000000Crypt-PasswdMD5-1.40/xt/author000755001750001750 012222250412 15010 5ustar00ronron000000000000Crypt-PasswdMD5-1.40/xt/author/pod.t000444001750001750 20412222250412 16070 0ustar00ronron000000000000use Test::More; eval "use Test::Pod 1.45"; plan skip_all => "Test::Pod 1.45 required for testing POD" if $@; all_pod_files_ok(); Crypt-PasswdMD5-1.40/t000755001750001750 012222250412 13316 5ustar00ronron000000000000Crypt-PasswdMD5-1.40/t/basic.t000444001750001750 162612222250412 14726 0ustar00ronron000000000000use strict; use warnings; use Test::More; # ------------------------------------------------ use_ok('Crypt::PasswdMD5'); my($phrase1) = "hello world\n"; my($stage1) = '$1$1234$BhY1eAOOs7IED4HLA5T5o.'; $|=1; ok(unix_md5_crypt($phrase1, '1234') eq $stage1, 'Hashing of a simple phrase + salt'); ok(unix_md5_crypt($phrase1, $stage1) eq $stage1, 'Rehash (check) of the phrase'); my($t) = unix_md5_crypt('', $$); ok(unix_md5_crypt('', $t) eq $t, 'Hashing/rehashing of the empty password'); $t = unix_md5_crypt('test4'); my($salt) = ($t =~ m/\$.+\$(.+)\$/); ok(unix_md5_crypt('test4', $salt) eq $t, 'Make sure null salt works'); # Warning: Do not remove the () around ($salt). $t = apache_md5_crypt('test5'); ($salt) = ($t =~ m/\$.+\$(.+)\$/); ok(apache_md5_crypt('test5', $salt) eq $t, 'And again with the Apache Variant'); ok($t =~ /^\$apr1\$/, '$t now has the correct value'); done_testing; Crypt-PasswdMD5-1.40/t/random.salt.t000444001750001750 71712222250412 16047 0ustar00ronron000000000000use strict; use warnings; use Crypt::PasswdMD5 'random_md5_salt'; use Test::More; # ------------------------------------------------ sub length_is { my $in = shift; my $out = shift; my $salt = random_md5_salt($in); ok($out == length($salt), "random_md5_salt(). Input: $in. Output length: $out"); } # End of length_is. # ------------------------------------------------ length_is($_, $_) for (1..8); length_is(0, 8); length_is(9, 8); done_testing; Crypt-PasswdMD5-1.40/lib000755001750001750 012222250412 13621 5ustar00ronron000000000000Crypt-PasswdMD5-1.40/lib/Crypt000755001750001750 012222250412 14722 5ustar00ronron000000000000Crypt-PasswdMD5-1.40/lib/Crypt/PasswdMD5.pm000444001750001750 1425712222250412 17215 0ustar00ronron000000000000package Crypt::PasswdMD5; use strict; use warnings; use Digest::MD5; use Exporter 'import'; our @EXPORT = qw/unix_md5_crypt apache_md5_crypt/; our @EXPORT_OK = (@EXPORT, 'random_md5_salt'); our $VERSION ='1.40'; # ------------------------------------------------ my($itoa64) = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; our($Magic) = q/$1$/; # Magic strings. Need 'our' because of local just below. my($max_salt_length) = 8; # ------------------------------------------------ sub apache_md5_crypt { # Change the Magic string to match the one used by Apache. local $Magic = q/$apr1$/; return unix_md5_crypt(@_); } # End of apache_md5_crypt. # ------------------------------------------------ sub random_md5_salt { my($len) = shift || $max_salt_length; my($salt) = ''; # Sanity check. $len = $max_salt_length unless ( ($len >= 1) and ($len <= $max_salt_length) ); $salt .= substr($itoa64,int(rand(64)),1) for (1..$len); return $salt; } # End of random_md5_salt. # ------------------------------------------------ sub to64 { my($v, $n) = @_; my($ret) = ''; while (--$n >= 0) { $ret .= substr($itoa64, $v & 0x3f, 1); $v >>= 6; } return $ret; } # End of to64. # ------------------------------------------------ sub unix_md5_crypt { my($pw, $salt) = @_; my($passwd); if (defined $salt) { $salt =~ s/^\Q$Magic//; # Take care of the magic string if present. $salt =~ s/^(.*)\$.*$/$1/; # Salt can have up to 8 chars... $salt = substr($salt, 0, 8); } else { $salt = random_md5_salt(); # In case no salt was proffered. } my($ctx) = Digest::MD5 -> new; # Here we start the calculation. $ctx -> add($pw); # Original password... $ctx -> add($Magic); # ...our magic string... $ctx -> add($salt); # ...the salt... my($final) = Digest::MD5 -> new; $final -> add($pw); $final -> add($salt); $final -> add($pw); $final = $final -> digest; for (my $pl = length($pw); $pl > 0; $pl -= 16) { $ctx -> add(substr($final, 0, $pl > 16 ? 16 : $pl) ); } # Now the 'weird' xform. for (my $i = length($pw); $i; $i >>= 1) { if ($i & 1) { $ctx -> add(pack('C', 0) ); } # This comes from the original version, where a # memset() is done to $final before this loop. else { $ctx -> add(substr($pw, 0, 1) ); } } $final = $ctx -> digest; # The following is supposed to make things run slower. # In perl, perhaps it'll be *really* slow! for (my $i = 0; $i < 1000; $i++) { my($ctx1) = Digest::MD5 -> new; if ($i & 1) { $ctx1 -> add($pw); } else { $ctx1 -> add(substr($final, 0, 16) ); } if ($i % 3) { $ctx1 -> add($salt); } if ($i % 7) { $ctx1 -> add($pw); } if ($i & 1) { $ctx1 -> add(substr($final, 0, 16) ); } else { $ctx1 -> add($pw); } $final = $ctx1 -> digest; } # Final xform $passwd = ''; $passwd .= to64(int(unpack('C', (substr($final, 0, 1) ) ) << 16) | int(unpack('C', (substr($final, 6, 1) ) ) << 8) | int(unpack('C', (substr($final, 12, 1) ) ) ), 4); $passwd .= to64(int(unpack('C', (substr($final, 1, 1) ) ) << 16) | int(unpack('C', (substr($final, 7, 1) ) ) << 8) | int(unpack('C', (substr($final, 13, 1) ) ) ), 4); $passwd .= to64(int(unpack('C', (substr($final, 2, 1) ) ) << 16) | int(unpack('C', (substr($final, 8, 1) ) ) << 8) | int(unpack('C', (substr($final, 14, 1) ) ) ), 4); $passwd .= to64(int(unpack('C', (substr($final, 3, 1) ) ) << 16) | int(unpack('C', (substr($final, 9, 1) ) ) << 8) | int(unpack('C', (substr($final, 15, 1) ) ) ), 4); $passwd .= to64(int(unpack('C', (substr($final, 4, 1) ) ) << 16) | int(unpack('C', (substr($final, 10, 1) ) ) << 8) | int(unpack('C', (substr($final, 5, 1) ) ) ), 4); $passwd .= to64(int(unpack('C', substr($final, 11, 1) ) ), 2); return $Magic . $salt . q/$/ . $passwd; } # End of unix_md5_crypt. # ------------------------------------------------ 1; =pod =encoding utf-8 =head1 NAME Crypt::PasswdMD5 - Provide interoperable MD5-based crypt() functions =head1 SYNOPSIS use strict; use warnings; use Crypt::PasswdMD5; my($password) = 'seekrit'; my($salt) = 'pepperoni'; my($unix_crypted) = unix_md5_crypt($password, $salt); my($apache_crypted) = apache_md5_crypt($password, $salt); Or: use strict; use warnings; use Crypt::PasswdMD5 'random_md5_salt'; my($length) = 7; my($salt_1) = random_md5_salt($length); my($salt_2) = random_md5_salt(); # Default to $length == 8. =head1 DESCRIPTION C provides a function compatible with Apache's C<.htpasswd> files. This was contributed by Bryan Hart . This function is exported by default. The C provides a crypt()-compatible interface to the rather new MD5-based crypt() function found in modern operating systems. It's based on the implementation found on FreeBSD 2.2.[56]-RELEASE. This function is also exported by default. For both functions, if a salt value is not supplied, a random salt will be generated, using the function random_md5_salt(). This function is not exported by default. =head1 LICENSE AND WARRANTY This code and all accompanying software comes with NO WARRANTY. You use it at your own risk. This code and all accompanying software can be used freely under the same terms as Perl itself. =head1 METHODS =head2 apache_md5_crypt($password, $salt) This sets a magic variable, and then passes all the calling parameters to L. Returns an encrypted version of the given password. Basically, it's a very poor choice for anything other than password authentication. =head2 random_md5_salt([$length]) Here, [] indicate an optional parameter. Returns a random salt of the given length. The maximum length is 8. If C<$length> is omitted, it defaults to 8. =head2 unix_md5_crypt($password, $salt) Returns an encrypted version of the given password. Basically, it's a very poor choice for anything other than password authentication. =head1 SUPPORT Bugs should be reported via the CPAN bug tracker at L =head1 AUTHOR Luis E. Muñoz . Maintenance by Ron Savage as of V 1.40. =cut