Skip Menu |

This queue is for tickets about the Crypt-CBC CPAN distribution.

Report information
The Basics
Id: 16270
Status: open
Priority: 0/
Queue: Crypt-CBC

People
Owner: LDS [...] cpan.org
Requestors: msk [...] newmail.ru
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in:
  • 2.15
  • 2.24
Fixed in: (no value)



Subject: Data corruption... Something wrong...
Example #!/usr/bin/perl use Crypt::CBC; my $cipher = Crypt::CBC->new( -key => '', -cipher => 'Blowfish', -salt => 0, -padding => "oneandzeroes", -prepend_iv => 0 ); my $key = Crypt::CBC::_null_padding('aaa',8,''); $cipher->key($key); $cipher->iv('abcdefgh'); $string = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX'; # Last symbol replaced by P! #$string = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx'; # Last symbol replaced by p! #$string = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8'; # Last symbol replaced by 0! #$string = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH'; # Last symbol replaced by @! #$string = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAh'; # Last symbol replaced by '! $work = $cipher->encrypt($string); #Encrypt string $work = $cipher->decrypt($work); #...and decrypt print $string."\n"; print $work."\n"; Result: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP Other combinations with last symbol of string is ok. BTW: Error in documentation: ------------- -padding The padding method, one of "standard", "space", "onesandzeroes", or "null". (default "standard") ------------- oneSandzeroes - must be oneandzeroes
Shorter program that fails on current version: #!/usr/bin/perl use strict; use warnings; use Crypt::CBC; my $cipher = Crypt::CBC->new( -key => 'aaab', -cipher => 'Blowfish', -padding => "oneandzeroes", ); my $string = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX'; # Last symbol replaced by P! my $work = $cipher->encrypt($string); #Encrypt string $work = $cipher->decrypt($work); #...and decrypt print $string."\n"; print $work."\n"; die unless $string eq $work; -- Alexandr Ciornii, http://chorny.net
Thanks. I'm working on this now. Lincoln On Sat Dec 03 18:48:02 2005, guest wrote: Show quoted text
> Example > > #!/usr/bin/perl > use Crypt::CBC; > > my $cipher = Crypt::CBC->new( > -key => '', > -cipher => 'Blowfish', > -salt => 0, > -padding => "oneandzeroes", > -prepend_iv => 0 > ); > my $key = Crypt::CBC::_null_padding('aaa',8,''); > $cipher->key($key); > $cipher->iv('abcdefgh'); > > $string = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX'; > # Last symbol replaced by P! > #$string = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx'; > # Last symbol replaced by p! > #$string = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8'; > # Last symbol replaced by 0! > #$string = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH'; > # Last symbol replaced by @! > #$string = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAh'; > # Last symbol replaced by '! > > > $work = $cipher->encrypt($string); #Encrypt string > $work = $cipher->decrypt($work); #...and decrypt > > print $string."\n"; > print $work."\n"; > > > > Result: > AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX > AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP > > Other combinations with last symbol of string is ok. > > BTW: > Error in documentation: > ------------- > -padding The padding method, one of "standard", "space", > "onesandzeroes", or "null". (default "standard") > ------------- > oneSandzeroes - must be oneandzeroes >
Try applying this patch. It turns out that Crypt::CBC's implementation of oneandzeroes padding is different from Crypt::Rijndael's, so I've had to add a new compatibility padding.
? Crypt-CBC-2.24 ? Makefile ? blib ? failure.pl ? failure_rijndael.pl ? onezeropadding.patch ? pm_to_blib Index: CBC.pm =================================================================== RCS file: /usr/local/cvs_repository/Crypt-CBC/CBC.pm,v retrieving revision 1.35 diff -c -r1.35 CBC.pm *** CBC.pm 28 Sep 2007 15:24:12 -0000 1.35 --- CBC.pm 11 Jan 2008 20:24:40 -0000 *************** *** 116,139 **** unless ($rbs == $bs); } } else { ! $padding = $padding eq 'null' ? \&_null_padding ! :$padding eq 'space' ? \&_space_padding ! :$padding eq 'oneandzeroes' ? \&_oneandzeroes_padding ! :$padding eq 'standard' ? \&_standard_padding :croak "'$padding' padding not supported. See perldoc Crypt::CBC for instructions on creating your own."; } # CONSISTENCY CHECKS # HEADER consistency if ($header_mode eq 'salt') { ! croak "Cannot use salt-based key generation if literal key is specified" if $options->{literal_key}; ! croak "Cannot use salt-based IV generation if literal IV is specified" if exists $options->{iv}; } elsif ($header_mode eq 'randomiv') { ! croak "Cannot encrypt using a non-8 byte blocksize cipher when using randomiv header mode" unless $bs == 8 || $legacy_hack; } elsif ($header_mode eq 'none') { ! croak "You must provide an initialization vector using -iv when using -header=>'none'" unless exists $options->{iv}; } # KEYSIZE consistency --- 116,144 ---- unless ($rbs == $bs); } } else { ! $padding = $padding eq 'null' ? \&_null_padding ! :$padding eq 'space' ? \&_space_padding ! :$padding eq 'oneandzeroes' ? \&_oneandzeroes_padding ! :$padding eq 'rijndael_compat'? \&_rijndael_compat ! :$padding eq 'standard' ? \&_standard_padding :croak "'$padding' padding not supported. See perldoc Crypt::CBC for instructions on creating your own."; } # CONSISTENCY CHECKS # HEADER consistency if ($header_mode eq 'salt') { ! croak "Cannot use salt-based key generation if literal key is specified" ! if $options->{literal_key}; ! croak "Cannot use salt-based IV generation if literal IV is specified" ! if exists $options->{iv}; } elsif ($header_mode eq 'randomiv') { ! croak "Cannot encrypt using a non-8 byte blocksize cipher when using randomiv header mode" ! unless $bs == 8 || $legacy_hack; } elsif ($header_mode eq 'none') { ! croak "You must provide an initialization vector using -iv when using -header=>'none'" ! unless exists $options->{iv}; } # KEYSIZE consistency *************** *** 222,227 **** --- 227,236 ---- my $bs = $self->{'blocksize'}; + croak "When using rijndael_compat padding, plaintext size must be a multiple of $bs" + if $self->{'padding'} eq \&_rijndael_compat + and length($data) % $bs; + return $result unless (length($self->{'buffer'}) >= $bs); my @blocks = unpack("a$bs "x(int(length($self->{'buffer'})/$bs)) . "a*", $self->{'buffer'}); *************** *** 468,474 **** sub _oneandzeroes_padding ($$$) { my ($b,$bs,$decrypt) = @_; - return unless length $b; $b = length $b ? $b : ''; if ($decrypt eq 'd') { my $hex = unpack("H*", $b); --- 477,482 ---- *************** *** 478,483 **** --- 486,502 ---- return $b . pack("C*", 128, (0) x ($bs - length($b) % $bs - 1) ); } + sub _rijndael_compat ($$$) { + my ($b,$bs,$decrypt) = @_; + return unless length $b; + if ($decrypt eq 'd') { + my $hex = unpack("H*", $b); + $hex =~ s/80*$//s; + return pack("H*", $hex); + } + return $b . pack("C*", 128, (0) x ($bs - length($b) % $bs - 1) ); + } + sub get_initialization_vector (\$) { my $self = shift; $self->iv(); *************** *** 628,635 **** 'randomiv' -- Randomiv-compatible "RandomIV" header 'none' -- prepend no header at all ! -padding The padding method, one of "standard", "space", ! "onesandzeroes", or "null". (default "standard") -literal_key If true, the key provided by "key" is used directly for encryption/decryption. Otherwise the actual --- 647,655 ---- 'randomiv' -- Randomiv-compatible "RandomIV" header 'none' -- prepend no header at all ! -padding The padding method, one of "standard" (default), ! "space", "oneandzeroes", "rijndael_compat", ! or "null" (default "standard"). -literal_key If true, the key provided by "key" is used directly for encryption/decryption. Otherwise the actual *************** *** 925,931 **** When the last block of plaintext is shorter than the block size, it must be padded. Padding methods include: "standard" (i.e., PKCS#5), ! "oneandzeroes", "space", and "null". standard: (default) Binary safe pads with the number of bytes that should be truncated. So, if --- 945,951 ---- When the last block of plaintext is shorter than the block size, it must be padded. Padding methods include: "standard" (i.e., PKCS#5), ! "oneandzeroes", "space", "rijndael_compat" and "null". standard: (default) Binary safe pads with the number of bytes that should be truncated. So, if *************** *** 938,951 **** block. If the last block is a full block and blocksize is 8, a block of "8000000000000000" will be appended. null: text only pads with as many "00" necessary to fill the block. If the last ! block is a full block and blocksize is 8, a block of "0000000000000000" will be appended. space: text only same as "null", but with "20". ! Both the standard and oneandzeroes paddings are binary safe. The space and null paddings are recommended only for text data. Which type of padding you use depends on whether you wish to communicate --- 958,978 ---- block. If the last block is a full block and blocksize is 8, a block of "8000000000000000" will be appended. + rijndael_compat: Binary safe, with caveats + similar to oneandzeroes, except that no padding is performed if + the last block is a full block. This is provided for + compatibility with Crypt::Rijndael only and can only be used + with messages that are a multiple of the Rijndael blocksize + of 16 bytes. + null: text only pads with as many "00" necessary to fill the block. If the last ! block is a full block and blocksize is 8, a block of "0000000000000000" will be appended. space: text only same as "null", but with "20". ! Both the standard and oneandzeroes paddings are binary safe. The space and null paddings are recommended only for text data. Which type of padding you use depends on whether you wish to communicate Index: MANIFEST =================================================================== RCS file: /usr/local/cvs_repository/Crypt-CBC/MANIFEST,v retrieving revision 1.15 diff -c -r1.15 MANIFEST *** MANIFEST 13 Aug 2006 02:33:15 -0000 1.15 --- MANIFEST 11 Jan 2008 20:24:40 -0000 *************** *** 16,21 **** --- 16,22 ---- t/IDEA.t t/PCBC.t t/Rijndael.t + t/onezeropadding.t t/Rijndael_compat.t t/func.t t/null_data.t Index: t/Rijndael_compat.t =================================================================== RCS file: /usr/local/cvs_repository/Crypt-CBC/t/Rijndael_compat.t,v retrieving revision 1.6 diff -c -r1.6 Rijndael_compat.t *** t/Rijndael_compat.t 9 Jan 2006 23:47:11 -0000 1.6 --- t/Rijndael_compat.t 11 Jan 2008 20:24:40 -0000 *************** *** 48,54 **** -iv => 'f' x $bs, -literal_key => 1, -header => 'none', ! -padding => 'oneandzeroes' ), "Couldn't create new object"); test(3,$j = Crypt::Rijndael->new('a' x $ks, Crypt::Rijndael->MODE_CBC), --- 48,54 ---- -iv => 'f' x $bs, -literal_key => 1, -header => 'none', ! -padding => 'rijndael_compat', ), "Couldn't create new object"); test(3,$j = Crypt::Rijndael->new('a' x $ks, Crypt::Rijndael->MODE_CBC), Index: t/null_data.t =================================================================== RCS file: /usr/local/cvs_repository/Crypt-CBC/t/null_data.t,v retrieving revision 1.4 diff -c -r1.4 null_data.t *** t/null_data.t 9 Jan 2006 23:47:11 -0000 1.4 --- t/null_data.t 11 Jan 2008 20:24:40 -0000 *************** *** 40,47 **** for my $mod (@in) { for my $pad (@pads) { ! my $cipher = Crypt::CBC->new(-key => 'secret', ! -cipher => $mod, -padding => $pad, ); for my $length (1..128) { --- 40,47 ---- for my $mod (@in) { for my $pad (@pads) { ! my $cipher = Crypt::CBC->new(-key => 'secret', ! -cipher => $mod, -padding => $pad, ); for my $length (1..128) { Index: t/onezeropadding.t =================================================================== RCS file: t/onezeropadding.t diff -N t/onezeropadding.t *** /dev/null 1 Jan 1970 00:00:00 -0000 --- t/onezeropadding.t 11 Jan 2008 20:24:40 -0000 *************** *** 0 **** --- 1,46 ---- + #!/usr/local/bin/perl + + use lib '..','../blib/lib','.','./blib/lib'; + + my (@mods,@pads,@in,$tnum); + + @mods = qw/Rijndael + Blowfish + Blowfish_PP + IDEA + DES + /; + + for $mod (@mods) { + eval "use Crypt::$mod(); 1" && push @in,$mod; + } + + unless ($#in > -1) { + print "1..0 # Skipped: no cryptographic modules found\n"; + exit; + } + + sub test { + local($^W) = 0; + my($num, $true,$msg) = @_; + $$num++; + print($true ? "ok $$num\n" : "not ok $$num $msg\n"); + } + + $tnum = 0; + + eval "use Crypt::CBC"; + test(\$tnum,!$@,"Couldn't load module"); + + my $cipher = Crypt::CBC->new( + -key => 'aaab', + -cipher => 'Rijndael', + -padding => "oneandzeroes", + ); + my $string = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX'; + + my $work = $cipher->encrypt($string); #Encrypt string + my $plain = $cipher->decrypt($work); #...and decrypt + + test(\$tnum,$string eq $plain,"oneandzeroes padding not working\n"); +