I have been having difficulties encrypting in PHP and then properly decrypting it in C#. I believe I have gotten to the heart of the issue - some reason the data being encrypted by openssl_encrypt does not seem to add the proper padding.
I keep getting an error message in Visual Studio that the input was not a full block. I tried placing some breakpoints and discovered that the size of the cipher text is indeed wrong (I think) - 24 bytes. Both the IV and Key length are correct (16 and 32 respectively), but the input is not (based on the block size, it should have been padded to 32 bytes - right?). I was under the impression that openSSL used PKCS7 padding by default, but that does not seem to be the case.
What am I doing wrong, is PHP not doing the padding correctly, or am I somehow stripping it when I write it to text file and copy and paste? Oddly enough, I can decrypt it just fine in PHP using the following:
openssl_decrypt(hex2bin("6a7a36662f337042666e3159374331504269486e56413d3d"), "aes-256-cbc", hex2bin("myKey"), 0, hex2bin("3a6f13459776c43f81737d72fea03b67"));
Here is the PHP:
try {
// DO ONLY ONCE //
/* $handler = fopen("../../etc/insurance.txt", "w");
fwrite($handler, bin2hex(openssl_random_pseudo_bytes(32))); // convert to hex
fclose($handler);
*/
$passFile = '../../etc/insurance.txt';
$handler = fopen($passFile, 'r');
$key = fread($handler, filesize($passFile));
$key = hex2bin($key); // openssl_encrypt expects binary, convert back
fclose($handler);
} catch (Exception $e) {
echo $e->getMessage();
}
part of the class used for encryption:
class dataHandler {
private $keyString;
private $employee;
function __construct($key, $employeeID) {
$this->keyString = $key; // encrypt sensitve data
$this->employee = $employeeID; // random id for identification
}
private function encrypt($data) {
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(METHOD));
$encrypted = openssl_encrypt($data, METHOD, $this->keyString, 0, $iv);
// both encrypted and $iv are binary, convert to hex for writing
$encrypted = bin2hex($encrypted );
$iv = bin2hex($iv);
$encrypted .= ":" . $iv; // append iv for access later
retu $encrypted;
}
public function insertEmployee($ssn, $lastName, $firstName, $gender, $email, $address, $location, $birth, $decision, $dependents, $vision) {
if(!$vision ) {
$vision = 'declined';
}
$employeeData = "id,ssn,last,first,gender,email,address,location,birth,decision,dependents,vision" . PHP_EOL;
$employeeData .= "$this->employee, $ssn, $lastName, $firstName, $gender, $email, $address, $location, $birth, $decision, $dependents, $vision";
retu $employeeData;
}
and an example of how it might be used
$dh = new dataHandler($key, $employeeID);
$employeeData = $dh->insertEmployee($ssn, $lastName, $firstName, $gender, $email, $address, $location, $birth, $selectedPlan, $eligibleDependents, $vision);
I think the issue is in the PHP rather than the C#, but I will include the latter just in case:
namespace Decryption
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private byte[] hexToBin(String hexString) {
int charCount = hexString.Length;
byte[] output = new byte[charCount / 2];
for(int i = 0; i < charCount; i += 2) {
output[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
}
retu output;
}
private void decrypter (byte[] cipherText, byte[] key, byte[] iv) {
String outputString;
try
{
using (Aes myAes = Aes.Create())
{
myAes.KeySize = 256;
myAes.Mode = CipherMode.CBC;
myAes.Key = key;
myAes.IV = iv;
myAes.Padding = PaddingMode.
ICryptoTransform myDecrypter = myAes.CreateDecryptor(myAes.Key, myAes.IV);
using (MemoryStream memory = new MemoryStream(cipherText))
{
using (CryptoStream cryptStream = new CryptoStream(memory, myDecrypter, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(cryptStream))
{
outputString = reader.ReadToEnd();
}
}
}
}
System.IO.File.WriteAllText("test.txt", outputString);
}
catch (Exception e)
{
Console.Write(e.Message);
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
byte[] cipher = this.hexToBin("51436c6777374c576d423570487941626850736969513d3d");
byte[] iv = this.hexToBin("6fea9ed1032cf452f7fe72b2af698721");
byte[] key = this.hexToBin("47062ee9fba8eff4b83626e67b26ef1ffc506936a980f8c71641202c51698716");
this.decrypter(cipher, key, iv);
}
}
}
I have been struggling with this for some time now, so I would really appreciate any help.
Thanks!
