releasing/cbrtools/perl/Digest/Perl/MD5.pm
changeset 607 378360dbbdba
parent 602 3145852acc89
equal deleted inserted replaced
591:22486c9c7b15 607:378360dbbdba
       
     1 # This library is free software; you can redistribute it and/or
       
     2 # modify it under the same terms as Perl itself.
       
     3 #
       
     4 #  Copyright 2000 Christian Lackas, Imperia Software Solutions
       
     5 #  Copyright 1998-1999 Gisle Aas.
       
     6 #  Copyright 1995-1996 Neil Winton.
       
     7 #  Copyright 1991-1992 RSA Data Security, Inc.
       
     8 
       
     9 #!/usr/local/bin/perl -w
       
    10 #$Id: MD5.pm,v 1.16 2000/09/19 22:19:31 lackas Exp $
       
    11 
       
    12 package Digest::Perl::MD5;
       
    13 use strict;
       
    14 use integer;
       
    15 use Exporter;
       
    16 use vars qw($VERSION @ISA @EXPORTER @EXPORT_OK);
       
    17 
       
    18 @EXPORT_OK = qw(md5 md5_hex md5_base64);
       
    19 
       
    20 @ISA = 'Exporter';
       
    21 $VERSION = '1.5';
       
    22 
       
    23 # I-Vektor
       
    24 sub A() { 0x67_45_23_01 }
       
    25 sub B() { 0xef_cd_ab_89 }
       
    26 sub C() { 0x98_ba_dc_fe }
       
    27 sub D() { 0x10_32_54_76 }
       
    28 
       
    29 # for internal use
       
    30 sub MAX() { 0xFFFFFFFF }
       
    31 
       
    32 # padd a message to a multiple of 64
       
    33 sub padding($) {
       
    34     my $l = length (my $msg = shift() . chr(128));    
       
    35     $msg .= "\0" x (($l%64<=56?56:120)-$l%64);
       
    36     $l = ($l-1)*8;
       
    37     $msg .= pack 'VV', $l & MAX , ($l >> 16 >> 16);
       
    38 }
       
    39 
       
    40 
       
    41 sub rotate_left($$) {
       
    42 	($_[0] << $_[1]) | (( $_[0] >> (32 - $_[1])  )  & ((1 << $_[1]) - 1));
       
    43 }
       
    44 
       
    45 sub gen_code {
       
    46   # Discard upper 32 bits on 64 bit archs.
       
    47   my $MSK = ((1 << 16) << 16) ? ' & ' . MAX : '';
       
    48   my %f = (
       
    49 	FF => "X0=rotate_left((X3^(X1&(X2^X3)))+X0+X4+X6$MSK,X5)+X1$MSK;",
       
    50 	GG => "X0=rotate_left((X2^(X3&(X1^X2)))+X0+X4+X6$MSK,X5)+X1$MSK;",
       
    51 	HH => "X0=rotate_left((X1^X2^X3)+X0+X4+X6$MSK,X5)+X1$MSK;",
       
    52 	II => "X0=rotate_left((X2^(X1|(~X3)))+X0+X4+X6$MSK,X5)+X1$MSK;",
       
    53   );
       
    54 
       
    55   my %s = (  # shift lengths
       
    56 	S11 => 7, S12 => 12, S13 => 17, S14 => 22, S21 => 5, S22 => 9, S23 => 14,
       
    57 	S24 => 20, S31 => 4, S32 => 11, S33 => 16, S34 => 23, S41 => 6, S42 => 10,
       
    58 	S43 => 15, S44 => 21
       
    59   );
       
    60 
       
    61   my $insert = "";
       
    62   while(<DATA>) {
       
    63 	chomp;
       
    64 	next unless /^[FGHI]/;
       
    65 	my ($func,@x) = split /,/;
       
    66 	my $c = $f{$func};
       
    67 	$c =~ s/X(\d)/$x[$1]/g;
       
    68 	$c =~ s/(S\d{2})/$s{$1}/;
       
    69         $c =~ s/^(.*)=rotate_left\((.*),(.*)\)\+(.*)$//;
       
    70 
       
    71 	$c = "\$r = $2;
       
    72         $1 = ((\$r << $3) | ((\$r >> (32 - $3))  & ((1 << $3) - 1))) + $4";
       
    73 	$insert .= "\t$c\n";
       
    74   }
       
    75   
       
    76   my $dump = '
       
    77   sub round {
       
    78 	my ($a,$b,$c,$d) = @_[0 .. 3];
       
    79 	my $r;
       
    80 
       
    81 	' . $insert . '
       
    82 	$_[0]+$a' . $MSK . ', $_[1]+$b ' . $MSK . 
       
    83         ', $_[2]+$c' . $MSK . ', $_[3]+$d' . $MSK . ';
       
    84   }';
       
    85   eval $dump;
       
    86 }
       
    87 
       
    88 gen_code();
       
    89 
       
    90 
       
    91 # object part of this module
       
    92 sub new {
       
    93 	my $class = shift;
       
    94 	bless {}, ref($class) || $class;
       
    95 }
       
    96 
       
    97 sub reset {
       
    98 	my $self = shift;
       
    99 	delete $self->{data};
       
   100 	$self
       
   101 }
       
   102 
       
   103 sub add(@) {
       
   104 	my $self = shift;
       
   105 	$self->{data} .= join'', @_;
       
   106 	$self
       
   107 }
       
   108 
       
   109 sub addfile {
       
   110   	my ($self,$fh) = @_;
       
   111 	if (!ref($fh) && ref(\$fh) ne "GLOB") {
       
   112 	    require Symbol;
       
   113 	    $fh = Symbol::qualify($fh, scalar caller);
       
   114 	}
       
   115 	$self->{data} .= do{local$/;<$fh>};
       
   116 	$self
       
   117 }
       
   118 
       
   119 sub digest {
       
   120 	md5(shift->{data})
       
   121 }
       
   122 
       
   123 sub hexdigest {
       
   124 	md5_hex(shift->{data})
       
   125 }
       
   126 
       
   127 sub b64digest {
       
   128 	md5_base64(shift->{data})
       
   129 }
       
   130 
       
   131 sub md5(@) {
       
   132 	my $message = padding(join'',@_);
       
   133 	my ($a,$b,$c,$d) = (A,B,C,D);
       
   134 	my $i;
       
   135 	for $i (0 .. (length $message)/64-1) {
       
   136 		my @X = unpack 'V16', substr $message,$i*64,64;	
       
   137 		($a,$b,$c,$d) = round($a,$b,$c,$d,@X);
       
   138 	}
       
   139 	pack 'V4',$a,$b,$c,$d;
       
   140 }
       
   141 
       
   142 
       
   143 sub md5_hex(@) {  
       
   144   unpack 'H*', &md5;
       
   145 }
       
   146 
       
   147 sub md5_base64(@) {
       
   148   encode_base64(&md5);
       
   149 }
       
   150 
       
   151 
       
   152 sub encode_base64 ($) {
       
   153     my $res;
       
   154     while ($_[0] =~ /(.{1,45})/gs) {
       
   155 	$res .= substr pack('u', $1), 1;
       
   156 	chop $res;
       
   157     }
       
   158     $res =~ tr|` -_|AA-Za-z0-9+/|;#`
       
   159     chop $res;chop $res;
       
   160     $res;
       
   161 }
       
   162 
       
   163 1;
       
   164 
       
   165 =head1 NAME
       
   166 
       
   167 Digest::MD5::Perl - Perl implementation of Ron Rivests MD5 Algorithm
       
   168 
       
   169 =head1 DISCLAIMER
       
   170 
       
   171 This is B<not> an interface (like C<Digest::MD5>) but a Perl implementation of MD5.
       
   172 It is written in perl only and because of this it is slow but it works without C-Code.
       
   173 You should use C<Digest::MD5> instead of this module if it is available.
       
   174 This module is only usefull for
       
   175 
       
   176 =over 4
       
   177 
       
   178 =item
       
   179 
       
   180 computers where you cannot install C<Digest::MD5> (e.g. lack of a C-Compiler)
       
   181 
       
   182 =item
       
   183 
       
   184 encrypting only small amounts of data (less than one million bytes). I use it to
       
   185 hash passwords.
       
   186 
       
   187 =item
       
   188 
       
   189 educational purposes
       
   190 
       
   191 =back
       
   192 
       
   193 =head1 SYNOPSIS
       
   194 
       
   195  # Functional style
       
   196  use Digest::MD5  qw(md5 md5_hex md5_base64);
       
   197 
       
   198  $hash = md5 $data;
       
   199  $hash = md5_hex $data;
       
   200  $hash = md5_base64 $data;
       
   201     
       
   202 
       
   203  # OO style
       
   204  use Digest::MD5;
       
   205 
       
   206  $ctx = Digest::MD5->new;
       
   207 
       
   208  $ctx->add($data);
       
   209  $ctx->addfile(*FILE);
       
   210 
       
   211  $digest = $ctx->digest;
       
   212  $digest = $ctx->hexdigest;
       
   213  $digest = $ctx->b64digest;
       
   214 
       
   215 =head1 DESCRIPTION
       
   216 
       
   217 This modules has the same interface as the much faster C<Digest::MD5>. So you can
       
   218 easily exchange them, e.g.
       
   219 
       
   220 	BEGIN {
       
   221 	  eval {
       
   222 	    require Digest::MD5;
       
   223 	    import Digest::MD5 'md5_hex'
       
   224 	  };
       
   225 	  if ($@) { # ups, no Digest::MD5
       
   226 	    require Digest::Perl::MD5;
       
   227 	    import Digest::Perl::MD5 'md5_hex'
       
   228 	  }		
       
   229 	}
       
   230 
       
   231 If the C<Digest::MD5> module is available it is used and if not you take
       
   232 C<Digest::Perl::MD5>.
       
   233 
       
   234 You can also install the Perl part of Digest::MD5 together with Digest::Perl::MD5
       
   235 and use Digest::MD5 as normal, it falls back to Digest::Perl::MD5 if it
       
   236 cannot load its object files.
       
   237 
       
   238 For a detailed Documentation see the C<Digest::MD5> module.
       
   239 
       
   240 =head1 EXAMPLES
       
   241 
       
   242 The simplest way to use this library is to import the md5_hex()
       
   243 function (or one of its cousins):
       
   244 
       
   245     use Digest::Perl::MD5 'md5_hex';
       
   246     print 'Digest is ', md5_hex('foobarbaz'), "\n";
       
   247 
       
   248 The above example would print out the message
       
   249 
       
   250     Digest is 6df23dc03f9b54cc38a0fc1483df6e21
       
   251 
       
   252 provided that the implementation is working correctly.  The same
       
   253 checksum can also be calculated in OO style:
       
   254 
       
   255     use Digest::MD5;
       
   256     
       
   257     $md5 = Digest::MD5->new;
       
   258     $md5->add('foo', 'bar');
       
   259     $md5->add('baz');
       
   260     $digest = $md5->hexdigest;
       
   261     
       
   262     print "Digest is $digest\n";
       
   263 
       
   264 =head1 LIMITATIONS
       
   265 
       
   266 This implementation of the MD5 algorithm has some limitations:
       
   267 
       
   268 =over 4
       
   269 
       
   270 =item
       
   271 
       
   272 It's slow, very slow. I've done my very best but Digest::MD5 is still about 135 times faster.
       
   273 You can only encrypt Data up to one million bytes in an acceptable time. But it's very usefull
       
   274 for encrypting small amounts of data like passwords.
       
   275 
       
   276 =item
       
   277 
       
   278 You can only encrypt up to 2^32 bits = 512 MB on 32bit archs. You should use C<Digest::MD5>
       
   279 for those amounts of data.
       
   280 
       
   281 =item
       
   282 
       
   283 C<Digest::Perl::MD5> loads all data to encrypt into memory. This is a todo.
       
   284 
       
   285 =back
       
   286 
       
   287 =head1 SEE ALSO
       
   288 
       
   289 L<Digest::MD5>
       
   290 
       
   291 L<md5sum(1)>
       
   292 
       
   293 RFC 1321
       
   294 
       
   295 =head1 COPYRIGHT
       
   296 
       
   297 This library is free software; you can redistribute it and/or
       
   298 modify it under the same terms as Perl itself.
       
   299 
       
   300  Copyright 2000 Christian Lackas, Imperia Software Solutions
       
   301  Copyright 1998-1999 Gisle Aas.
       
   302  Copyright 1995-1996 Neil Winton.
       
   303  Copyright 1991-1992 RSA Data Security, Inc.
       
   304 
       
   305 The MD5 algorithm is defined in RFC 1321. The basic C code
       
   306 implementing the algorithm is derived from that in the RFC and is
       
   307 covered by the following copyright:
       
   308 
       
   309 =over 4
       
   310 
       
   311 =item
       
   312 
       
   313 Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
       
   314 rights reserved.
       
   315 
       
   316 License to copy and use this software is granted provided that it
       
   317 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
       
   318 Algorithm" in all material mentioning or referencing this software
       
   319 or this function.
       
   320 
       
   321 License is also granted to make and use derivative works provided
       
   322 that such works are identified as "derived from the RSA Data
       
   323 Security, Inc. MD5 Message-Digest Algorithm" in all material
       
   324 mentioning or referencing the derived work.
       
   325 
       
   326 RSA Data Security, Inc. makes no representations concerning either
       
   327 the merchantability of this software or the suitability of this
       
   328 software for any particular purpose. It is provided "as is"
       
   329 without express or implied warranty of any kind.
       
   330 
       
   331 These notices must be retained in any copies of any part of this
       
   332 documentation and/or software.
       
   333 
       
   334 =back
       
   335 
       
   336 This copyright does not prohibit distribution of any version of Perl
       
   337 containing this extension under the terms of the GNU or Artistic
       
   338 licenses.
       
   339 
       
   340 =head1 AUTHORS
       
   341 
       
   342 The original MD5 interface was written by Neil Winton
       
   343 (C<N.Winton@axion.bt.co.uk>).
       
   344 
       
   345 C<Digest::MD5> was made by Gisle Aas <gisle@aas.no> (I took his Interface
       
   346 and part of the documentation)
       
   347 
       
   348 Thanks to Guido Flohr for his 'use integer'-hint.
       
   349 
       
   350 This release was made by Christian Lackas <delta@clackas.de>.
       
   351 
       
   352 =cut
       
   353 
       
   354 __DATA__
       
   355 FF,$a,$b,$c,$d,$_[4],7,0xd76aa478,/* 1 */
       
   356 FF,$d,$a,$b,$c,$_[5],12,0xe8c7b756,/* 2 */
       
   357 FF,$c,$d,$a,$b,$_[6],17,0x242070db,/* 3 */
       
   358 FF,$b,$c,$d,$a,$_[7],22,0xc1bdceee,/* 4 */
       
   359 FF,$a,$b,$c,$d,$_[8],7,0xf57c0faf,/* 5 */
       
   360 FF,$d,$a,$b,$c,$_[9],12,0x4787c62a,/* 6 */
       
   361 FF,$c,$d,$a,$b,$_[10],17,0xa8304613,/* 7 */
       
   362 FF,$b,$c,$d,$a,$_[11],22,0xfd469501,/* 8 */
       
   363 FF,$a,$b,$c,$d,$_[12],7,0x698098d8,/* 9 */
       
   364 FF,$d,$a,$b,$c,$_[13],12,0x8b44f7af,/* 10 */
       
   365 FF,$c,$d,$a,$b,$_[14],17,0xffff5bb1,/* 11 */
       
   366 FF,$b,$c,$d,$a,$_[15],22,0x895cd7be,/* 12 */
       
   367 FF,$a,$b,$c,$d,$_[16],7,0x6b901122,/* 13 */
       
   368 FF,$d,$a,$b,$c,$_[17],12,0xfd987193,/* 14 */
       
   369 FF,$c,$d,$a,$b,$_[18],17,0xa679438e,/* 15 */
       
   370 FF,$b,$c,$d,$a,$_[19],22,0x49b40821,/* 16 */ 
       
   371 GG,$a,$b,$c,$d,$_[5],5,0xf61e2562,/* 17 */
       
   372 GG,$d,$a,$b,$c,$_[10],9,0xc040b340,/* 18 */
       
   373 GG,$c,$d,$a,$b,$_[15],14,0x265e5a51,/* 19 */
       
   374 GG,$b,$c,$d,$a,$_[4],20,0xe9b6c7aa,/* 20 */
       
   375 GG,$a,$b,$c,$d,$_[9],5,0xd62f105d,/* 21 */
       
   376 GG,$d,$a,$b,$c,$_[14],9,0x2441453,/* 22 */
       
   377 GG,$c,$d,$a,$b,$_[19],14,0xd8a1e681,/* 23 */
       
   378 GG,$b,$c,$d,$a,$_[8],20,0xe7d3fbc8,/* 24 */
       
   379 GG,$a,$b,$c,$d,$_[13],5,0x21e1cde6,/* 25 */
       
   380 GG,$d,$a,$b,$c,$_[18],9,0xc33707d6,/* 26 */
       
   381 GG,$c,$d,$a,$b,$_[7],14,0xf4d50d87,/* 27 */
       
   382 GG,$b,$c,$d,$a,$_[12],20,0x455a14ed,/* 28 */
       
   383 GG,$a,$b,$c,$d,$_[17],5,0xa9e3e905,/* 29 */
       
   384 GG,$d,$a,$b,$c,$_[6],9,0xfcefa3f8,/* 30 */
       
   385 GG,$c,$d,$a,$b,$_[11],14,0x676f02d9,/* 31 */
       
   386 GG,$b,$c,$d,$a,$_[16],20,0x8d2a4c8a,/* 32 */
       
   387 HH,$a,$b,$c,$d,$_[9],4,0xfffa3942,/* 33 */
       
   388 HH,$d,$a,$b,$c,$_[12],11,0x8771f681,/* 34 */
       
   389 HH,$c,$d,$a,$b,$_[15],16,0x6d9d6122,/* 35 */
       
   390 HH,$b,$c,$d,$a,$_[18],23,0xfde5380c,/* 36 */
       
   391 HH,$a,$b,$c,$d,$_[5],4,0xa4beea44,/* 37 */
       
   392 HH,$d,$a,$b,$c,$_[8],11,0x4bdecfa9,/* 38 */
       
   393 HH,$c,$d,$a,$b,$_[11],16,0xf6bb4b60,/* 39 */
       
   394 HH,$b,$c,$d,$a,$_[14],23,0xbebfbc70,/* 40 */
       
   395 HH,$a,$b,$c,$d,$_[17],4,0x289b7ec6,/* 41 */
       
   396 HH,$d,$a,$b,$c,$_[4],11,0xeaa127fa,/* 42 */
       
   397 HH,$c,$d,$a,$b,$_[7],16,0xd4ef3085,/* 43 */
       
   398 HH,$b,$c,$d,$a,$_[10],23,0x4881d05,/* 44 */
       
   399 HH,$a,$b,$c,$d,$_[13],4,0xd9d4d039,/* 45 */
       
   400 HH,$d,$a,$b,$c,$_[16],11,0xe6db99e5,/* 46 */
       
   401 HH,$c,$d,$a,$b,$_[19],16,0x1fa27cf8,/* 47 */
       
   402 HH,$b,$c,$d,$a,$_[6],23,0xc4ac5665,/* 48 */
       
   403 II,$a,$b,$c,$d,$_[4],6,0xf4292244,/* 49 */
       
   404 II,$d,$a,$b,$c,$_[11],10,0x432aff97,/* 50 */
       
   405 II,$c,$d,$a,$b,$_[18],15,0xab9423a7,/* 51 */
       
   406 II,$b,$c,$d,$a,$_[9],21,0xfc93a039,/* 52 */
       
   407 II,$a,$b,$c,$d,$_[16],6,0x655b59c3,/* 53 */
       
   408 II,$d,$a,$b,$c,$_[7],10,0x8f0ccc92,/* 54 */
       
   409 II,$c,$d,$a,$b,$_[14],15,0xffeff47d,/* 55 */
       
   410 II,$b,$c,$d,$a,$_[5],21,0x85845dd1,/* 56 */
       
   411 II,$a,$b,$c,$d,$_[12],6,0x6fa87e4f,/* 57 */
       
   412 II,$d,$a,$b,$c,$_[19],10,0xfe2ce6e0,/* 58 */
       
   413 II,$c,$d,$a,$b,$_[10],15,0xa3014314,/* 59 */
       
   414 II,$b,$c,$d,$a,$_[17],21,0x4e0811a1,/* 60 */
       
   415 II,$a,$b,$c,$d,$_[8],6,0xf7537e82,/* 61 */
       
   416 II,$d,$a,$b,$c,$_[15],10,0xbd3af235,/* 62 */
       
   417 II,$c,$d,$a,$b,$_[6],15,0x2ad7d2bb,/* 63 */
       
   418 II,$b,$c,$d,$a,$_[13],21,0xeb86d391,/* 64 */