Perl is dead simple with CBC Block Encryption
Scotticles
Posted on December 8, 2020
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);
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;
If you run this, you will have a few files to look at.
Posted on December 8, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.