1# easy en/decryption with DES/IDEA/Blowfish and some other ciphers 2# Mike Blazer <blazer@mail.nevalink.ru> 3 4package Crypt::CBCeasy; 5 6use 5.003; 7use Crypt::CBC; 8use Carp; 9use Symbol; 10 11use strict; 12no strict 'refs'; 13use vars qw($VERSION @DEFAULT_CIPHERS $LastCipher); 14 15$VERSION = '0.24'; 16@DEFAULT_CIPHERS = qw/DES IDEA Blowfish/; 17 18 19#-------------- 20sub useCBC { 21#-------------- 22# $from - handler (r), filename or just plain or encrypted text 23# $to - handler (r), or filename. If '' or undef sub returns $to-string 24 my ($key, $from, $to) = @_; 25 my $sub = (caller(1))[3]; # caller subroutine 26 my ($algorithm, $op) = $sub =~ /^(.*)::(.*)$/; 27#print "$algorithm, $op\n"; 28 $LastCipher = $algorithm; 29 30 my ($fhi, $fho, $fromFile, $INopened, $OUTopened, 31 $buffer, $fromStr, $toStr, $cipher); 32 33 croak "CBCeasy: source not defined\n" unless defined $from; 34 croak "CBCeasy: key not defined\n" unless defined $key; 35 croak "CBCeasy: I can do only `encipher' or `decipher'\n" 36 unless $op && $op =~ /^(encipher|decipher)$/i; 37 38 if ((UNIVERSAL::isa($from, 'GLOB') || # \*HANDLE 39 UNIVERSAL::isa(\$from,'GLOB') # *HANDLE 40 ) && defined fileno $from 41 ) { 42 43 $fhi = $from; 44 $fromFile = 1; 45 46 } elsif (-e $from && -r _) { # filename 47 $fhi = gensym; 48 $fromFile = 1; 49 $INopened = 1; 50 open ($fhi, $from) || croak "CBCeasy: file `$from' not found/readable\n"; 51 52 } elsif (-e $from && !-r _) { # filename 53 croak "CBCeasy: file `$from' not readable\n"; 54 55 } else { # stream itself in $from 56 } 57 58 $cipher = new Crypt::CBC($key, $algorithm); 59 $cipher->start(lc $op); 60 61 if ($fromFile) { 62 63 binmode $fhi; 64 # fails with too long chains 65 while (read($fhi,$buffer,4096)) { 66 $toStr .= $cipher->crypt($buffer); 67 } 68 $toStr .= $cipher->finish; 69 70 close $fhi if $INopened; 71 72 } else { 73 # fails with too long chains 74 while ($from) { 75 $fromStr = substr($from, 0, 4096); 76 substr($from, 0, 4096) = ''; 77 $toStr .= $cipher->crypt($fromStr); 78 } 79 $toStr .= $cipher->finish; 80 } 81 82 return $toStr unless $to; 83 84 if ((UNIVERSAL::isa($to, 'GLOB') || # \*HANDLE 85 UNIVERSAL::isa(\$to,'GLOB') # *HANDLE 86 ) && defined fileno $to 87 ) { 88 89 $fho = $to; 90 91 } else { # filename 92 $fho = gensym; 93 $OUTopened = 1; 94 open ($fho, ">$to") || croak "CBCeasy: can't write file `$to'\n"; 95 96 } 97 98 binmode $fho; 99 print $fho $toStr; 100 101 close $fho if $OUTopened; 102 103} 104 105#-------------- 106sub import { 107 my $pkg = shift; 108 109 for (@_ ? @_ : @DEFAULT_CIPHERS) { 110 eval <<"E_O_P" unless defined *{"$_\::encipher"}{CODE}; 111 112 sub $_\::encipher { useCBC(\@_) } 113 sub $_\::decipher { useCBC(\@_) } 114E_O_P 115 116 } 117} 118 1191; 120__END__ 121 122=head1 NAME 123 124Crypt::CBCeasy - Easy things make really easy with Crypt::CBC 125 126=head1 SYNOPSIS 127 128 use Crypt::CBCeasy; # !!! YOU can not 'require' this module !!! 129 130 IDEA::encipher($my_key, "plain-file", "crypted-file"); 131 132 $plain_text = DES::decipher($my_key, \*CRYPTO_FILE); 133 134 $crypted = Blowfish::encipher($my_key, \*PLAIN_SOCKET); 135 136=head1 ABSTRACT 137 138This module is just a helper for Crypt::CBC to make simple and 139usual jobs just one-liners. 140 141The current version of the module is available at CPAN. 142 143=head1 DESCRIPTION 144 145After you call this module as 146 147 use Crypt::CBCeasy IMPORT-LIST; 148 149it creates the C<encipher()> and C<decipher()> functions in all 150namespaces (packages) listed in the C<IMPORT-LIST>. 151 152Without the C<IMPORT-LIST> it creates these 2 functions 153in the B<DES::>, B<IDEA::> and 154B<Blowfish::> namespaces by default 155to stay compatible with the previous versions 156that were capable to handle only these 3 ciphers. 157 158You have to install C<Crypt::CBC> v. 1.22 or later to work with C<Blowfish>. 159 160Sure IDEA:: functions will work only if you have Crypt::IDEA installed, 161DES:: - if you have Crypt::DES, Blowfish:: - if you have Crypt::Blowfish 162and Crypt::CBC is version 1.22 or above etc. 163 164Here's the list of the ciphers that could be called via the 165C<Crypt::CBCeasy> interface today (in fact the same modules 166that are C<Crypt::CBC> compatible): 167 168 Cipher CPAN module 169 170 DES Crypt::DES 171 IDEA Crypt::IDEA 172 Blowfish Crypt::Blowfish 173 Twofish2 Crypt::Twofish2 174 DES_PP Crypt::DES_PP 175 Blowfish_PP Crypt::Blowfish_PP 176 Rijndael Crypt::Rijndael 177 TEA Crypt::TEA 178 179Note that cipher names are case sensitive in the C<IMPORT-LIST>, 180so "blowfish" will give an error. 181Type them exactly as they are written in the correspondent 182underlying modules. 183 184Both C<encipher()> and C<decipher()> functions take 3 parameters: 185 186 1 - en/decryption key 187 2 - source 188 3 - destination 189 190The sources could be: an existing file, a scalar (just a string that would be 191encrypted), an opened filehandle, any other object that inherits from the 192filehandle, for example IO::File or FileHandle object, and socket. 193 194Destinations could be any of the above except scalar, because we can not 195distinguish between scalar and output file name here. 196 197Well, it's easier to look at the examples: 198 199(C<$fh> vars here are IO::Handle, IO::File or FileHandle objects, 200variables of type "GLOB", "GLOB" refs or sockets) 201 202B<IDEA::encipher(> $my_key, "in-file", "out-file" B<);> 203 204B<IDEA::encipher(> $my_key, *IN, "out-file" B<);> 205 206B<IDEA::encipher(> $my_key, \*IN, "out-file" B<);> 207 208B<IDEA::encipher(> $my_key, $fh_in, "out-file" B<);> 209 210B<IDEA::encipher(> $my_key, "in-file", *OUT B<);> 211 212B<IDEA::encipher(> $my_key, "in-file", \*OUT B<);> 213 214B<IDEA::encipher(> $my_key, "in-file", $fh_out B<);> 215 216B<IDEA::encipher(> $my_key, *IN, *OUT B<);> 217 218B<IDEA::encipher(> $my_key, \*IN, \*OUT B<);> 219 220B<IDEA::encipher(> $my_key, $fh_in, $fh_out B<);> 221 222B<IDEA::encipher(> $my_key, $plain_text, "out-file" B<);> 223 224B<IDEA::encipher(> $my_key, $plain_text, *OUT B<);> 225 226B<IDEA::encipher(> $my_key, $plain_text, \*OUT B<);> 227 228B<IDEA::encipher(> $my_key, $plain_text, $fh_out B<);> 229 230any of the above will work and do what was expected. 231 232In addition there is a 2-argument version that returns it's result 233as scalar: 234 235$crypted_text = B<IDEA::encipher(> $my_key, $plain_text B<);> 236 237$crypted_text = B<IDEA::encipher(> $my_key, "in-file" B<);> 238 239$crypted_text = B<IDEA::encipher(> $my_key, *IN B<);> 240 241$crypted_text = B<IDEA::encipher(> $my_key, \*IN B<);> 242 243$crypted_text = B<IDEA::encipher(> $my_key, $fh B<);> 244 245All the same is possible for any of the ciphers in the C<IMPORT-LIST>. 246 247All functions croak on errors (such as "input file not found"), so 248if you want to trap errors use them inside the C<eval{}> block 249and check the C<$@>. 250 251 252Note that all filehandles are used in C<binmode> whether you claimed them 253C<binmode> or not. On Win32 for example this will result in CRLF's in 254$plain_text after 255 256 $plain_text = DES::decipher($my_key, "crypted_file"); 257 258if "crypted_file" was created by 259 260 DES::encipher($my_key, "text_file", "crypted_file"); 261 262If the filehandle was used before - it's your job to rewind it 263to the beginning and/or close. 264 265=head1 INSTALLATION 266 267As this is just a plain module no special installation is needed. Put it 268into the /Crypt subdirectory somewhere in your @INC. The standard 269 270 Makefile.PL 271 make 272 make test 273 make install 274 275procedure is provided. In addition 276 277 make html 278 279will produce the HTML-docs. 280 281This module requires 282 283Crypt::CBC by Lincoln Stein, lstein@cshl.org 284v.1.20 or later. 285 286one or more of 287 288Crypt::IDEA, Crypt::DES, Crypt::Blowfish, Crypt::Blowfish_PP, 289Crypt::Twofish2, Crypt::DES_PP or other Crypt::CBC compatible modules. 290 291=head1 CAVEATS 292 293This module has been created and tested in a Win95/98/2000Pro environment 294with Perl 5.004_02 and ActiveState ActivePerl build 618. 295I expect it to function correctly on other systems too. 296 297=head1 CHANGES 298 299 0.21 Mon Mar 6 07:28:41 2000 - first public release 300 301 0.22 Sun Feb 18 13:11:59 2001 302 A horrible BUG was found by Michael Drumheller <drumheller@alum.mit.edu> 303 In fact 0.21 was ALWAYS using DES despite of the desired cipher. 304 DAMN! 305 Fixed. 306 And the test is modified so that this will never happen again. 307 308 Now you can define the list of ciphers that are compatible 309 with Crypt::CBC in the import list. 310 You can not call this module with the "require" statement. This 311 is incompatible with the older versions. 312 313 0.23 Crypt::Rijndael 0.02 compatibility was approved. 314 Tests are some more complex now. 315 316 0.24 Crypt::TEA 1.01 by Abhijit Menon-Sen <ams@wiw.org> is checked 317 and approved. 318 319=head1 TODO 320 321Any suggestions are much appreciated. 322 323=head1 BUGS 324 325Please report. 326 327=head1 VERSION 328 329This man page documents "Crypt::CBCeasy" version 0.24 330 331February 18, 2001 332 333=head1 AUTHOR 334 335Mike Blazer, blazer@mail.nevalink.ru 336 337http://base.dux.ru/guest/fno/perl/ 338 339=head1 SEE ALSO 340 341Crypt::CBC 342 343=head1 COPYRIGHT 344 345Copyright (C) 2000-2001 Mike Blazer. 346 347This package is free software; you can redistribute it and/or 348modify it under the same terms as Perl itself. 349 350=cut 351 352