PHP 服务器和 iOS 上的 AES Rijndael 有时会生成不同的密码
我正在使用 Jim Dovey 的 NSData+AESCrypt 类别和 Michael Sedlaczek 的 NSString+AESCrypt (2011-02-22)。
在 PHP 上,我有一个简单的脚本:
<?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/>";
?>
在 ObjC 中:
NSString *key = @"01234567890123456789012345678901";
NSString *plaintext = [@"+l56Ia4yyK19D2x2+oCXuw==" AES256DecryptWithKey: key];
NSLog(@"plaintext: %@", plaintext);
我更改 PHP 中的变量 $plaintext,运行脚本并将输出密码复制并粘贴到 Objective-c 中以解密它。
并且:
“myword”给我“+l56Ia4yyK19D2x2+oCXuw==”,我在iOS上解密并得到“myword”[OK]
“早上好”给了我“5UdImsV1pQs60ovXmH74HQ==”,我解密并在 iOS 上得到“早上好”[OK]
- “Schröder”给了我“KqNSCE8nGsYUYVdGZ2tnMw==”,我解密并在 iOS 上得到“Schröder”[OK]
- “Schröder”给我“KqNSCE8nGsYUYVdGZ2tnMw==”,我解密并在 iOS 上得到“Schröder”[OK]
- “非常长的文本”给我“lsa+QF3IHQnAFiOjl2Heyg==”我解密并在 iOS 上得到“非常长的文本”[好的]
- “非常非常非常长的文本”给了我“kl/ThEyuyUMmKSqU4/fJSzzJOyvsXrGRt5/zsnqjQww=”并且我无法在 iOS 上解密它 [失败]
为什么 #5 失败?如果我尝试使用 Xcode 加密“非常非常非常长的文本”,我会得到“kl/ThEyuyUMmKSqU4/fJS90UZoJ73S4gox2uCoWoIL8=”注意: 吉隆坡/ThEyuyUMmKSqU4/fJS == 吉隆坡/ThEyuyUMmKSqU4/fJS zzJOyvsXrGRt5/zsnqjQww != 90UZoJ73S4gox2uCoWoIL8=
但更进一步,在 Xcode 上加密“早上好”会得到“hVq1AuR8PAXSOztK26pmMw==”,而 PHP 会给出“5UdImsV1pQs60ovXmH74HQ==”,但 Xcode 会将两者解密为使用相同的键“早上好”。
请帮忙。
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:
"myword" gives me "+l56Ia4yyK19D2x2+oCXuw==" and I decrypt in and get "myword" on iOS [OK]
"good morning" gives me "5UdImsV1pQs60ovXmH74HQ==" and I decrypt in and get "good morning" on iOS [OK]
- "Schröder" gives me "KqNSCE8nGsYUYVdGZ2tnMw==" and I decrypt in and get "Schröder" on iOS [OK]
- "Schröder" gives me "KqNSCE8nGsYUYVdGZ2tnMw==" and I decrypt in and get "Schröder" on iOS [OK]
- "very long text" gives me "lsa+QF3IHQnAFiOjl2Heyg==" and I decrypt in and get "very long text" on iOS [OK]
- "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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的 PHP 代码正在使用 ECB 模式。我看不到你在 ObjC 中设置模式的位置。想必您正在使用其默认模式。 ObjC 默认模式可能不是 ECB,更有可能是 CBC。另请注意,只要您的明文等于或小于 16 个字节(即一个块或更少),解密就会起作用。当它大于 16 字节(即它扩展到第二个块)时,它会失败。
我怀疑 ObjC 默认是 CBC 模式,IV 为零。这就像仅适用于第一个区块的 ECB,而对于第二个及后续区块则有所不同。
ECB 模式不安全并且会泄露信息。请改用具有指定 IV 的 CBC 模式。至少更改您的 PHP 代码以使用 CBC 模式而不是 ECB 模式。
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.
您可以使用
MCRYPT_RIJNDAEL_128
加密消息,这将为您提供 128 位(即 16 字节)的块大小。您会注意到
非常非常非常长的文本
大于 16 个字节。所以我猜你在 ios 上解密使用了不同的块大小。我对ios不熟悉,但是
AES256DecryptWithKey
似乎表明它使用256位的块大小。尝试在 PHP 代码中使用
MCRYPT_RIJNDAEL_256
,或更改 ios 代码以使用AES128DecryptWithKey
(我不知道是否存在,同样,我不知道 ios)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 useAES128DecryptWithKey
(I don't know if that exist, again, I don't know ios)