1
votes

i am trying to encrypt and then decrypt a file using Crypt::CBC in perl. When decrypting my ciphertext after encrypting it, i am missing some bytes at the end of my recovered plaintext.

encryption method:

#!/usr/bin/perl

use 5.24.0;
use warnings;
use Crypt::CBC;

my $cipher;
my $buffer;

   $cipher = Crypt::CBC->new( {'key'             => 'abcdefgh',
                               'literal_key'     => 1, 
                     # 'cipher'          => 'Blowfish',
                              'iv'              => '01234567',
                           #   'regenerate_key'  => 0,   # default true
                              'padding'         => 'standard',
                              'prepend_iv'      => 0,
                              'blocksize'       => 8
                           });

$cipher->start('encrypting');
open(F,"./plaintext.txt");
open(STDOUT,">ciphertext.txt");
  while (sysread(F,$buffer,1024)) {
      print $cipher->crypt($buffer);
  }
close STDOUT;

my plaintext looks like this:

plaintext before

then i decrypt my ciphertext with:

#!/usr/bin/perl
# # entschlüsselt eine datei, http://www.perlmonks.org/?node_id=252460

use 5.24.0;
use warnings;
use Crypt::CBC;

my $cipher;
my $buffer;

   $cipher = Crypt::CBC->new( {'key'             => 'abcdefgh',
                              'literal_key'     => 1, 
                              #'cipher'          => 'Blowfish',
                              'iv'              => '01234567',
                            #  'regenerate_key'  => 0,   # default true
                              'padding'         => 'standard',
                              'prepend_iv'      => 0,
                              'blocksize'       => 8
                           });

$cipher->start('decrypting');
open(F,"./ciphertext.txt")
  while (sysread(F,$buffer,1024)) {
      print $cipher->crypt($buffer);

  }
close STDOUT;

and the plaintext afterwards:

plaintext after

1
Reopening STDOUT like that is an odd way of doing this. Could you try opening a separate, non-default filehandle? I wonder if doing it this way is causing it not to get flushed the way you expect.frezik
While it may not have an effect in this particular situation, you want interactions with ciphertext.txt to be done using :raw handles since it's a "binary" file, not a text file (despite the extension).ikegami
Tip: Using a constant IV is irresponsible and severly weakens your encryption. Let CBC pick a random one!ikegami
... and prefix the IV to the ciphertext (it has a constant size). But that's the fourth issue with the code above, I guess you (ichtyp) need to read more into file handling and cryptography before continueing.Maarten Bodewes
@frezik: I'am now using a separate filehandler, which helped me to get rid of problems with CR LF formatting at the end of the lines.ichtyp

1 Answers

2
votes

You’re missing a call to $cipher->finish; after the loop, for both encrypting and decrypting, so you’re cutting of part of the last block in both cases.

The CBC algorithm must buffer data blocks internally until they are even multiples of the encryption algorithm's blocksize (typically 8 bytes). After the last call to crypt() you should call finish(). This flushes the internal buffer and returns any leftover ciphertext.

You need something like this:

while (sysread(F,$buffer,1024)) {
    print $cipher->crypt($buffer);
}
print $cipher->finish;

(You’re also missing a semicolon at the end of the open line in your decryption code.)