Crypt-CBCeasy
view release on metacpan or search on metacpan
# easy en/decryption with DES/IDEA/Blowfish and some other ciphers
# Mike Blazer <blazer@mail.nevalink.ru>
package Crypt::CBCeasy;
use 5.003;
use Crypt::CBC;
use Carp;
use Symbol;
use strict;
no strict 'refs';
use vars qw($VERSION @DEFAULT_CIPHERS $LastCipher);
$VERSION = '0.24';
@DEFAULT_CIPHERS = qw/DES IDEA Blowfish/;
#--------------
sub useCBC {
#--------------
# $from - handler (r), filename or just plain or encrypted text
# $to - handler (r), or filename. If '' or undef sub returns $to-string
my ($key, $from, $to) = @_;
my $sub = (caller(1))[3]; # caller subroutine
my ($algorithm, $op) = $sub =~ /^(.*)::(.*)$/;
#print "$algorithm, $op\n";
$LastCipher = $algorithm;
my ($fhi, $fho, $fromFile, $INopened, $OUTopened,
$buffer, $fromStr, $toStr, $cipher);
croak "CBCeasy: source not defined\n" unless defined $from;
croak "CBCeasy: key not defined\n" unless defined $key;
croak "CBCeasy: I can do only `encipher' or `decipher'\n"
unless $op && $op =~ /^(encipher|decipher)$/i;
if ((UNIVERSAL::isa($from, 'GLOB') || # \*HANDLE
UNIVERSAL::isa(\$from,'GLOB') # *HANDLE
) && defined fileno $from
) {
$fhi = $from;
$fromFile = 1;
} elsif (-e $from && -r _) { # filename
$fhi = gensym;
$fromFile = 1;
$INopened = 1;
open ($fhi, $from) || croak "CBCeasy: file `$from' not found/readable\n";
} elsif (-e $from && !-r _) { # filename
croak "CBCeasy: file `$from' not readable\n";
} else { # stream itself in $from
}
$cipher = new Crypt::CBC($key, $algorithm);
$cipher->start(lc $op);
if ($fromFile) {
binmode $fhi;
# fails with too long chains
while (read($fhi,$buffer,4096)) {
$toStr .= $cipher->crypt($buffer);
}
$toStr .= $cipher->finish;
if ((UNIVERSAL::isa($to, 'GLOB') || # \*HANDLE
UNIVERSAL::isa(\$to,'GLOB') # *HANDLE
) && defined fileno $to
) {
$fho = $to;
} else { # filename
$fho = gensym;
$OUTopened = 1;
open ($fho, ">$to") || croak "CBCeasy: can't write file `$to'\n";
}
binmode $fho;
print $fho $toStr;
close $fho if $OUTopened;
}
#--------------
sub import {
my $pkg = shift;
for (@_ ? @_ : @DEFAULT_CIPHERS) {
eval <<"E_O_P" unless defined *{"$_\::encipher"}{CODE};
sub $_\::encipher { useCBC(\@_) }
sub $_\::decipher { useCBC(\@_) }
E_O_P
}
}
1;
__END__
=head1 NAME
Crypt::CBCeasy - Easy things make really easy with Crypt::CBC
=head1 SYNOPSIS
use Crypt::CBCeasy; # !!! YOU can not 'require' this module !!!
IDEA::encipher($my_key, "plain-file", "crypted-file");
$plain_text = DES::decipher($my_key, \*CRYPTO_FILE);
$crypted = Blowfish::encipher($my_key, \*PLAIN_SOCKET);
=head1 ABSTRACT
This module is just a helper for Crypt::CBC to make simple and
usual jobs just one-liners.
The current version of the module is available at CPAN.
=head1 DESCRIPTION
After you call this module as
use Crypt::CBCeasy IMPORT-LIST;
it creates the C<encipher()> and C<decipher()> functions in all
namespaces (packages) listed in the C<IMPORT-LIST>.
Without the C<IMPORT-LIST> it creates these 2 functions
in the B<DES::>, B<IDEA::> and
B<Blowfish::> namespaces by default
to stay compatible with the previous versions
that were capable to handle only these 3 ciphers.
You have to install C<Crypt::CBC> v. 1.22 or later to work with C<Blowfish>.
Sure IDEA:: functions will work only if you have Crypt::IDEA installed,
DES:: - if you have Crypt::DES, Blowfish:: - if you have Crypt::Blowfish
and Crypt::CBC is version 1.22 or above etc.
Here's the list of the ciphers that could be called via the
C<Crypt::CBCeasy> interface today (in fact the same modules
that are C<Crypt::CBC> compatible):
Cipher CPAN module
DES Crypt::DES
IDEA Crypt::IDEA
Blowfish Crypt::Blowfish
Twofish2 Crypt::Twofish2
DES_PP Crypt::DES_PP
Blowfish_PP Crypt::Blowfish_PP
Rijndael Crypt::Rijndael
make install
procedure is provided. In addition
make html
will produce the HTML-docs.
This module requires
Crypt::CBC by Lincoln Stein, lstein@cshl.org
v.1.20 or later.
one or more of
Crypt::IDEA, Crypt::DES, Crypt::Blowfish, Crypt::Blowfish_PP,
Crypt::Twofish2, Crypt::DES_PP or other Crypt::CBC compatible modules.
=head1 CAVEATS
This module has been created and tested in a Win95/98/2000Pro environment
with Perl 5.004_02 and ActiveState ActivePerl build 618.
I expect it to function correctly on other systems too.
=head1 CHANGES
0.21 Mon Mar 6 07:28:41 2000 - first public release
0.22 Sun Feb 18 13:11:59 2001
A horrible BUG was found by Michael Drumheller <drumheller@alum.mit.edu>
In fact 0.21 was ALWAYS using DES despite of the desired cipher.
DAMN!
Fixed.
And the test is modified so that this will never happen again.
Now you can define the list of ciphers that are compatible
with Crypt::CBC in the import list.
You can not call this module with the "require" statement. This
is incompatible with the older versions.
0.23 Crypt::Rijndael 0.02 compatibility was approved.
Tests are some more complex now.
0.24 Crypt::TEA 1.01 by Abhijit Menon-Sen <ams@wiw.org> is checked
and approved.
=head1 TODO
Any suggestions are much appreciated.
=head1 BUGS
Please report.
=head1 VERSION
This man page documents "Crypt::CBCeasy" version 0.24
February 18, 2001
=head1 AUTHOR
Mike Blazer, blazer@mail.nevalink.ru
http://base.dux.ru/guest/fno/perl/
=head1 SEE ALSO
Crypt::CBC
=head1 COPYRIGHT
Copyright (C) 2000-2001 Mike Blazer.
This package is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=cut
Revision history for Perl extension Crypt::CBCeasy.
0.21 Mon Mar 6 07:28:41 2000
- first public release
0.22 Sun Feb 18 13:11:59 2001
A horrible BUG was found by Michael Drumheller <drumheller@alum.mit.edu>
In fact 0.21 was ALWAYS using DES despite of the desired cipher.
DAMN!
Fixed.
And the test is modified so that this will never happen again.
Now you can define the list of ciphers that are compatible
with Crypt::CBC in the import list.
You can not call this module with the "require" statement. This
is incompatible with the older versions.
0.23 Crypt::Rijndael 0.02 compatibility was approved.
Tests are some more complex now.
0.24 Sun Apr 8 02:28:26 2001
Crypt::TEA 1.01 by Abhijit Menon-Sen <ams@wiw.org> is checked
Changes
Makefile.PL
MANIFEST
README
CBCeasy.pm
test.pl
eg/chat2new.pl
eg/CBCeasy_sock.pl
Makefile.PL view on Meta::CPAN
-e "$$dir = $$ARGV[0];use File::Find;" \
-e "find(\&process, $$dir); sub process { return if -d || /\.dll$$/i;" \
-e "open(I,$$_) || die \"to_unix: can't read file `$$_'\n\";" \
-e "@file = <I>; close I;chmod 0666, $$_;" \
-e "open(O,\">$$_\") || die \"to_unix: can't write file `$$_'\n\";" \
-e "binmode O;print O map { s/\r\n/\n/;$$_ } @file; close O; }" $*
EOP
use ExtUtils::MakeMaker;
WriteMakefile(
"NAME" => "Crypt::CBCeasy",
"DISTNAME" => "Crypt-CBCeasy",
"VERSION_FROM" => "CBCeasy.pm",
"PREREQ_PM" => { "Crypt::CBC" => "1.20", "MD5" => 0 },
($] < 5.005 ? () :
(
"ABSTRACT" => "Easy things make really easy with Crypt::CBC",
"AUTHOR" => "Mike Blazer <blazer\@mail.nevalink.ru>",
)),
"dist" => { COMPRESS => 'gzip -9frN', SUFFIX => 'gz',
($^O eq "MSWin32" ? (PREOP => $PREOP) : ())},
"clean" => { FILES => "./tests pod2* *.html" },
);
sub MY::postamble {
my $postamble =<<'END';
html: CBCeasy.pm
pod2html --netscape --noindex CBCeasy.pm > CBCeasy.pm.html
END
$postamble;
}
NAME
Crypt::CBCeasy - Easy things make really easy with Crypt::CBC
SYNOPSIS
use Crypt::CBCeasy;
IDEA::encipher($my_key, "plain-file", "crypted-file");
$plain_text = DES::decipher($my_key, \*CRYPTO_FILE);
$crypted = Blowfish::encipher($my_key, \*PLAIN_SOCKET);
ABSTRACT
This module is a helper for Crypt::CBC to make simple and
usual jobs just one-liners.
The current version of the module is available at CPAN.
See CBCeasy.pm for POD docs.
INSTALLATION
As this is just a plain module no special installation is needed. Put it
into the /Crypt subdirectory somewhere in your @INC. The standard
Makefile.PL
make
make test
make install
installation procedure is provided. In addition
make html
will produce the HTML-docs.
This module requires
Crypt::CBC at least 1.20 by Lincoln Stein, lstein@cshl.org
one or more of
Crypt::IDEA, Crypt::DES, Crypt::Blowfish, Crypt::Blowfish_PP,
Crypt::Twofish2, Crypt::DES_PP, Crypt::Rijndael or other
Crypt::CBC compatible modules.
AUTHOR
Mike Blazer, blazer@mail.nevalink.ru
http://www.dux.ru/guest/fno/perl/
COPYRIGHT
eg/CBCeasy_sock.pl view on Meta::CPAN
#!/usr/bin/perl -w
use Crypt::CBCeasy;
$|=1;
require "chat2new.pl";
$host="204.71.200.67";
$req= "GET / HTTP/1.0\r\n\r\n";
http_get($host,80,$req);
# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.pl'
######################### We start with some black magic to print on failure.
# Change 1..1 below to 1..last_test_to_print .
# (It may become useful if the test is moved to ./t subdirectory.)
BEGIN {
require Crypt::CBC;
%REQ = (
DES => {crypt_cbc_version => 0, version => 0},
DES_PP => {crypt_cbc_version => 0, version => 0},
IDEA => {crypt_cbc_version => 0, version => 0},
Twofish2 => {crypt_cbc_version => 0, version => 0.06},
Rijndael => {crypt_cbc_version => 0, version => 0.01},
Blowfish => {crypt_cbc_version => 1.22, version => 0},
Blowfish_PP => {crypt_cbc_version => 1.22, version => 0},
TEA => {crypt_cbc_version => 0, version => 1.01},
);
@ciphers = ();
for (sort keys %REQ) {
$REQ{$_}->{crypt_cbc_version} &&
$Crypt::CBC::VERSION < $REQ{$_}->{crypt_cbc_version} and next;
eval "require Crypt::$_";
$@ and undef($@), next;
$ver = eval "\$Crypt::${_}::VERSION";
$REQ{$_}->{version} && $ver < $REQ{$_}->{version} and next;
push @ciphers, $_;
}
$all_tests = 27;
$| = 1; print "1..".(2 + $all_tests * scalar @ciphers)."\n";
}
END {print "not ok 1\n" unless $loaded;}
use Crypt::CBCeasy @ciphers;
use MD5;
use File::Path;
use FileHandle;
$loaded = 1;
print "ok 1\n";
######################### End of black magic.
# Insert your test code below (better if it prints "ok 13"
$res = eval qq~ &Test$i ~;
if ($res) {$res{$cipher}->{"ok"}++} else {$res{$cipher}->{"failed"}++}
print(( $res ? "" : "not " )."ok ".($test_num++)."\n");
}
}
$len = (sort {$b <=> $a} map length,@ciphers)[0];
print "\nOK, here it is. The ciphers you can use with Crypt::CBCeasy
(the other could be added later, see POD docs):\n\n";
for $cipher(@ciphers) {
($ok, $failed) = ($res{$cipher}->{"ok"}, $res{$cipher}->{"failed"});
print "Crypt::$cipher ".(" "x($len-length $cipher)).
" tests: ".($ok+$failed)." ok: $ok failed: $failed\n";
}
sub Test1 {
my $out = "tests/$cipher.o1";
eval "${cipher}::encipher(\$key, \$in_file, \$out)";
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
1;
}
sub Test2 {
my $in = "tests/$cipher.o1";
my $out = "tests/$cipher.o2";
-f $in or return;
eval "${cipher}::decipher(\$key, \$in, \$out)";
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
$FILE_HASH eq hash_file($out);
}
sub Test3 {
my $in = "tests/$cipher.o1";
my $out = "tests/$cipher.o3";
local *OUT;
-f $in or return;
open (OUT, ">$out") or return;
eval "${cipher}::decipher(\$key, \$in, \*OUT)";
close OUT;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
$FILE_HASH eq hash_file($out);
}
sub Test4 {
my $in = "tests/$cipher.o1";
my $out = "tests/$cipher.o4";
local *OUT;
-f $in or return;
open (OUT, ">$out") or return;
eval "${cipher}::decipher(\$key, \$in, \\*OUT)";
close OUT;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
$FILE_HASH eq hash_file($out);
}
sub Test5 {
my $in = "tests/$cipher.o1";
my $out = "tests/$cipher.o5";
local *IN;
-f $in or return;
open (IN, $in) or return;
eval "${cipher}::decipher(\$key, \*IN, \$out)";
close IN;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
$FILE_HASH eq hash_file($out);
}
sub Test6 {
my $in = "tests/$cipher.o1";
my $out = "tests/$cipher.o6";
local *IN;
-f $in or return;
open (IN, $in) or return;
eval "${cipher}::decipher(\$key, \\*IN, \$out)";
close IN;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
$FILE_HASH eq hash_file($out);
}
sub Test7 {
my $in = "tests/$cipher.o1";
my $out = "tests/$cipher.o7";
local (*IN, *OUT);
-f $in or return;
open (IN, $in) or return;
open (OUT, ">$out") or return;
eval "${cipher}::decipher(\$key, \*IN, \*OUT)";
close IN; close OUT;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
$FILE_HASH eq hash_file($out);
}
sub Test8 {
my $in = "tests/$cipher.o1";
my $out = "tests/$cipher.o8";
local (*IN, *OUT);
-f $in or return;
open (IN, $in) or return;
open (OUT, ">$out") or return;
eval "${cipher}::decipher(\$key, \\*IN, \\*OUT)";
close IN; close OUT;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
$FILE_HASH eq hash_file($out);
}
sub Test9 {
my $in = "tests/$cipher.o1";
-f $in or return;
my $str = eval "${cipher}::decipher(\$key, \$in)";
$@ and undef($@), return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
$str =~ s/\r\n/\n/g;
$FILE_HASH eq MD5->hash($str);
}
sub Test10 {
my $in = "tests/$cipher.o1";
local *IN;
-f $in or return;
open (IN, $in) or return;
my $str = eval "${cipher}::decipher(\$key, \\*IN)";
close IN;
$@ and undef($@), return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
$str =~ s/\r\n/\n/g;
$FILE_HASH eq MD5->hash($str);
}
sub Test11 {
check_plainfile("tests/$cipher.o1");
}
sub Test12 {
my $out = "tests/$cipher.o12";
local *OUT;
open(OUT, ">$out") or return;
eval "${cipher}::encipher(\$key, \$in_file, \\*OUT)";
close OUT;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
check_plainfile($out);
}
sub Test13 {
my $out = "tests/$cipher.o13";
local *OUT;
open(OUT, ">$out") or return;
eval "${cipher}::encipher(\$key, \$in_file, \*OUT)";
close OUT;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
check_plainfile($out);
}
sub Test14 {
my $out = "tests/$cipher.o14";
local (*IN, *OUT);
open(IN, $in_file) or return;
my $in_str = join "", <IN>;
close IN;
open(OUT, ">$out") or return;
eval "${cipher}::encipher(\$key, \$in_str, \*OUT)";
close OUT;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
check_plainfile($out);
}
sub Test15 {
my $out = "tests/$cipher.o15";
local (*IN, *OUT);
open(IN, $in_file) or return;
open(OUT, ">$out") or return;
eval "${cipher}::encipher(\$key, \*IN, \*OUT)";
close OUT; close IN;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
check_plainfile($out);
}
sub Test16 {
my $out = "tests/$cipher.o16";
local (*IN, *OUT);
open(IN, $in_file) or return;
open(OUT, ">$out") or return;
eval "${cipher}::encipher(\$key, \\*IN, \\*OUT)";
close OUT; close IN;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
check_plainfile($out);
}
sub Test17 {
my $out = "tests/$cipher.o17";
local *IN;
open(IN, $in_file) or return;
my $str = eval "${cipher}::encipher(\$key, \*IN)";
close IN;
$@ and undef($@), return;
write_file($out, $str) or return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
check_plainfile($out);
}
sub Test18 {
my $out = "tests/$cipher.o18";
local *IN;
open(IN, $in_file) or return;
my $str = eval "${cipher}::encipher(\$key, \\*IN)";
close IN;
$@ and undef($@), return;
write_file($out, $str) or return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
check_plainfile($out);
}
sub Test19 {
my $out = "tests/$cipher.o19";
my $str = eval "${cipher}::encipher(\$key, \$in_file)";
$@ and undef($@), return;
write_file($out, $str) or return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
check_plainfile($out);
}
#==== OO ======
sub Test20 {
my $in = "tests/$cipher.o1";
my $out = "tests/$cipher.o20";
-f $in or return;
my $fh = FileHandle->new(">$out") or return;
eval "${cipher}::decipher(\$key, \$in, \$fh)";
$fh->close;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
$FILE_HASH eq hash_file($out);
}
sub Test21 {
my $in = "tests/$cipher.o1";
my $out = "tests/$cipher.o21";
-f $in or return;
my $fh = FileHandle->new($in) or return;
eval "${cipher}::decipher(\$key, \$fh, \$out)";
$fh->close;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
$FILE_HASH eq hash_file($out);
}
sub Test22 {
my $in = "tests/$cipher.o1";
my $out = "tests/$cipher.o22";
-f $in or return;
my $fhi = FileHandle->new($in) or return;
my $fho = FileHandle->new(">$out") or return;
eval "${cipher}::decipher(\$key, \$fhi, \$fho)";
$fhi->close; $fho->close;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
$FILE_HASH eq hash_file($out);
}
sub Test23 {
my $in = "tests/$cipher.o1";
-f $in or return;
my $fh = FileHandle->new($in) or return;
my $str = eval "${cipher}::decipher(\$key, \$fh)";
$fh->close;
$@ and undef($@), return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
$str =~ s/\r\n/\n/g;
$FILE_HASH eq MD5->hash($str);
}
sub Test24 {
my $out = "tests/$cipher.o24";
my $fh = FileHandle->new(">$out") or return;
eval "${cipher}::encipher(\$key, \$in_file, \$fh)";
$fh->close;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
check_plainfile($out);
}
sub Test25 {
my $out = "tests/$cipher.o25";
local (*IN);
open(IN, $in_file) or return;
my $in_str = join "", <IN>;
close IN;
my $fh = FileHandle->new(">$out") or return;
eval "${cipher}::encipher(\$key, \$in_str, \$fh)";
$fh->close;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
check_plainfile($out);
}
sub Test26 {
my $out = "tests/$cipher.o26";
my $fhi = FileHandle->new($in_file) or return;
my $fho = FileHandle->new(">$out") or return;
eval "${cipher}::encipher(\$key, \$fhi, \$fho)";
$fhi->close; $fho->close;
$@ and undef($@), return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
check_plainfile($out);
}
sub Test27 {
my $out = "tests/$cipher.o27";
my $fh = FileHandle->new($in_file) or return;
my $str = eval "${cipher}::encipher(\$key, \$fh)";
$fh->close;
$@ and undef($@), return;
write_file($out, $str) or return;
-f $out && -s _ or return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
check_plainfile($out);
}
sub read_file {
my $in = shift;
local *IN;
open(IN, $in) || return;
my $in_string = join "", <IN>;
my $in = shift;
local *IN;
-f $in or return;
open (IN, $in) or return;
my $str = eval "${cipher}::decipher(\$key, \*IN)";
close IN;
$@ and undef($@), return;
$Crypt::CBCeasy::LastCipher ne $cipher and return;
$str =~ s/\r\n/\n/g;
$FILE_HASH eq MD5->hash($str);
}
sub write_file {
my ($out, $str) = @_;
local *OUT;
open(OUT, ">$out") or return;
binmode OUT;
( run in 1.598 second using v1.01-cache-2.11-cpan-e1769b4cff6 )