Category Archives: Bash

CAST-128 encryption in practice

Published / by prscientist

 

This symmetric-key block cipher comes in handy as it allows a variable key size of 40 to 128 bits and a block size of 64 bits. According to RFC2144 there is no difference between CAST-128 and CAST5, these are two names of a same thing.

 

Even if widely regarded unsafe, some of us still have reasons for using a smaller key. Other people should go for the full 128 bit key.

We will discuss how you encrypt a text with openssl and decrypt it from php, along with a couple of subtleties for the beginner crypto user. For this example we will use CAST-128 with a 64 bit key.

Common questions for block ciphers:

  • how does the block size impact the plaintext? which kind of padding is being applied pre-encryption? — depending on the params, openssl may use the PKCS#5 padding algorithm or in case of zero padding it may expect the plaintext to be pre-paded/have its length multiple of block length
  • is the PKCS#5 padding similar to PKCS#7? — “PKCS#5 padding is identical to PKCS#7 padding, except that it has only been defined for block ciphers that use a 64-bit (8-byte) block size. In practice the two can be used interchangeably.” Source: Padding (cryptography).
  • what initialization vector (iv) we use for CAST-128? — When we encode in CBC mode, “The iv is optional and defaults to all-zero.”. Source: RFC2144 

OpenSSL

  • Depending on your platform along with your openssl version, params might not be the same, here all been tested on a macOS Big Sur ver.11.4 with version OpenSSL 1.1.1i
  • To encrypt with a 64 bit key, which is a medium key length supported by CAST-128 please note, the openssl will be padding your key up to 128 bit. Zeros will be added. So if you call openssl with enc -K “ABCDABEFAABBCCDD” which is a 64 bit key, in reality key will be ABCDABEFAABBCCDD0000000000000000  
  • Make sure the input file does not contain any extra chars such as LF. Consider as input a file containing ANNABELLE in plain text
MacBook-Pro:~ alexandru$ openssl enc -K "ABCDABEFAABBCCDD" -cast -e -in input.txt -out output.base64 -iv 0000000000000000 -nosalt -base64 -p
hex string is too short, padding with zero bytes to length
key=ABCDABEFAABBCCDD0000000000000000
iv =0000000000000000

MacBook-Pro:~ alexandru$ cat output.base64
M11VwvXjPq5sWTrZr4KNDA==

PHP

  • From PHP are calling the openssl_decrypt and not the obsolete mcrypt_decrypt
  • Due to the OPENSSL_RAW_DATA we are preparing most params as binary, with the only exception: $method
  • The $decrypt_result will be plain text
$method = "CAST5-CBC";
$secret_key = hex2bin("ABCDABEFAABBCCDD"); //hex string transformed into binary

$encrypted_msg = "M11VwvXjPq5sWTrZr4KNDA=="; //note, this is base64
$raw_encrypted_msg = base64_decode($encrypted_msg);

$iv = hex2bin("0000000000000000"); //hex string transformed into binary

if (is_bool($decrypt_result = openssl_decrypt($raw_encrypted_msg, $method, $secret_key, OPENSSL_RAW_DATA, $iv)))
echo "FAILED!";
else
echo $decrypt_result;

Tricks

  • to find what kind of padding your openssl inserted on your plaintext: encrypt normally then decrypt adding the -nopad parameter, the PKCS#5 / PKCS#7 is NOT padding with zeros
openssl enc -K "ABCDABEFAABBCCDD" -cast -e -in input.txt -out output.base64 -iv 0000000000000000 -nosalt -base64
openssl enc -K "ABCDABEFAABBCCDD" -cast -d -in output.base64 -out output.dec -iv 0000000000000000 -nosalt -base64 -nopad

References