AES Rijndael on PHP server and iOS generates somet

2020-06-25 09:43发布

问题:

I'm using NSData+AESCrypt category by Jim Dovey and NSString+AESCrypt by Michael Sedlaczek (2011-02-22).

And on PHP I have a simple script:

<?php
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = '01234567890123456789012345678901';
$plaintext = "myworda";

$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_ECB);
$base64encoded_ciphertext = base64_encode($ciphertext);
echo "ciphertext: ".$base64encoded_ciphertext."<br/>";
?>

In ObjC:

NSString *key = @"01234567890123456789012345678901";
NSString *plaintext = [@"+l56Ia4yyK19D2x2+oCXuw==" AES256DecryptWithKey: key];
NSLog(@"plaintext: %@", plaintext);

I change the variable $plaintext in PHP, run script and copy and paste the output-cipher to the Objective-c to decrypt it.

And:

  1. "myword" gives me "+l56Ia4yyK19D2x2+oCXuw==" and I decrypt in and get "myword" on iOS [OK]

  2. "good morning" gives me "5UdImsV1pQs60ovXmH74HQ==" and I decrypt in and get "good morning" on iOS [OK]

  3. "Schröder" gives me "KqNSCE8nGsYUYVdGZ2tnMw==" and I decrypt in and get "Schröder" on iOS [OK]
  4. "Schröder" gives me "KqNSCE8nGsYUYVdGZ2tnMw==" and I decrypt in and get "Schröder" on iOS [OK]
  5. "very long text" gives me "lsa+QF3IHQnAFiOjl2Heyg==" and I decrypt in and get "very long text" on iOS [OK]
  6. "very very very very long text" gives me "kl/ThEyuyUMmKSqU4/fJSzzJOyvsXrGRt5/zsnqjQww=" and I cannot decrypt it on iOS [FAIL]

Why #5 fails? If I try to encrypt "very very very very long text" using Xcode, I get "kl/ThEyuyUMmKSqU4/fJS90UZoJ73S4gox2uCoWoIL8=" notice that: kl/ThEyuyUMmKSqU4/fJS == kl/ThEyuyUMmKSqU4/fJS zzJOyvsXrGRt5/zsnqjQww != 90UZoJ73S4gox2uCoWoIL8=

But going further, encrypting "good morning" on Xcode gives me "hVq1AuR8PAXSOztK26pmMw==", while PHP gave "5UdImsV1pQs60ovXmH74HQ==", but Xcode decrypts both to "good morning" using the same key.

Please help.

回答1:

Your PHP code is using ECB mode. I cannot see where you are setting the mode in ObjC. Presumably you are using its default mode. It is possible that the ObjC default mode is not ECB, more likely CBC. Also notice that whenever your plaintext is 16 bytes or less (that is one block or less) the decryption works. When it is greater than 16 bytes (that is it extends into a second block) it fails.

I suspect that the ObjC default is CBC mode with a zero IV. That will act as if it is ECB for the first block only, and differ for the second and subsequent blocks.

ECB mode is unsafe and leaks information. Use CBC mode with a specified IV instead. At the very least change your PHP code to use CBC mode instead of ECB mode.



回答2:

You encrypt the message using MCRYPT_RIJNDAEL_128 which gives you a block size of 128 bits, or 16 bytes. You'll notice that very very very very long text is larger than 16 bytes.

So I'm guessing you're decryption on ios uses a different block size. I'm not familiar with ios, but AES256DecryptWithKey seems to indicate it uses a block size of 256 bits.

Try using MCRYPT_RIJNDAEL_256 in your PHP code, or change the ios code to use AES128DecryptWithKey (I don't know if that exist, again, I don't know ios)