The code below is a wrapper class around the AES-128 implementation at http://www.phpclasses.org/browse/package/3650.html and the MCrypt extension. It use the MCrypt extension if it is enabled and use the pure PHP AES-128 class otherwise.
function hex2bin($hex) {
return pack ( "H*", $hex );
}
class Cipher {
public $password;
public $plainText;
public $encryptedText;
public $iv;
public $mode;
const AES_128_ECB = "AES_128_ECB";
const AES_128_CBC = "AES_128_CBC";
public function __construct() {
$this->mode = self::AES_128_ECB;
}
public function encrypt($useSuppliedIV = false) {
if (!$this->plainText) {
return "";
}
switch ($this->mode) {
case self::AES_128_ECB :
case self::AES_128_CBC :
if (strlen($this->password) > 16) {
$this->password = substr($this->password, 0, 16);
}
break;
}
if (function_exists ( "mcrypt_module_open" ) && function_exists ( "mcrypt_create_iv" ) && function_exists ( "mcrypt_generic_init" ) && function_exists ( "mcrypt_generic" ) && function_exists ( "mcrypt_generic_deinit" )) {
switch ($this->mode) {
case self::AES_128_ECB :
$td = mcrypt_module_open ( 'rijndael-128', '', 'ecb', '' );
break;
case self::AES_128_CBC :
$td = mcrypt_module_open ( 'rijndael-128', '', 'cbc', '' );
break;
}
if ($useSuppliedIV) {
if (strlen ( $this->iv ) != mcrypt_enc_get_iv_size ( $td )) {
return null;
}
} else {
$this->iv = mcrypt_create_iv ( mcrypt_enc_get_iv_size ( $td ), MCRYPT_RAND );
}
mcrypt_generic_init ( $td, $this->password, $this->iv );
$this->encryptedText = mcrypt_generic ( $td, $this->plainText );
mcrypt_generic_deinit ( $td );
} else {
$aes = new AES128 ( );
$key = $aes->makeKey ( $this->password );
$plainTextArray = str_split ( $this->plainText, 16 );
$lastIndex = count($plainTextArray) - 1;
if (strlen($plainTextArray[$lastIndex]) != 16) {
for ($i = strlen($plainTextArray[$lastIndex]); $i < 16; $i++) {
$plainTextArray[$lastIndex] .= chr (0);
}
}
$this->encryptedText = "";
if ($useSuppliedIV) {
if (strlen ( $this->iv ) != 16) {
return null;
}
} else {
$this->iv = "";
for ($i = 0; $i < 16; $i++) {
$this->iv .= chr (rand(0, 255));
}
}
switch ($this->mode) {
case self::AES_128_ECB :
for($i = 0; $i < count ( $plainTextArray ); $i ++) {
$this->encryptedText .= $aes->blockEncrypt ( $plainTextArray [$i], $key );
}
break;
case self::AES_128_CBC :
$encryptedTextArray = array();
for ($i = 0; $i < count ( $plainTextArray ); $i ++) {
if ($i == 0) {
$input = $this->iv ^ $plainTextArray[$i];
} else {
$input = $encryptedTextArray[$i - 1] ^ $plainTextArray[$i];
}
$encryptedTextArray[$i] = $aes->blockEncrypt ( $input, $key );
}
$this->encryptedText = join("", $encryptedTextArray);
break;
}
}
}
public function decrypt() {
if (!$this->encryptedText) {
return "";
}
if (function_exists ( "mcrypt_module_open" ) && function_exists ( "mcrypt_create_iv" ) && function_exists ( "mcrypt_enc_get_iv_size" ) && function_exists ( "mcrypt_generic_init" ) && function_exists ( "mcrypt_generic" ) && function_exists ( "mcrypt_generic_deinit" )) {
switch ($this->mode) {
case self::AES_128_ECB :
$td = mcrypt_module_open ( 'rijndael-128', '', 'ecb', '' );
$this->iv = mcrypt_create_iv ( mcrypt_enc_get_iv_size ( $td ), MCRYPT_RAND );
break;
case self::AES_128_CBC :
$td = mcrypt_module_open ( 'rijndael-128', '', 'cbc', '' );
if (strlen ( $this->iv ) != mcrypt_enc_get_iv_size ( $td )) {
return null;
}
break;
}
mcrypt_generic_init ( $td, $this->password, $this->iv );
$this->plainText = mdecrypt_generic ( $td, $this->encryptedText );
mcrypt_generic_deinit ( $td );
} else {
$aes = new AES128 ( );
$key = $aes->makeKey ( $this->password );
$encryptedTextArray = str_split ( bin2hex ( $this->encryptedText ), 32 );
$this->plainText = "";
switch ($this->mode) {
case self::AES_128_ECB :
for($i = 0; $i < count ( $encryptedTextArray ); $i ++) {
$this->plainText .= $aes->blockDecrypt ( hex2bin ( $encryptedTextArray [$i] ), $key );
}
break;
case self::AES_128_CBC :
if (strlen ( $this->iv ) != 16) {
return null;
}
$plainTextArray = array();
for ($i = 0; $i < count ( $encryptedTextArray ); $i ++) {
$output = $aes->blockDecrypt ( hex2bin($encryptedTextArray[$i]), $key );
if ($i == 0) {
$plainTextArray[$i] = $this->iv ^ $output;
} else {
$plainTextArray[$i] = hex2bin($encryptedTextArray[$i - 1]) ^ $output;
}
$this->plainText = join("", $plainTextArray);
}
break;
}
}
$this->plainText = trim ( $this->plainText );
}
}
Save the code above to cipher.php. In addition to this, you will need the AES128.php file from http://www.phpclasses.org/browse/package/3650.html
Here’s an example of AES-128 ECB mode encryption:
include_once ("AES128.php");
include_once ("cipher.php");
$encrypt = new Cipher;
$encrypt->password = "password";
$encrypt->plainText = "this is a very long string that we would like to encrypt using AES128";
$encrypt->encrypt();
echo "encrypted: " . bin2hex( $encrypt->encryptedText ) . "<br>";
$decrypt = new Cipher;
$decrypt->password = "password";
$decrypt->encryptedText = $encrypt->encryptedText;
$decrypt->decrypt();
echo "plain text: " . $decrypt->plainText;
The default mode is ECB. So, we don’t need to set $encrypt->mode and $decrypt->mode to Cipher::AES_128_ECB .
Here’s an example of AES-128 CBC mode encryption using an initialization vector:
include_once ("AES128.php");
include_once ("cipher.php");
$encrypt = new Cipher;
$encrypt->mode = Cipher::AES_128_CBC;
$encrypt->password = "password";
$encrypt->plainText = "this is a very long string that we would like to encrypt using AES128";
$encrypt->encrypt();
echo "iv: " . bin2hex( $encrypt->iv ) . "<br>";
echo "encrypted: " . bin2hex( $encrypt->encryptedText ) . "<br>";
$decrypt = new Cipher;
$decrypt->mode = Cipher::AES_128_CBC;
$decrypt->iv = $encrypt->iv;
$decrypt->password = "password";
$decrypt->encryptedText = $encrypt->encryptedText;
$decrypt->decrypt();
echo "plain text: " . $decrypt->plainText;
Related posts:
