DEV Community

Scotticles
Scotticles

Posted on • Updated on

Perl is dead simple with CBC Block Encryption

INTRO

I hope this blog post will help someone with CryptX.

My disclaimer: I am not an expert in cryptography.

I first started using Crypt::CBC but I liked how CryptX had more modules, better maintained and it was faster. I moved my system over to CryptX. In Crypt, the CBC piece was done more for you, where Crypt::Mode::CBC requires a little more from the developer to configure it.

WHY?

I am designing a system and needed a way to take files uploaded by users and encrypt them before storing them until needed. S3 has it built it, I know but I didn't want to rely on that. I decided to use CBC block as my encryption method. I also had to encrypt text and store them in the database, I can use the same encryption methods for both tasks. If you plan on storing in a database, remember these are bytes and needs to be a blob type.

HOW?

Here is the Crypt::Mode::CBC snippet

use Crypt::Mode::CBC;
my $m = Crypt::Mode::CBC->new('AES');

#(en|de)crypt at once
my $ciphertext = $m->encrypt($plaintext, $key, $iv);
Enter fullscreen mode Exit fullscreen mode

Crypt::Mode::CBC

It uses AES, requires a $key and a $iv. AES is one of the many Ciphers to use. The padding by default is PKCS5 padding.

vulnerabilities-cbc-mode - Extra Reading

What the heck is the IV?

The IV is 'initialization vector'. To make each message unique, an initialization vector must be used in the first block. IV Resource

I generate a IV for each encrypted object and store it in the database for when decryption is needed.
IV Resource

Here is a full example.
I use Mojo::File for file manipulation, it makes things easy.

Just to note, rand() is not cryptographically secure. Please see the doc for picking the right module, if you need a secure implementation. In this example I am using Math::Random::Secure that replaced the native rand()
https://perldoc.perl.org/functions/rand

Requires Modules:

  • Crypt::Mode::CBC
  • Mojo::File
  • Modern::Perl
  • Crypt::Digest::SHA512_256
  • Math::Random::Secure
use Crypt::Mode::CBC;
use Mojo::File;
use Modern::Perl;
use warnings;
use strict;
use Crypt::Digest::SHA512_256 qw( sha512_256_hex );
use Math::Random::Secure qw(rand);
my $key =  sha512_256_hex(rand(1000));
my $iv =  sha512_256_hex(rand(1000));

# Lets print out the IV and KEY for fun.
say $key;
say substr($iv, 0, 32);

my $cbc = Crypt::Mode::CBC->new('AES');

# Encrypt
my $file = Mojo::File->new('plainfile.txt');

my $ciphertext = $cbc->encrypt($file->slurp, pack("H*", $key), pack("H*", substr($iv, 0, 32)));

my $encFile = Mojo::File->new('plainfile.txt.crypted');
$encFile->spurt($ciphertext);

# Move the old file
$file->move_to('plainfile.txt.backup');
$file->new('plainfile.txt');

# Decrypt

my $plaintext = $cbc->decrypt($encFile->slurp, pack("H*", $key), pack("H*", substr($iv, 0, 32)));

$file->spurt($plaintext);
# this should print out the data and if you cat the file plainfile.txt, it should print out the data.
say $plaintext;
Enter fullscreen mode Exit fullscreen mode

If you run this, you will have a few files to look at.

Latest comments (2)

Collapse
 
thibaultduponchelle profile image
Tib • Edited

Great article ! Thank you 👍

I think you can highlight syntax by adding « perl » to your « quote quote quote »

Collapse
 
scotticles profile image
Scotticles

Thanks :D, added the perl syntax, was trying to figure that out but gave up. Looks way better.