在iOS和PHP之间AESCrypt解密

我有一段时间搞清楚如何解密用NSData + AESCrypt.mencryption的string( 这里解释 )

我一直在寻找其他一些线程,但是我只需要iDevice将一个string发送到一个PHP文件encryption,然后在PHP内部(它被存储到数据库中)解密。

此代码:

NSString *encryptedString = [@"Hello" AES256EncryptWithKey:@"a16byteslongkey!"]; NSLog(@"The strign encrypted : %@",encryptedString); 

返回encryption的string: 7opqbb7sEVNoXplyQv / X8g ==

这里是我的解密PHP代码:

 function decrypt_data($data, $key) { return mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key,$data,MCRYPT_MODE_ECB); } function unpadPKCS7($data, $blockSize) { $length = strlen ( $data ); if ($length > 0) { $first = substr ( $data, - 1 ); if (ord ( $first ) <= $blockSize) { for($i = $length - 2; $i > 0; $i --) if (ord ( $data [$i] != $first )) break; return substr ( $data, 0, $i ); } } return $data; } function decrypt_string($string) { $string = unpadPKCS7($string,128); $string = decrypt_data($string,"a16byteslongkey!"); return $string; } die('<br>Basic :'.decrypt_string('7opqbb7sEVNoXplyQv/X8g==')); 

更新:

一直在做一些MD5解密和实验,但还远远没有取得可用的结果。 这是我到目前为止:

 Original string : Hello AES256Encrypt result : 7opqbb7sEVNoXplyQv/X8 base64_decode Decrypted: îŠjm¾ìSh^™rBÿ× mcrypt_rijndael_128 : Õ¯Öå«Ž(ás2''u) mcrypt_rijndael_128 & hex2bin : UÃ)ı+úy´e 

可悲的是,不pipe我怎么弯曲和扭曲,我只是乱七八糟。 任何人都可以看到我做错了什么?

免责声明:我没有iPhone开发经验。

简短的答案 – 什么TC。 说过。 AES256EncryptWithKey有些可怕的错误:

作为AES256,你会期望它需要一个32字节的密钥,而不是一个16字节的密钥。 但是,好吧,说它填充空字节较短的键,使他们32字节。 这可能会解释为什么你的16字节密钥被填充16个空字符。

但是,当涉及到实际的encryption行为,它使用AES 128,但与32字节的关键。 说啊?

将tc。的Python转换为PHP:

 $base64encoded_ciphertext = '7opqbb7sEVNoXplyQv/X8g=='; $key = 'a16byteslongkey!'; $padded_key = $key . str_repeat(chr(0x00), 16); // Argh! $result = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $padded_key, base64_decode($base64encoded_ciphertext), 'ecb'); // Yetch - $result ends up being padded with 0x0b's (vertical tab). var_dump(rtrim($result, chr(0x0b))); 

结果:

string(5)“你好”

~~

编辑: 这个来自Henno的post有一些相关的细节。

~~

做了一些额外的研究。 您的密钥上的空填充可能是因为AES256需要一个32字节的密钥。 明文上的0x0B填充感谢PKCS7 。 PKCS7是一种填充scheme,其中用于填充的字节的值等于所添加的字节数。 在这个例子中,11个字节被添加到“Hello”的末尾,将5个字节的input转换为AES的16字节块。 11 = 0x0B。

因此,当明文不是长度= 5时,上面的代码将不起作用。请改为:

 $pad_char = ord(substr($result, -1)); $result_without_padding = substr($result, 0, strlen($result) - $pad_char); 

encryption的string看起来像是base64编码的。 在解密之前尝试解码它。

首先,您使用的Objective-C代码非常糟糕:

  • 密钥空间严重受限(大概UTF-8字节以空字节结尾,以空字节扩展到32字节)。 生成一个随机密钥最简单的方法是坚持ASCII,这使得默认的密钥大小为256位,将其限制在大约223.6位。
  • encryption在ECB模式下完成。
  • 数据似乎被不可逆地填充了0x0B。

不惜一切代价避免。 这是不安全的。

它可以在Python中用这样的东西“解密”:

 >>> import Crypto.Cipher.AES >>> import base64 >>> Crypto.Cipher.AES.new('a16byteslongkey!'+'\0'*16).decrypt(base64.b64decode('7opqbb7sEVNoXplyQv/X8g==')) 'Hello\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b' 

在这里看到我的post: PHP的iOS AESencryption


我刚刚通过这种types的项目。 我使用了你在“也被认为是…”中引用的库

这里是一些用php解密的例子代码:

 $iv2 = ''; for($i=0;$i<16;$i++){ $iv2 .= "\0"; } $plain_text_CBC = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted_text, MCRYPT_MODE_CBC, $iv2); var_dump($plain_text_CBC); 

确保您的密钥都是256位(32个字符,我还没有任何编码问题,但如果你这样做,记住你是encryption字节,而不是字符)。 请注意,MCRYPT_RIJNDAEL_128中的128是块大小,而不是密钥大小,而在AES256DecryptWithKey方法中,256是对密钥大小的引用,而块大小是128. AES256DecryptWithKey以CBC模式运行,但具有空初始化vectorⅳ)。

CBC意味着每个块依赖于最后一个块,所以它使用一个预先设定的,通常是随机的“块-1”,称为IV

ECB意味着每个块都以相同的方式encryption,因此它显示了同一个消息中的两个块是相同的。 提到的图书馆没有使用它,所以我只是为了对比而提到它。

使用零字节(以字节为单位0000000000000000)被认为是不安全的,但它确实为您提供了一些额外的安全性(但您仍然可以确定您的纯文本的第16个字符是否每次都是相同的)。 要解决这个问题,你必须为IV创build一个NSData * ivvariables,修改NSData + AESCrypt.m的CCcrypt参数,为iv参数添加[iv bytes](我还没有testing过这个代码)需要存储这个iv并把它和你的消息一起传递给php。 但首先我会testing,并使一切工作与零iv。