in reply to Re^3: line by line Encryption fun with Crypt::CBC and Rijndael? File Ownership issues? (code)
in thread line by line Encryption fun with Crypt::CBC and Rijndael? File Ownership issues?

Hi, I am trying to use your code and I get the "Unexpected end of file" error while decrypting.

The call to SUB read_uint32 works fine the first time and the value of $to_read = 4 in SUB read_bytes. Inside SUB read_bytes in the while ($to_read) loop, the value of $buf = 'Rand' (the first 4 characters in my encrypted file).

Once SUB read_unit32 returns control to SUB read_str, the value of $length is set at some large number. I get an error during the call: read_bytes($fh, $length).

It attempts to read $length the first time around, so say length = 825373492 was passed to read_bytes. Then, to_read = 825373492 The first iteration through the while loop decrements $to_read as below: WHILE to_read = 825370130

However, in the next iteration I get the error.

13:05:54 ERROR ***** 13:05:54 Unexpected end of file

Could you please help or guide me in the right direction? I apologize if my elaborating the problem in this way causes problems. I wasn't sure on how else to do it. Thanks, Sam
  • Comment on Re^4: line by line Encryption fun with Crypt::CBC and Rijndael? File Ownership issues? (code)

Replies are listed 'Best First'.
Re^5: line by line Encryption fun with Crypt::CBC and Rijndael? File Ownership issues? (code)
by ikegami (Patriarch) on Jul 25, 2008 at 02:38 UTC
    Are you sure the file was created using my write_str? The point of this thread was to create an appendable encrypted file format. I proposed such a file format, my encrypter produces it, and my decrypter decrypts it (and only it).
    >perl 700015.pl Hello World foo bar >debug data.enc -rcx CX 0040 : -d100 l40 0100 00 00 00 20 53 61 6C 74-65 64 5F 5F 90 66 5E D2 ... Salted__.f^. ^^^^^^^^^^^ 0110 88 43 CE 87 E6 FE 44 DA-2C E8 84 FF 2B 2B A1 84 .C....D.,...++.. 0120 FD BB 96 89 00 00 00 18-53 61 6C 74 65 64 5F 5F ........Salted__ ^^^^^^^^^^^ 0130 1F 12 77 C8 38 9A 4B 69-A2 33 51 9D 03 60 50 27 ..w.8.Ki.3Q..`P' -q

    You seem to be missing the higlighted parts.

    700015.pl:

    use strict; use warnings; use Crypt::CBC qw( ); my $qfn = 'data.enc'; sub read_bytes { my ($fh, $to_read) = @_; my $buf = ''; while ($to_read) { my $bytes_read = read($fh, $buf, $to_read, length($buf)); die("$!\n") if !defined($bytes_read); die("Unexpected end of file\n") if !$bytes_read; $to_read -= $bytes_read; } return $buf; } sub read_uint32 { my ($fh) = @_; return (unpack('N', read_bytes($fh, 4))); } sub read_str { my ($fh) = @_; my $length = read_uint32($fh); return read_bytes($fh, $length); } sub write_uint32 { my ($fh, $n) = @_; print $fh (pack('N', $n)); } sub write_str { my ($fh, $str) = @_; print $fh (pack('N', length($str)), $str); } { my $key = Crypt::CBC->random_bytes(8); my $cipher = Crypt::CBC->new({ key => $key, cipher => 'Blowfish' }) +; { open(my $fh, '>', $qfn) or die; binmode($fh); write_str($fh, $cipher->encrypt("Hello World")); write_str($fh, $cipher->encrypt("foo bar")); } { open(my $fh, '<', $qfn) or die; binmode($fh); while (!eof($fh)) { print($cipher->decrypt(read_str($fh)), "\n"); } } }

    (Blowfish was used since I'm having a linking problem with Rjindael. You should get similar results with both)

      Thank you very much for your help. I changed the pack/unpack to little-endian order and that worked. If I have to encrypt something on an outside machine and decrypt it at my end (using the encrypter and decrypter above), do they both have to be the same endian?

      Could I use your recommendation above to encrypt and decrypt large files (about 3 million records) or would you have any suggestions or reference points you could guide me to?

      As a useless side-note: I use Tera Term Pro version 2.3 and sometimes when I 'more' the encrypted and decrypted files, my entire charset on the terminal gets funky.

      Thanks again.

        If I have to encrypt something on an outside machine and decrypt it at my end (using the encrypter and decrypter above), do they both have to be the same endian?

        If you store 0x11223344 into the file, you'd rather not read 0x44332211 from the file.

        Thank you very much for your help. I changed the pack/unpack to little-endian order and that worked

        I used 'N', which produces the same encoding on all systems. Why did you change it?

        Could I use your recommendation above to encrypt and decrypt large files (about 3 million records) or would you have any suggestions or reference points you could guide me to?

        The format is efficient for appending records semi-frequently, but it's quite wasteful otherwise. Your 300MB might very well take up 600MB, and it could take a while to decode.

        If you have a write-once-read-often scenario, you'd be better off converting the record file into a normal (single encryption session) file before doing your reading.

        An alternative to the entire approach would be to have a persistent deamon which handles writting to the file (as a single encryption session). This would definitely be better if you had a near-constant stream of records to write.

        my entire charset on the terminal gets funky.

        Programs control the terminal by sending special character sequences in-band. The encrypted data can contain any characters, including some that resemble terminal control sequences.

        more and/or less replace "dangerous" characters with representative glyphs. There's also od.