Mario
Mario

Reputation: 1478

Decrypt AES returned from a PHP script in a C# application

First of all, I know that this question is available here a lot - but they are not the ones I want.

I am trying to encrypt data on a PHP script then decrypt it later on a C# application

My current PHP code:

$plaintext = 'My secret message 1234';
$password = '3sc3RLrpd17';
$method = 'aes-256-cbc';

$key = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);

// IV must be exact 16 chars (128 bit)
$iv = chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0);

// av3DYGLkwBsErphcyYp+imUW4QKs19hUnFyyYcXwURU=
$encrypted = base64_encode(openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv));

echo $encrypted;

After that, I want to decrypt the value of $encrypted on my C# application...

I am currently doing it like that:

public string DecryptString(string cipherText, byte[] key, byte[] iv)
{
    // Instantiate a new Aes object to perform string symmetric encryption
    Aes encryptor = Aes.Create();

    encryptor.Mode = CipherMode.CBC;
    //encryptor.KeySize = 256;
    //encryptor.BlockSize = 128;
    //encryptor.Padding = PaddingMode.Zeros;

    // Set key and IV
    encryptor.Key = key.Take(32).ToArray();
    encryptor.IV = iv;

    // Instantiate a new MemoryStream object to contain the encrypted bytes
    MemoryStream memoryStream = new MemoryStream();

    // Instantiate a new encryptor from our Aes object
    ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();

    // Instantiate a new CryptoStream object to process the data and write it to the 
    // memory stream
    CryptoStream cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);

    // Will contain decrypted plaintext
    string plainText = String.Empty;

    try
    {
        // Convert the ciphertext string into a byte array
        byte[] cipherBytes = Convert.FromBase64String(cipherText);

        // Decrypt the input ciphertext string
        cryptoStream.Write(cipherBytes, 0, cipherBytes.Length);

        // Complete the decryption process
        cryptoStream.FlushFinalBlock();

        // Convert the decrypted data from a MemoryStream to a byte array
        byte[] plainBytes = memoryStream.ToArray();

        // Convert the decrypted byte array to string
        plainText = Encoding.ASCII.GetString(plainBytes, 0, plainBytes.Length);
    }
    finally
    {
        // Close both the MemoryStream and the CryptoStream
        memoryStream.Close();
        cryptoStream.Close();
    }

    // Return the decrypted data as a string
    return plainText;
}

string password = "3sc3RLrpd17";

// hash the password with BCrypt
string hashedPassword = BCrypt.Net.BCrypt.HashPassword(password, 12);

// Convert hashed password to array
byte[] key = Encoding.ASCII.GetBytes(hashedPassword);

// Create secret IV
byte[] iv = new byte[16] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };

string decrypted = this.DecryptString(encrypted, key, iv);

But at last, the value of decrypted is the not My secret message 1234

The error I get is: Padding is invalid and cannot be removed.

DISCLAIMER: I have the BCrypt package installed.

I think that the problem is in the iv.

I've tried a lot to fix it.

Any help would be appreciated.

Thanks!

Upvotes: 1

Views: 189

Answers (1)

odan
odan

Reputation: 4952

Try to change the following code in the EncryptString and DecryptString function:

Old

encryptor.Key = key.Take(32).ToArray();

New

byte[] aesKey = new byte[32];
Array.Copy(key, 0, aesKey, 0, 32);
encryptor.Key = aesKey;

PS: Your error messages means, that the AES key is not correct. Make sure you are using the same key and iv for encryption and decryption.

Upvotes: 1

Related Questions