Xcode 中的 AES128 加密和 PHP 中的解密成功与否取决于密钥值
AES128 encryption in Xcode and decrypt in PHP succeeds and fails depending on key value
我按照 https://tharindufit.wordpress.com/2011/12/15/aes128-encryption-in-ios-and-decryption-in-php/ 中的步骤在 Xcode 中开发了客户端加密,在 PHP 中开发了服务器解密。
我在 https://asecuritysite.com/encryption/keygen 生成了一个 aes-128-ecb 密钥。
我的问题是:
如果我将密钥设为 "key" 之类的短字符串,则 PHP 解密有效;但如果我使用上述网站生成的密钥,例如 "D3C3794A79ADBDFD256645D59F01E2BD",PHP 解密将不起作用。
这是为什么?
我的确切代码如下。
Xcode 中的客户端:
#import "ViewController.h"
#import "NSString+AESCrypt.h"
static NSString *const KEY = @"D3C3794A79ADBDFD256645D59F01E2BD";
@interface ViewController (){
NSString *rawPassword;
NSMutableData *receivedData;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)send:(UIButton *)sender {
rawPassword = @"passwordHere";
[self sendRequest];
}
- (void) sendRequest {
NSString *rawUserid = @"useridHere";
// Encrypt with key
NSString *encoded_usr = [rawUserid AES128EncryptWithKey: KEY];
NSString *encoded_pwd = [rawPassword AES128EncryptWithKey: KEY];
NSString *parameter = [NSString stringWithFormat:
@"userid=%@&password=%@",encoded_usr, encoded_pwd];
NSLog(@"sending:%@", parameter);
NSData *parameterData = [parameter dataUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString: @"http://mywebsite.com/server.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPBody:parameterData];
[request setHTTPMethod:@"POST"];
[request addValue: @"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
if(connection){
receivedData = [[NSMutableData alloc]init];
NSLog(@"CONNECTING");
} else {
NSLog(@"NO CONNECTING");
}
}
#pragma mark NSURLConnection delegates
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receivedData setLength:0];
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[receivedData appendData:data];
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"CONNECTION FAILED");
return;
}
-(void) connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString* newStr = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
NSLog(@"connectionDidFinishLoading:%@", newStr);
}
@end
服务器端PHP:
<?php
$encoded_pwd = $_POST['password'];
$encoded_usr = $_POST['userid'];
$device = $_POST['device'];
$decoded_pwd = decrypt_password( $encoded_pwd , "D3C3794A79ADBDFD256645D59F01E2BD");
$decoded_usr = decrypt_password( $encoded_usr , "D3C3794A79ADBDFD256645D59F01E2BD");
echo "decoded userid:".$decoded_usr." decoded password:".$decoded_pwd;
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;
}
?>
由于您使用的是 AES-128,因此您的密钥应为 128 位(即 16 bytes/characters)。您链接到的 Objective-C 代码同样如此 (// ‘key’ should be 16 bytes for AES128
),它还会填充一个较短的键以使其长度合适 (// fill with zeroes (for padding)
)。
因此,大于 128 位的密钥会导致问题是可以预料的;并且小于 128 位的密钥也可以工作(因为它通过用零填充来增加到 128 位)。
您正在使用的密钥生成站点为 AES-128 ECB 生成 16 个字符的密钥...但以 十六进制 显示它们(即每个密钥字符 2 个十六进制数字 = > 32 个十六进制数字),这就是它们显示为 32-"character" 键的原因。
我按照 https://tharindufit.wordpress.com/2011/12/15/aes128-encryption-in-ios-and-decryption-in-php/ 中的步骤在 Xcode 中开发了客户端加密,在 PHP 中开发了服务器解密。
我在 https://asecuritysite.com/encryption/keygen 生成了一个 aes-128-ecb 密钥。
我的问题是:
如果我将密钥设为 "key" 之类的短字符串,则 PHP 解密有效;但如果我使用上述网站生成的密钥,例如 "D3C3794A79ADBDFD256645D59F01E2BD",PHP 解密将不起作用。
这是为什么?
我的确切代码如下。
Xcode 中的客户端:
#import "ViewController.h"
#import "NSString+AESCrypt.h"
static NSString *const KEY = @"D3C3794A79ADBDFD256645D59F01E2BD";
@interface ViewController (){
NSString *rawPassword;
NSMutableData *receivedData;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)send:(UIButton *)sender {
rawPassword = @"passwordHere";
[self sendRequest];
}
- (void) sendRequest {
NSString *rawUserid = @"useridHere";
// Encrypt with key
NSString *encoded_usr = [rawUserid AES128EncryptWithKey: KEY];
NSString *encoded_pwd = [rawPassword AES128EncryptWithKey: KEY];
NSString *parameter = [NSString stringWithFormat:
@"userid=%@&password=%@",encoded_usr, encoded_pwd];
NSLog(@"sending:%@", parameter);
NSData *parameterData = [parameter dataUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString: @"http://mywebsite.com/server.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPBody:parameterData];
[request setHTTPMethod:@"POST"];
[request addValue: @"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
if(connection){
receivedData = [[NSMutableData alloc]init];
NSLog(@"CONNECTING");
} else {
NSLog(@"NO CONNECTING");
}
}
#pragma mark NSURLConnection delegates
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receivedData setLength:0];
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[receivedData appendData:data];
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"CONNECTION FAILED");
return;
}
-(void) connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString* newStr = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
NSLog(@"connectionDidFinishLoading:%@", newStr);
}
@end
服务器端PHP:
<?php
$encoded_pwd = $_POST['password'];
$encoded_usr = $_POST['userid'];
$device = $_POST['device'];
$decoded_pwd = decrypt_password( $encoded_pwd , "D3C3794A79ADBDFD256645D59F01E2BD");
$decoded_usr = decrypt_password( $encoded_usr , "D3C3794A79ADBDFD256645D59F01E2BD");
echo "decoded userid:".$decoded_usr." decoded password:".$decoded_pwd;
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;
}
?>
由于您使用的是 AES-128,因此您的密钥应为 128 位(即 16 bytes/characters)。您链接到的 Objective-C 代码同样如此 (// ‘key’ should be 16 bytes for AES128
),它还会填充一个较短的键以使其长度合适 (// fill with zeroes (for padding)
)。
因此,大于 128 位的密钥会导致问题是可以预料的;并且小于 128 位的密钥也可以工作(因为它通过用零填充来增加到 128 位)。
您正在使用的密钥生成站点为 AES-128 ECB 生成 16 个字符的密钥...但以 十六进制 显示它们(即每个密钥字符 2 个十六进制数字 = > 32 个十六进制数字),这就是它们显示为 32-"character" 键的原因。