Perl is dead simple with CBC Block Encryption
Tags: perl, encryption, cbc, cryptx
Published: 2020-12-08 22:25:38



# INTRO
I hope this blog post will help someone with [CryptX](https://metacpan.org/pod/CryptX). 

**My disclaimer:** I am not an expert in cryptography. 

I first started using [Crypt::CBC](https://metacpan.org/pod/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](https://metacpan.org/pod/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

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

#(en|de)crypt at once
my $ciphertext = $m->encrypt($plaintext, $key, $iv);
```
[Crypt::Mode::CBC](https://metacpan.org/pod/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](https://docs.microsoft.com/en-us/dotnet/standard/security/vulnerabilities-cbc-mode)

## 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](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_block_chaining_(CBC))

I generate a IV for each encrypted object and store it in the database for when decryption is needed.
[IV Resource](http://www.ciphersbyritter.com/NEWS6/CBCIV.HTM)

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](https://perldoc.perl.org/functions/rand)

**Requires Modules:**

* Crypt::Mode::CBC
* Mojo::File
* Modern::Perl
* Crypt::Digest::SHA512_256
* Math::Random::Secure

```perl
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;
```

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