Subject: Strange key length behavior with Blowfish and CBC in Perl 5.8 on
To: None <netbsd-help@netbsd.org, lstein@cshl.org, amused@pobox.com>
From: Gan Uesli Starling <gan@starling.us>
List: netbsd-help
Date: 08/13/2005 14:55:31
This is a multi-part message in MIME format.
--------------000908070009020700010407
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit

There is a mystery regarding 56- vs 112-byte keys in Blowfish
via Perl on NetBSD. I can't test it at present on Win32 as the
PPM server at Univ. Winnipeg seems to be down. Attached is
a short Perl script which exemplifies the mystery with an easy
toggle for both cases.

Affected NetBSD version is:
NetBSD 2.0.2 (GENERIC) #0: Wed Mar 23 08:53:42 UTC 2005

Affected Perl module packages are:
perl-5.8.6nb6 Practical Extraction and Report Language
p5-Crypt-Blowfish-2.09nb1
p5-Crypt-CBC-2.08nb1

Full details are embeded within the attached Perl script. Copy it to
anywhere, chmod it 755 and run it.

My question is whether this be a NetBSD package bug or a
Perl module bug or what?

Respectfully,

Gan Starling
Kalamazoo MI

--------------000908070009020700010407
Content-Type: application/x-perl;
 name="gus_example_blowfish_cbc.pl"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="gus_example_blowfish_cbc.pl"

#!/usr/pkg/bin/perl -w

use Crypt::CBC;

my $double_key = 0; # Toggle 0 or 1 to see mystery behavior.

# Note 1: Blowfish algorithm claims 56 bytes for max key. But
# experimentation shows double (112) works with Blowfish alone. 
# Likewise for minimal key, which Crypt::Blowfish says must be 8, 
# but # really needs 16 for Blowfish alone. Yet here with Crypt::CBC
# alone, it goes back to requiring 56 and 8 rather than double. Why? 

# Note 2: As regards Note 1 above, I can toggle the mysterious behavior 
# back and forth by the either declaring 'use Crypt::Blowfish;' or not. Why?

# NetBSD uname -a says:
# NetBSD baal.amalekite.net 2.0.2 NetBSD 2.0.2 (GENERIC) #0: Wed Mar 23 08:53:42 UTC 2005  jmc@faith.netbsd.org:/home/builds/ab/netbsd-2-0-2-RELEASE/i386/200503220140Z-obj/home/builds/ab/netbsd-2-0-2-RELEASE/src/sys/arch/i386/compile/GENERIC i386

# NetBSD pkg_info says:
# perl-5.8.6nb6 Practical Extraction and Report Language
# p5-Crypt-Blowfish-2.09nb1 Perl5 Blowfish implementation
# p5-Crypt-CBC-2.08nb1 Perl5 cipher block chaining mode for various crypto algorithms

#############################
# BEGIN EXAMPLE PERL SCRIPT #
#############################

my $max_key_size = 56; 
my $min_key_size = 8;

if ($double_key) {
    use Crypt::Blowfish;
    $max_key_size *= 2;
    $min_key_size *= 2;
}

# Eight bytes minimum for cypher key!
my $key_text = 
    'Once upon a midnight dreary' .
    'While I pondered weak and weary' .
    'Over many a quaint and curious' .
    'Volume of forgotten lore' .
    'As I sat there nearly napping' .
    'Suddenly there came a tapping' .
    'As of someone gently rapping' .
    'Rapping on my chamber door' .
    'Merely this and nothing more';

# Uncomment line below to test for mininmal key.
# $key_text = substr($key_text, 0, $min_key_size); # See Note 1 above.

print "Key provided:\n\t", $key_text, "\n\n";

# Use the last, not first part, of key text.
my $key_0th = 0;
$key_0th = length($key_text) - $max_key_size if length($key_text) > $max_key_size;
$key_text = substr( $key_text, $key_0th);
print "Key portion used:\n\t", $key_text, "\n\n";

my $cipher = Crypt::CBC->new( 
    {   'key'             => $key_text,
        'cipher'          => 'Blowfish',
        'iv'              => '$KJh#(}q',
        'regenerate_key'  => 1,   # default true
        'padding'         => 'space',
        'prepend_iv'      => 1
    }
);
  
# Prepare to encrypt this very Perl script.
open(FILE_AU,"<./gus_example_blowfish_cbc.pl");  # Golden original.
open(FILE_PB,">./gus_example_blowfish_cbc.cfr"); # Leaden copy.

# Encrypt it now.
$cipher->start('encrypting');
print FILE_PB $cipher->crypt($_) while <FILE_AU>;
print FILE_PB $cipher->finish();

# Prepare to decrypt it back again.
open(FILE_PB,"<./gus_example_blowfish_cbc.cfr"); # Leaden copy.
open(FILE_AG,">./gus_example_blowfish_cbc.pln"); # Silver copy.

# Decrypt it now.
$cipher->start('decrypting');
print FILE_AG $cipher->crypt($_) while <FILE_PB>;
print FILE_AG $cipher->finish();

# Compare golden versus silver via Unix 'diff' functioin.
# So must test to skip when on Win32 systems.
unless ( $^O =~ /Win/i) {
    print "Differences before/after encryption:\n\t";
    my $differences = join "\n\t", `diff gus_example_blowfish_cbc.pl gus_example_blowfish_cbc.pln`;
    print $differences, "\n";
    print "Total of differing lines: ", length $differences, "\n\n";
}

# Let user know this script did not hang.
print "All done.\n";






--------------000908070009020700010407--