Subject: | CBC fixes for oneandzeroes and compatibility |
Fixes (in order of diff):
1. parse buffer into blocks only if buffer is greater than blocksize
since ->finish will do pad/encrypt stuff for 1 block.
2. the code ---- . "a*" ---- in the unpack was causing an extra byte to
be added to strings which evenly divide into blocks.
3. code formatting inside an if statement
4. oneandzeroes fix. basically, the bit string was being truncated
incorrectly. I made it a hex string and truncate /80+$/ (i.e., 0x80 is
the 1 plus any zeros)
Tested:
Perl v5.6.1 built for powerpc-linux
Perl v5.6.1 built for i386-linux
oneandzeroes padding with Crypt::Rijndael
With this patch, Crypt::CBC works out of the box with Cryptix 3.2.0 and
Crypt::Rijndael::MODE_CBC.
-s
--- CBC.pm Tue Jun 4 15:48:04 2002
+++ CBC.pm.new Wed Jun 5 13:34:45 2002
@@ -174,27 +174,23 @@
my $bs = $self->{'blocksize'};
- return $result unless (length($self->{'buffer'}) >= $bs);
+ return $result unless (length($self->{'buffer'}) > $bs);
# split into blocksize chunks
- # used to be:
- # my @blocks = $self->{'buffer'}=~/(.{1,$bs})/ogs;
- # but this is a little faster (about 1.5 times)
- my @blocks = unpack("a$bs "x(int(length($self->{'buffer'})/$bs)) . "a*", $self->{'buffer'});
- $self->{'buffer'} = '';
-
- if ($d) { # when decrypting, always leave a free block at the end
- $self->{'buffer'} = length($blocks[-1]) < $bs ? join '',splice(@blocks,-2) : pop(@blocks);
+ my $bcnt = int(length($self->{'buffer'})/$bs);
+ my @blocks = unpack("a$bs "x $bcnt, $self->{'buffer'});
+ if (length($self->{'buffer'}) % $bs == 0) {
+ $self->{'buffer'} = pop @blocks;
} else {
- $self->{'buffer'} = pop @blocks if length($blocks[-1]) < $bs; # what's left over
+ $self->{'buffer'} = substr($self->{'buffer'}, $bcnt * $bs);
}
foreach my $block (@blocks) {
if ($d) { # decrypting
- $result .= $iv ^ $self->{'crypt'}->decrypt($block);
- $iv = $block;
+ $result .= $iv ^ $self->{'crypt'}->decrypt($block);
+ $iv = $block;
} else { # encrypting
- $result .= $iv = $self->{'crypt'}->encrypt($iv ^ $block);
+ $result .= $iv = $self->{'crypt'}->encrypt($iv ^ $block);
}
}
$self->{'civ'} = $iv; # remember the iv
@@ -280,14 +276,10 @@
my $decrypt = shift;
if ($decrypt eq 'd') { # decrypting
- my $bitstring = unpack("B*", $block);
- $bitstring =~ s/10*$//s;
- while (length($bitstring)%8) {
- # this shouldn't be the case, but let's make stuff full bytes...
- $bitstring .= '0';
- }
- $block = pack("B*", $bitstring);
- } else {
+ my $hex = unpack("H*", $block);
+ $hex =~ s/80+$//s;
+ $block = pack("H*", $hex);
+ } elsif (length($block) < $bs) {
$block .= pack("H2", "80");
$block = pack("a$bs", $block);
}