I am trying to convert VB.NET Encrypt/Decrypt to PHP. The issue is we can not update the PHP version and the server supports only PHP5.3
VB.NET Sample Output Link
http://www.tattoogenda.com/LoginTest.aspx
VB.NET Output is: Ao5ZnFYo344iWqv/Jr9euw==
PHP OutPut is: NzmRRxTaXgWFIPx/SqODog==
VB.NET Code as below:
Public Shared Function Encrypt(clearText As String) As String
Dim EncryptionKey As String = "MAKV2SPBNI99212"
Dim clearBytes As Byte() = Encoding.Unicode.GetBytes(clearText)
Using encryptor As Aes = Aes.Create()
Dim pdb As New Rfc2898DeriveBytes(EncryptionKey, New Byte() {&H49, &H76, &H61, &H6E, &H20, &H4D,
&H65, &H64, &H76, &H65, &H64, &H65,
&H76})
encryptor.Key = pdb.GetBytes(32)
encryptor.IV = pdb.GetBytes(16)
Using ms As New MemoryStream()
Using cs As New CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write)
cs.Write(clearBytes, 0, clearBytes.Length)
cs.Close()
End Using
clearText = Convert.ToBase64String(ms.ToArray())
End Using
End Using
Return clearText
End Function
Public Shared Function Decrypt(cipherText As String) As String
Dim EncryptionKey As String = "MAKV2SPBNI99212"
Dim cipherBytes As Byte() = Convert.FromBase64String(cipherText)
Using encryptor As Aes = Aes.Create()
Dim pdb As New Rfc2898DeriveBytes(EncryptionKey, New Byte() {&H49, &H76, &H61, &H6E, &H20, &H4D,
&H65, &H64, &H76, &H65, &H64, &H65,
&H76})
encryptor.Key = pdb.GetBytes(32)
encryptor.IV = pdb.GetBytes(16)
Using ms As New MemoryStream()
Using cs As New CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write)
cs.Write(cipherBytes, 0, cipherBytes.Length)
cs.Close()
End Using
cipherText = Encoding.Unicode.GetString(ms.ToArray())
End Using
End Using
Return cipherText
End Function
PHP Test link Output:
http://www.tattoogenda.com/app-api/logintest.php
PHP Code:
<?php
include_once('PBKDF2.php');
use PBKDF2PBKDF2;
function encrypt_decrypt($action, $string) {
$output = false;
$encrypt_method = "AES-256-CBC";
//$encrypt_method = "AES-128-CBC";
$secret_key = 'MAKV2SPBNI99212';
$secret_iv=chr(0x49).chr(0x76).chr(0x61).chr(0x6e).chr(0x20).chr(0x4d).chr(0x65).chr(0x64).chr(0x76).chr(0x65).chr(0x64).chr(0x65).chr(0x76);
$generated_key = PBKDF2::deriveKey("sha256", $secret_key, $secret_iv, 20000, 128, true, false);
$key = substr($generated_key, 0, 32);;
//$key = substr(hash('sha1', $secret_key), 0, 32);;
echo "key: ".$key."<br>";
$iv = substr($generated_key, 0, 16);
//$iv = substr(hash('sha1', $secret_iv), 0, 16);
echo "iv key: ".$iv."<br>";
if( $action == 'encrypt' ) {
$output = openssl_encrypt($string, $encrypt_method, $key, $options=OPENSSL_RAW_DATA,$iv );
$output = base64_encode($output);
}
else if( $action == 'decrypt' ){
$output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, $options=OPENSSL_RAW_DATA, $iv);
}
return $output;
}
$plain_txt = "1234";
echo "Plain Text = $plain_txtn"."<br/>";
$plain_txt = mb_convert_encoding($plain_txt, "UTF-8" , "UTF-16LE");
echo "Encoded Plain Text = $plain_txtn"."<br/>";
$encrypted_txt = encrypt_decrypt('encrypt', $plain_txt);
echo "Encrypted Text = $encrypted_txtn"."<br/>";
$decrypted_txt = encrypt_decrypt('decrypt', $encrypted_txt);
echo "Decrypted Text = $decrypted_txtn"."<br/>";
if( $plain_txt === $decrypted_txt ) echo "SUCCESS"."<br/>";
else echo "FAILED"."<br/>";
echo "n"."<br/>";
?>
2
Answers
The VB code uses a 32 bytes key so in the PHP code
AES-256-CBC
is correct. AlsoRfc2898DeriveBytes()
applies an iteration count of 1000 by default (and SHA1 as digest), which must therefore also be used in the PHP code. Since the VB code derives both, the 32 bytes key and the IV, 32 + 16 must be specified as size in the PHP code:Of the returned result, the first 32 bytes are the key, the following 16 bytes are the IV:
$
key
and $iv
are to be used directly inopenssl_encrypt()/decrypt()
, i.e. the explicit hashing with SHA1 is to be removed for key and IV.The passed plaintext must be UTF-16LE encoded before encryption (either inside or outside of
encrypt_decrypt()
), e.g. withNote that the start encoding is the third parameter and the destination encoding is the second parameter.
An encryption of
Hello Asif
returns1N1U0Oy81PGOm/Yqdp9sT5iyPgPFxsc8Q8mADNa8BzQ=
in accordance with the VB code.For decryption, the procedure is analogous.
Note that for security reasons the salt (denoted here as
$secret_iv
) should be randomly generated for each key derivation. The salt is not secret and can be sent along with the ciphertext (usually concatenated). Also, an iteration count of 1000 is generally too small for PBKDF2.