在objective-CIOS中,AES128加密-base64编码-post to PHP-PHP解码有时会失败

在objective-CIOS中,AES128加密-base64编码-post to PHP-PHP解码有时会失败,php,ios,objective-c,encryption,aes,Php,Ios,Objective C,Encryption,Aes,以下是我试图做的: 1) 从用户处获取纯NSString 2) 使用AES128加密,密钥长度为16字节(例如:0123456789abcdef) 3) 将其发送到PHP服务器 4) 将其解密为纯文本 但是如果输入的纯文本太长或太短,解密就会失败 以下是我所做的: 链接 提供 NSData+AEScrypt.h NSData+AEScrypt.m NSString+AEScrypt.h NSString+AEScrypt.m 内置ViewController.m #import "ViewCon

以下是我试图做的:

1) 从用户处获取纯NSString

2) 使用AES128加密,密钥长度为16字节(例如:0123456789abcdef)

3) 将其发送到PHP服务器

4) 将其解密为纯文本

但是如果输入的纯文本太长或太短,解密就会失败

以下是我所做的:

链接 提供

NSData+AEScrypt.h

NSData+AEScrypt.m

NSString+AEScrypt.h

NSString+AEScrypt.m

内置ViewController.m

#import "ViewController.h"
#import "NSString+AESCrypt.h"

...

-(void) sendPost {
//1. prepare 16-bytes long key
NSString *theKey = @"0123456789abcdef";

//2. prepare any plain NSString
NSString *plainString = @"abcdef";

//3. turn NSString into UTF-8 NSData
NSData *plainStringData = [plainString dataUsingEncoding:NSUTF8StringEncoding];

//4. turn UTF-8 NSData into AES128 Encrypted NSData with key
NSData *aesData = [plainStringData AES128EncryptWithKey: theKey];

//5. encode AES data into Base64-encoded NSString
NSString *base64String = [aesData base64EncodedStringWithOptions:0];

//check what the client is sending to the server
NSLog("Client plain text:%@ encrypted text:%@", plainString, base64String);
//Logs:
//Client plain text: abcdef encrypted text: iD+22cYZOlopuScGn42rAg==


/** do normal POST request to server ************/
//6. send 'base64String' to server
//set up parameter
NSString *parameter = [NSString stringWithFormat:@"data=%@", base64String];
NSData *parameterData = [parameter dataUsingEncoding:NSUTF8StringEncoding];

//set up URL
NSURL *url = [NSURL URLWithString: @"http://mywebsite.com/myserver.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPBody:parameterData];

//set up as POST method
[request setHTTPMethod:@"POST"];
[request addValue: @"application/x-www-form-urlencoded; charset=utf-8"  forHTTPHeaderField:@"Content-Type"];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
}
在myserver.php内部

<?php
//1. receive data from client
$data = $_POST['data'];

//2. check what the server received
echo "Before decrypt:".$data
//this echoes:
//Before decrypt:iD 22cYZOlopuScGn42rAg== 

//3. set up the same key as client's key
$key = "0123456789abcdef";

//4. decrypt AES
$decoded_data = decrypt_password($data, "0123456789abcdef");

//5. see the result
echo "After decrypt:".$decoded_data;
//this echoes:
//After decrypt: abcdef




function decrypt_password($pass,$key)
{
$base64encoded_ciphertext = $pass;

$res_non = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($base64encoded_ciphertext), MCRYPT_MODE_ECB);

$decrypted = $res_non;
$dec_s2 = strlen($decrypted);

$padding = ord($decrypted[$dec_s2-1]);
$decrypted = substr($decrypted, 0, -$padding);

return  $decrypted;
}

?>
从PHP下载,如下所示:

Before decrypt:iD 22cYZOlopuScGn42rAg==
After decrypt:abcdef
但是如果NSString*纯字符串太长或太短, 我从PHP得到:

Before decrypt:pQGKv22BszWe5WN b9oOtQ==
After decrypt:
也就是说,PHP无法解密它。 此外,我还意识到“+”符号出现在“解密前:”echo中。但这似乎不是问题,因为有时解密是有效的

我的问题是 为什么对于太长或太短的普通NSString解密失败?? 我怎样才能解决这个问题??我似乎找不到任何解决办法。请帮助..

找到答案

当加密字符串包含“+”符号时,PHP会将其转换为空白,因为“+”符号是保留的

因此,对其使用urlencode()和urldecode(),如下所示:

<?php
$key = 'secretkey';
$string = $_GET['data'];

$string = urlencode($string);
$string = str_replace("+", "%2B",$string);
$string = urldecode($string);
$output = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($string), MCRYPT_MODE_CBC, md5(md5($key))), "\0");

?>


这只是一种可能性,但PHP和Objective C可能会以不同的方式应用填充。好luckCan你能给我一个解决方案吗?因为你的PHP代码对我来说很好,我能给你的建议是:去测试那些不起作用的案例,找出起作用的和不起作用的案例之间的区别,此差异导致错误的原因,然后执行前缀/后缀处理以更正此差异,同时不损坏加密链。Good luckmcrypt使用非标准的空填充,甚至声明如果数据的最后一个字节在0x00上,填充将失败。普通加密和非bozo世界使用PKCS#7填充。PKCS#7 padding是PKCS#5的超集。MCRYPT#u RIJNDAEL#u 256不是AES,并且不指定256位密钥。它指定AES不支持的256位块大小。
<?php
$key = 'secretkey';
$string = $_GET['data'];

$string = urlencode($string);
$string = str_replace("+", "%2B",$string);
$string = urldecode($string);
$output = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($string), MCRYPT_MODE_CBC, md5(md5($key))), "\0");

?>