# Blowfishinator: a wrapper around blowfish cfb mode # # WARNING/DISCLAIMER: this module contains an aptly named "destroy file" # function that can and will irreversibly obliterate a file - if you # wreck something with it, that's not my fault - even if it was a direct # or indirect result of using this module correctly or incorrectly. # # you assume any and all responsibility for any damage to data, software, # hardware, pets or local weather patterns that may occur directly or indirectly # from the use of this software. Caveat Hacktor. Phew. ok - enough gluteal # covering - on to the nerdy crypto fun :) # # you may use/modify this code under the sames terms as perl itself. # see your distribution for details. # # oh, and the crypto purists among you will note that there is no facility # for input vectors, so this probably isn't "bullet proof" crypto. but then # again, if you really needed bullet proof crypto, you wouldn't be using a module # written by some random person on the internet, now would you? hmmm? # # Author: Steve McNabb steve@justsomeguy.com # # Many thanks to my employer Training Alternatives (www.trainingalternatives.com) # for giving me permission to release this module as open source software # # see pod after __END__ package Blowfishinator_PP; # slightly hacked version to use the pure perl implementation of # blowfish from Crypt::Blowfish_PP # bits of this code pinched from hopwoodg@satx.net 's example # script at http://user.intersatx.net/hopwoodg/bfsample.txt use strict; use Crypt::Blowfish_PP; use Crypt::CFB; #cipher feedback mode... use Carp; my $VERSION = '0.1'; sub new { my $self ={}; my $class = shift; bless($self,$class); $self->{wipe_level} = shift || '3'; # how paranoid are you? return $self; } sub encrypt_string { my ($self, $key, $plaintext) = @_; my $cipher_8byteblock = Crypt::Blowfish_PP->new($key); my $cipher = Crypt::CFB->new($cipher_8byteblock); return unpack("H*", $cipher->encrypt($plaintext)); } sub decrypt_string { my ($self,$key, $ciphertext) = @_; my $cipher_8byteblock = Crypt::Blowfish_PP->new($key); my $cipher = Crypt::CFB->new($cipher_8byteblock); $ciphertext = pack("H*", $ciphertext); return $cipher->decrypt($ciphertext); } # does not destroy the original file, writes encrypted file to $file.fish sub encrypt_file { my ($self,$key, $file) = @_; open(IN, $file) or die "Unable to open $file, $!\n"; open(OUT, "> $file.fish") or die "Unable to open $file.fish, $!\n"; binmode IN; binmode OUT; #for you windohs folks my $cipher_8byteblock = Crypt::Blowfish_PP->new($key); my $cipher = Crypt::CFB->new($cipher_8byteblock); my $buff; while (read(IN, $buff, 32768)) { my $cipherblock = $cipher->encrypt($buff); print OUT $cipherblock; } close IN; close OUT; return "$file.fish"; #reutrns name of encrypted file } # does not destroy encrypted file, saves file to $encrypted_file without the .fish extension sub decrypt_file { my ($self,$key, $file) = @_; if ($file =~ /(.*)\.fish$/) { open(IN, $file) or die "Unable to open $file, $!\n"; open(OUT, "> $1") or die "Unable to open $1, $!\n"; binmode IN; binmode OUT; #for you windohs folks } else { print "($file) Unencrypted file, or incorrect extension - file should have a .fish extension\n"; return; } my $cipher_8byteblock = Crypt::Blowfish_PP->new($key); my $cipher = Crypt::CFB->new($cipher_8byteblock); my $buff; while (read(IN, $buff, 32768)) { my $block = $cipher->decrypt($buff); print OUT $block; } close IN; close OUT; return $1; #returns filename of decrypted file. } # blows away original file and overwites it with random crud # returns filename of encrypted file sub encrypt_and_destroy_file { my($self,$key,$file) = @_; my $encrypted_file = $self->encrypt_file($key,$file); $self->destroy_file($file); return $encrypted_file; } # blows away encrypted file - no real need to overwrite it, but what the heck # returns filename of decrypted file sub decrypt_and_destroy_file { my($self,$key,$file) = @_; my $decrypted_file = $self->decrypt_file($key,$file); $self->destroy_file($file); return $decrypted_file; } sub destroy_file { my($self,$file) = @_; for(1..$self->{wipe_level}) { open(FILE,"$file") or die "cannot open $file for reading: $!"; my $fileguts = do { local $/; }; close FILE; my $random_crud = $self->random_crud(length($fileguts)); open(FILE,">$file") or die "cannot open $file for wiping - pass $_: $!"; print FILE $random_crud; close FILE; } unlink $file; } sub random_crud { my ($self,$size) = @_; my $random_crud; #0-9 A-Z a-z and a few other sundry characters for(1..$size) {$random_crud .= chr(int(rand(74))+48)} return $random_crud; } 1; __END__; =head1 Name Blowfishinator_PP.pm - a (hopefully) simple to use blowfish/cfb wrapper slightly modified to use the pure perl version of Blowfish =head1 Author Steve McNabb s.mcnabb@sympatico.ca =head1 Synopsis use Blowfishinator_PP; my $bf = new Blowfishinator_PP; or my $bf = new Blowfishinator_PP(50); #wipe the file with 50 over writes - super paranoia. #defaults to 3 passes # encrypt/decrypt strings $ciphertext = $bf->encrypt_string( "Here is my secret passphrase", "My secret message is : the monkey pees at dawn!"); $plaintext = $bf->decrypt_string( "Here is my secret passphrase", $ciphertext); # encrypt/decrypt files $encrypted_filename = $bf->encrypt_file( "Here is my secret passphrase", $filename); $decrypted_filename = $bf->decrypt_file( "Here is my secret passphrase", $filename); # encrypt and obliterate / decrypt and obliterate - USE WITH CAUTION!! $encrypted_filename = $bf->encrypt_and_destroy_file( "Here is my secret passphrase", $filename); $decrypted_filename = $bf->decrypt_and_destroy_file( "Here is my secret passphrase", $filename);