diff options
Diffstat (limited to 'Master/tlpkg/tlperl0/lib/Crypt/OpenPGP/Cipher.pm')
-rwxr-xr-x | Master/tlpkg/tlperl0/lib/Crypt/OpenPGP/Cipher.pm | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl0/lib/Crypt/OpenPGP/Cipher.pm b/Master/tlpkg/tlperl0/lib/Crypt/OpenPGP/Cipher.pm new file mode 100755 index 00000000000..8476657bbe2 --- /dev/null +++ b/Master/tlpkg/tlperl0/lib/Crypt/OpenPGP/Cipher.pm @@ -0,0 +1,232 @@ +package Crypt::OpenPGP::Cipher; +use strict; + +use Crypt::OpenPGP::CFB; +use Crypt::OpenPGP::ErrorHandler; +use base qw( Crypt::OpenPGP::ErrorHandler ); + +use vars qw( %ALG %ALG_BY_NAME ); +%ALG = ( + 1 => 'IDEA', + 2 => 'DES3', + 3 => 'CAST5', + 4 => 'Blowfish', + 7 => 'Rijndael', + 8 => 'Rijndael192', + 9 => 'Rijndael256', + 10 => 'Twofish', +); +%ALG_BY_NAME = map { $ALG{$_} => $_ } keys %ALG; + +sub new { + my $class = shift; + my $alg = shift; + $alg = $ALG{$alg} || $alg; + return $class->error("Unsupported cipher algorithm '$alg'") + unless $alg =~ /^\D/; + my $pkg = join '::', $class, $alg; + my $ciph = bless { __alg => $alg, + __alg_id => $ALG_BY_NAME{$alg} }, $pkg; + my $impl_class = $ciph->crypt_class; + my @classes = ref($impl_class) eq 'ARRAY' ? @$impl_class : ($impl_class); + for my $c (@classes) { + eval "use $c;"; + $ciph->{__impl} = $c, last unless $@; + } + return $class->error("Error loading cipher implementation for " . + "'$alg': no implementations installed.") + unless $ciph->{__impl}; + $ciph->init(@_); +} + +sub init { + my $ciph = shift; + my($key, $iv) = @_; + if ($key) { + my $class = $ciph->{__impl}; + ## Make temp variable, because Rijndael checks SvPOK, which + ## doesn't seem to like a value that isn't a variable? + my $tmp = substr $key, 0, $ciph->keysize; + my $c = $class->new($tmp); + $ciph->{cipher} = Crypt::OpenPGP::CFB->new($c, $iv); + } + $ciph; +} + +sub encrypt { $_[0]->{cipher}->encrypt($_[1]) } +sub decrypt { $_[0]->{cipher}->decrypt($_[1]) } + +sub sync { $_[0]->{cipher}->sync } + +sub alg { $_[0]->{__alg} } +sub alg_id { + return $_[0]->{__alg_id} if ref($_[0]); + $ALG_BY_NAME{$_[1]} || $_[1]; +} +sub supported { + my $class = shift; + my %s; + for my $cid (keys %ALG) { + my $cipher = $class->new($cid); + $s{$cid} = $cipher->alg if $cipher; + } + \%s; +} + +package Crypt::OpenPGP::Cipher::IDEA; +use strict; +use base qw( Crypt::OpenPGP::Cipher ); + +sub init { + my $ciph = shift; + my($key, $iv) = @_; + if ($key) { + my $c = IDEA->new(substr($key, 0, $ciph->keysize)); + $ciph->{cipher} = Crypt::OpenPGP::CFB->new($c, $iv); + } + $ciph; +} + +sub crypt_class { 'Crypt::IDEA' } +sub keysize { 16 } +sub blocksize { 8 } + +package Crypt::OpenPGP::Cipher::Blowfish; +use strict; +use base qw( Crypt::OpenPGP::Cipher ); + +sub crypt_class { 'Crypt::Blowfish' } +sub keysize { 16 } +sub blocksize { 8 } + +package Crypt::OpenPGP::Cipher::DES3; +use strict; +use base qw( Crypt::OpenPGP::Cipher ); + +sub crypt_class { 'Crypt::DES_EDE3' } +sub keysize { 24 } +sub blocksize { 8 } + +package Crypt::OpenPGP::Cipher::CAST5; +use strict; +use base qw( Crypt::OpenPGP::Cipher ); + +sub crypt_class { 'Crypt::CAST5_PP' } +sub keysize { 16 } +sub blocksize { 8 } + +package Crypt::OpenPGP::Cipher::Twofish; +use strict; +use base qw( Crypt::OpenPGP::Cipher ); + +sub crypt_class { 'Crypt::Twofish' } +sub keysize { 32 } +sub blocksize { 16 } + +package Crypt::OpenPGP::Cipher::Rijndael; +use strict; +use base qw( Crypt::OpenPGP::Cipher ); + +sub crypt_class { 'Crypt::Rijndael' } +sub keysize { 16 } +sub blocksize { 16 } + +package Crypt::OpenPGP::Cipher::Rijndael192; +use strict; +use base qw( Crypt::OpenPGP::Cipher ); + +sub crypt_class { 'Crypt::Rijndael' } +sub keysize { 24 } +sub blocksize { 16 } + +package Crypt::OpenPGP::Cipher::Rijndael256; +use strict; +use base qw( Crypt::OpenPGP::Cipher ); + +sub crypt_class { 'Crypt::Rijndael' } +sub keysize { 32 } +sub blocksize { 16 } + +1; +__END__ + +=head1 NAME + +Crypt::OpenPGP::Cipher - PGP symmetric cipher factory + +=head1 SYNOPSIS + + use Crypt::OpenPGP::Cipher; + + my $alg = 'Rijndael'; + my $cipher = Crypt::OpenPGP::Cipher->new( $alg ); + + my $plaintext = 'foo bar'; + my $ct = $cipher->encrypt($plaintext); + my $pt = $cipher->decrypt($ct); + +=head1 DESCRIPTION + +I<Crypt::OpenPGP::Cipher> is a factory class for PGP symmetric ciphers. +All cipher objects are subclasses of this class and share a common +interface; when creating a new cipher object, the object is blessed +into the subclass to take on algorithm-specific functionality. + +A I<Crypt::OpenPGP::Cipher> object is a wrapper around a +I<Crypt::OpenPGP::CFB> object, which in turn wraps around the actual +cipher implementation (eg. I<Crypt::Blowfish> for a Blowfish cipher). +This allows all ciphers to share a common interface and a simple +instantiation method. + +=head1 USAGE + +=head2 Crypt::OpenPGP::Cipher->new($cipher) + +Creates a new symmetric cipher object of type I<$cipher>; I<$cipher> +can be either the name of a cipher (in I<Crypt::OpenPGP> parlance) or +the numeric ID of the cipher (as defined in the OpenPGP RFC). Using +a cipher name is recommended, for the simple reason that it is easier +to understand quickly (not everyone knows the cipher IDs). + +Valid cipher names are: C<IDEA>, C<DES3>, C<Blowfish>, C<Rijndael>, +C<Rijndael192>, C<Rijndael256>, C<Twofish>, and C<CAST5>. + +Returns the new cipher object on success. On failure returns C<undef>; +the caller should check for failure and call the class method I<errstr> +if a failure occurs. A typical reason this might happen is an +unsupported cipher name or ID. + +=head2 $cipher->encrypt($plaintext) + +Encrypts the plaintext I<$plaintext> and returns the encrypted text +(ie. ciphertext). The encryption is done in CFB mode using the +underlying cipher implementation. + +=head2 $cipher->decrypt($ciphertext) + +Decrypts the ciphertext I<$ciphertext> and returns the plaintext. The +decryption is done in CFB mode using the underlying cipher +implementation. + +=head2 $cipher->alg + +Returns the name of the cipher algorithm (as listed above in I<new>). + +=head2 $cipher->alg_id + +Returns the numeric ID of the cipher algorithm. + +=head2 $cipher->blocksize + +Returns the blocksize of the cipher algorithm (in bytes). + +=head2 $cipher->keysize + +Returns the keysize of the cipher algorithm (in bytes). + +=head1 AUTHOR & COPYRIGHTS + +Please see the Crypt::OpenPGP manpage for author, copyright, and +license information. + +=cut |