2

The code below is a simple .NET snippet, having test on the input it returns p+cTm2VODfvQnreAl02wUQ== as an output.

Dim aesEncryptObj As New System.Security.Cryptography.RijndaelManaged()
Dim encoder As System.Text.ASCIIEncoding = New System.Text.ASCIIEncoding()

Dim tempKey As Byte() = encoder.GetBytes("00000011111111111111111111111111")
aesEncryptObj.Key = tempKey
aesEncryptObj.BlockSize = 128
aesEncryptObj.Mode = System.Security.Cryptography.CipherMode.ECB
aesEncryptObj.Padding = System.Security.Cryptography.PaddingMode.PKCS7
aesEncryptObj.GenerateIV()

Dim EncryptedBytes As Byte()
Dim encryptor As System.Security.Cryptography.ICryptoTransform = aesEncryptObj.CreateEncryptor(aesEncryptObj.Key, aesEncryptObj.IV)

Using msEncrypt As New System.IO.MemoryStream()
    Using csEncrypt As New System.Security.Cryptography.CryptoStream(msEncrypt, encryptor, System.Security.Cryptography.CryptoStreamMode.Write)
        Using swEncrypt As New System.IO.StreamWriter(csEncrypt)
            swEncrypt.Write(txtInput.Text)
        End Using
        EncryptedBytes = msEncrypt.ToArray()
    End Using
End Using

txtOutput.Text = Convert.ToBase64String(EncryptedBytes)

Now, here is the PHP code:

const ENCRYPT_METHOD = 'aes-256-ecb';

$aesKey = pack('H*', '00000011111111111111111111111111');
$ivSize = openssl_cipher_iv_length(ENCRYPT_METHOD);

$plainText = "test";

$iv = openssl_random_pseudo_bytes($ivSize);

$cipherText = openssl_encrypt(
    $plainText,
    ENCRYPT_METHOD,
    $aesKey,
    OPENSSL_RAW_DATA,
    $iv
);

$encryptedText = $iv . $cipherText;

echo base64_encode($encryptedText);

It returns 1W3UvYVNKWEoFrpPZPd+Qw== which differs from the .NET one. I've tried both aes-256-ecb and aes-128-ecb and the result is always different from the .NET's one.

As far as I know, openssl_encrypt do the PKCS7 padding by default, is that right? Can you see the reason why PHP is giving different result?

Stanimir Stoyanov
  • 1,623
  • 18
  • 29

1 Answers1

5

Your code isn't working because:

  • GetBytes in .NET returns you the byte values of that string. That is, you are going to get a byte array with a length of 32 (AES-256). However, pack in PHP with H* decodes a hex string, which is going to give you a key of length 16 (AES-128). This whole time you've been encrypting with not only two different keys, but two different key sizes.

Fixing the above will make your code work, but it will be far from actually secure and should not be used. If you want to make your code secure, you need to:

  • Stop using ECB mode. Use GCM mode if you can, CBC otherwise. You are most likely going to end up using CBC. If you do, you need to prepend the IV to your ciphertext so that the decrypting party can retrieve it and use it when decrypting. IVs don't need to be secret, they just need to be random, so your use of OpenSSL random bytes and the GenerateIV method is good.
  • Since you are likely going to be using CBC mode, you will need to apply an HMAC to ensure integrity. Otherwise anyone can modify your ciphertext and you won't know. When applying an HMAC, always encrypt-then-mac. Remember to include your IV before applying the HMAC.
  • Lastly, and I don't think you actually meant to do this, but never use the ASCII values of a string as a key. If you want to create a key from a passphrase, you should apply a KDF. PBKDF2 is probably the best suited and has implementations in both PHP and .NET.
Luke Joshua Park
  • 9,527
  • 5
  • 27
  • 44
  • Thank you for the complete analysis of the issue. I'm going to investigate it further and accept the answer later in the day. – Stanimir Stoyanov Dec 07 '16 at 09:34
  • You nailed it! I'm aware that ECB mode is not secure, but I'm working with a closed-source device which is sending me the encrypted data. This will be the next thing to do - ask for a change in the mode when the communication protocol is verified to be fully implemented. Thank you once again, you saved my day as I have almost no knowledge in .NET, and yes, most probably we'll use CBC. – Stanimir Stoyanov Dec 07 '16 at 09:53
  • @StanimirStoyanov Happy to help. Good on you for pressuring the close source developers into implementing more secure methods! – Luke Joshua Park Dec 07 '16 at 12:21
  • Actually the company which provides the devices is really open minded, so there was no need of pressure, but yes, it is important and definitely deal-braking thing. Thanks again. – Stanimir Stoyanov Dec 07 '16 at 14:00