# $Id: Blowfish.pm,v 1.14 2001/05/08 02:55:40 btrott Exp $
package Net::SSH::Perl::Cipher::Blowfish;
use strict;
use Net::SSH::Perl::Cipher;
use base qw( Net::SSH::Perl::Cipher );
use Net::SSH::Perl::Cipher::CBC;
use vars qw( $BF_CLASS );
BEGIN {
my @err;
for my $mod (qw( Crypt::Blowfish Crypt::Blowfish_PP )) {
eval "use $mod;";
$BF_CLASS = $mod, last unless $@;
push @err, $@;
}
die "Failed to load Crypt::Blowfish and Crypt::Blowfish_PP: @err"
unless $BF_CLASS;
}
sub new {
my $class = shift;
my $ciph = bless { }, $class;
$ciph->init(@_) if @_;
$ciph;
}
sub keysize { 16 }
sub blocksize { 8 }
sub init {
my $ciph = shift;
my($key, $iv, $is_ssh2) = @_;
my $blow = $BF_CLASS->new($is_ssh2 ? substr($key, 0, 16) : $key);
$ciph->{cbc} = Net::SSH::Perl::Cipher::CBC->new($blow,
$iv ? substr($iv, 0, 8) : undef);
$ciph->{is_ssh2} = defined $is_ssh2 ? $is_ssh2 : 0;
}
sub encrypt {
my($ciph, $text) = @_;
$ciph->{is_ssh2} ?
$ciph->{cbc}->encrypt($text) :
_swap_bytes($ciph->{cbc}->encrypt(_swap_bytes($text)));
}
sub decrypt {
my($ciph, $text) = @_;
$ciph->{is_ssh2} ?
$ciph->{cbc}->decrypt($text) :
_swap_bytes($ciph->{cbc}->decrypt(_swap_bytes($text)));
}
sub _swap_bytes {
my $str = $_[0];
$str =~ s/(.{4})/reverse $1/sge;
$str;
}
1;
__END__
=head1 NAME
Net::SSH::Perl::Cipher::Blowfish - Wrapper for SSH Blowfish support
=head1 SYNOPSIS
use Net::SSH::Perl::Cipher;
my $cipher = Net::SSH::Perl::Cipher->new('Blowfish', $key);
print $cipher->encrypt($plaintext);
=head1 DESCRIPTION
I<Net::SSH::Perl::Cipher::Blowfish> provides Blowfish encryption
support for I<Net::SSH::Perl>. To do so it wraps around either
I<Crypt::Blowfish> or I<Crypt::Blowfish_PP>; the former is a
C/XS implementation of the blowfish algorithm, and the latter is
a Perl implementation. I<Net::SSH::Perl::Cipher::Blowfish> prefers
to use I<Crypt::Blowfish>, because it's faster, so we try to load
that first. If it fails, we fall back to I<Crypt::Blowfish_PP>.
Note that, when using I<Crypt::Blowfish_PP>, you'll experience
a very noticeable decrease in performance.
The blowfish used here is in CBC filter mode with a key length
of 32 bytes.
SSH1 adds an extra wrinkle with respect to its blowfish algorithm:
before and after encryption/decryption, we have to swap the bytes
in the string to be encrypted/decrypted. The byte-swapping is done
four bytes at a time, and within each of those four-byte blocks
we reverse the bytes. So, for example, the string C<foobarba>
turns into C<boofabra>. We swap the bytes in this manner in the
string before we encrypt/decrypt it, and swap the
encrypted/decrypted string again when we get it back.
This byte-swapping is not done when Blowfish is used in the
SSH2 protocol.
=head1 AUTHOR & COPYRIGHTS
Please see the Net::SSH::Perl manpage for author, copyright,
and license information.
=cut