Skip to content
Advertisement

Convert VB.NET Encrypt/Decript old code to PHP 5.3

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/>";

?>

Advertisement

Answer

The VB code uses a 32 bytes key so in the PHP code AES-256-CBC is correct. Also Rfc2898DeriveBytes() 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:

$generated_key =  PBKDF2::deriveKey("sha1", $secret_key, $secret_iv, 1000, 32+16, true, false);

Of the returned result, the first 32 bytes are the key, the following 16 bytes are the IV:

$key = substr($generated_key, 0, 32);
$iv = substr($generated_key, 32, 16);

$key and $iv are to be used directly in openssl_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. with

$string =  mb_convert_encoding($string, 'utf-16le', 'utf-8');

Note that the start encoding is the third parameter and the destination encoding is the second parameter.

An encryption of Hello Asif returns 1N1U0Oy81PGOm/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.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement