Sep 6 2012
Encrypt in VB.NET and Decrypt in PHP 4 Using Phpseclib0.3.0
Originally I had found code from: Encrypt in VB.NET and Decrypt in PHP and Vice Versa .
Everything worked well, until I realized that the specific webserver I was writing code for ran PHP 4…No mcrypt_decrypt.
Hence I discovered PHPSecLib has the Rijndael algorithm implemented as PHP code.
Following please find code to check if mcrypt exists and react differently (where $line is the encrypted text):
if(function_exists('mcrypt_decrypt'))
$dec = decryptRJ256($ky, $iv, $line);
else
$dec = decryptRJ256_PHPSECLIB($ky, $iv, $line);
Below please find the decryptRJ256() and decryptRJ256_PHPSECLIB() functions.
include('includes/phpseclib0.3.0/Crypt/Rijndael.php');
function decryptRJ256($key,$iv,$string_to_decrypt)
{
$string_to_decrypt = base64_decode($string_to_decrypt);
$rtn = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $string_to_decrypt, MCRYPT_MODE_CBC, $iv);
$rtn = rtrim($rtn, "4");
return($rtn);
}
function decryptRJ256_PHPSECLIB($key,$iv,$string_to_decrypt)
{
$string_to_decrypt = base64_decode($string_to_decrypt);
$cipher = new Crypt_Rijndael(); // could use CRYPT_RIJNDAEL_MODE_CBC
$cipher->setKeyLength(256);
$cipher->setBlockLength(256);
$cipher->setKey($key);
$cipher->setIV($iv); // defaults to all-NULLs if not explicitely defined
$cipher->paddable = false; //WILL NOT WORK WITHOUT paddable=false
$rtn = $cipher->decrypt($string_to_decrypt);
$rtn = rtrim($rtn, "4");
return($rtn);
}
Please note the decryption does not work until $cipher->paddable = false; is set.
Specifically, within the decrypt() function of CryptRijndael.php,
having paddable=true causes the _unpad command to be used which leads to the returned decrypted $plaintext to become “”. Line 940 in Rijndael.php of PhpSecLib 0.3.0.
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
Below finally also the VB.net code which is not much changed from Encrypt in VB.NET and Decrypt in PHP and Vice Versa .
Public Function EncryptRJ256(ByVal prm_key As String, ByVal prm_iv As String, ByVal prm_text_to_encrypt As String)
Dim sToEncrypt As String = prm_text_to_encrypt
Dim myRijndael As New RijndaelManaged
myRijndael.Padding = PaddingMode.Zeros
myRijndael.Mode = CipherMode.CBC
'myRijndael.KeySize = 256
myRijndael.BlockSize = 256
Dim encrypted() As Byte
Dim toEncrypt() As Byte
Dim key() As Byte
Dim IV() As Byte
key = System.Text.Encoding.ASCII.GetBytes(prm_key)
IV = System.Text.Encoding.ASCII.GetBytes(prm_iv)
Dim encryptor As ICryptoTransform = myRijndael.CreateEncryptor(key, IV)
Dim msEncrypt As New MemoryStream()
Dim csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
toEncrypt = System.Text.Encoding.UTF8.GetBytes(sToEncrypt)
csEncrypt.Write(toEncrypt, 0, toEncrypt.Length)
csEncrypt.FlushFinalBlock()
encrypted = msEncrypt.ToArray()
Return (Convert.ToBase64String(encrypted))
End Function
Sep 07, 2012 @ 03:44:20
$cipher->paddable = false; //WILL NOT WORK WITHOUT paddable=false
Try $cipher->disablePadding() instead.
Also, fyi, phpseclib, itself, uses mcrypt if it’s available.
Sep 07, 2012 @ 15:16:50
Ofcourse 🙂 Unfortunately though in the specific PHP 4 server mcrypt did not exist.
Also,why wait for phpseclib to find if mcrypt exists. You can check yourself and avoid loading Rijndael.php and increasing the size of your call stack.
Obviously, should rename the includes to require_once and include within the decrypt function as it’s not worth it to include for servers having mcrypt_decrypt.
function decryptRJ256_PHPSECLIB($key,$iv,$string_to_decrypt)
{
require_once(‘includes/phpseclib0.3.0/Crypt/Rijndael.php’);
$string_to_decrypt = base64_decode($string_to_decrypt);
$cipher = new Crypt_Rijndael(); // could use CRYPT_RIJNDAEL_MODE_CBC
$cipher->setKeyLength(256);
$cipher->setBlockLength(256);
$cipher->setKey($key);
$cipher->setIV($iv); // defaults to all-NULLs if not explicitely defined
$cipher->paddable = false; //WILL NOT WORK WITHOUT paddable=false
$rtn = $cipher->decrypt($string_to_decrypt);
$rtn = rtrim($rtn, “4”);
return($rtn);
}
Sep 19, 2012 @ 23:55:54
Hmm..Comment, if decryptRJ256_PHPSECLIB is called more than once (e.g. in a loop) it’s better to move the require_once out of the loop. I see a lot of discussions about overhead caused by it, e.g.: http://stackoverflow.com/questions/186338/why-is-require-once-so-bad-to-use