2013-04-01 38 views
1

我想加密Xcode中的字符串並用PHP解密或用PHP加密並用Xcode解密。Xcode AES加密/解密 - php兼容性問題

所以首先我試圖得到相同的AES encryption結果。

這裏是我的Xcode的文件(我已經把一切爲了簡單起見,單個文件):

#import "t.h" 
#import <CommonCrypto/CommonCryptor.h> 

@interface NSData(AES) 
- (NSData*)AES256EncryptWithKey:(NSString*)key; 
- (NSData*)AES256DecryptWithKey:(NSString*)key; 
@end 

@implementation NSData (AES) 

- (NSData*)AES256EncryptWithKey:(NSString*)key { 
char keyPtr[kCCKeySizeAES256]; 

[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSASCIIStringEncoding]; 

NSString *iv = @"1234567812345678"; 
char ivPtr[kCCKeySizeAES128]; 

[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSASCIIStringEncoding];  

NSUInteger dataLength = [self length]; 

size_t bufferSize   = dataLength + kCCBlockSizeAES128; 
void* buffer    = malloc(bufferSize); 

size_t numBytesEncrypted = 0; 
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, NULL, 
             keyPtr, kCCKeySizeAES256, 
             ivPtr /* initialization vector (optional) */, 
             [self bytes], dataLength, /* input */ 
             buffer, bufferSize, /* output */ 
             &numBytesEncrypted); 

if (cryptStatus == kCCSuccess) 
{ 
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; 
} 

free(buffer); //free the buffer; 
return nil; 
} 

- (NSData*)AES256DecryptWithKey:(NSString*)key { 
char keyPtr[kCCKeySizeAES256]; 

NSString *iv = @"1234567812345678"; 
char ivPtr[kCCKeySizeAES128]; 

[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSASCIIStringEncoding]; 


// fetch key data 
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSASCIIStringEncoding]; 

NSUInteger dataLength = [self length]; 

size_t bufferSize   = dataLength + kCCBlockSizeAES128; 
void* buffer    = malloc(bufferSize); 

size_t numBytesDecrypted = 0; 
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, NULL, 
             keyPtr, kCCKeySizeAES256, 
             ivPtr /* initialization vector (optional) */, 
             [self bytes], dataLength, /* input */ 
             buffer, bufferSize, /* output */ 
             &numBytesDecrypted); 

if (cryptStatus == kCCSuccess) 
{ 
    return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; 
} 

free(buffer); //free the buffer; 
return nil; 
} 

@end 



@interface t() 
@end 

@implementation t 

- (void)viewDidLoad 
{ 
[super viewDidLoad]; 


NSString *key = @"12345678123456781234567812345678"; 

NSData *plaintext = [[@"aaa0000000000000" dataUsingEncoding:NSASCIIStringEncoding] AES256EncryptWithKey: key]; 

label1.text = [[NSString alloc] initWithData:plaintext encoding:NSASCIIStringEncoding]; 


} 

@end 

而現在的PHP代碼:

<?php 

$key256 = "12345678123456781234567812345678"; 
$iv128 = "1234567812345678"; 
$text = "aaa"; 

$blocksize = 16; 
$len = strlen($text); 
$pad = $blocksize - ($len % $blocksize); 

$text .= str_repeat("0", $pad); 

$cipher = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key256, $text, MCRYPT_MODE_CBC, $iv128); 

echo $cipher; 

?> 

Xcode的加密字符串和PHP加密的字符串不同。

PHP:â5¢Ð[Iüf#hÂ(Æ

的Xcode:¡#yZPbEs¿D6ñ

我能做些什麼,使工作?難道我做錯了什麼?

我將進一步解釋代碼做什麼,它是如何構成的,所以你可以更容易理解的問題(糾正我,如果我錯了):

  1. PHP和Xcode中使用CBC AES加密等等我想那裏沒有問題。你可以看到我只是試圖得到相同的結果 - 安全無關緊要 - 所以我沒有填充 - 文本長度正好是128位(16個字符)。

  2. 密鑰是256位(32個字符)。

  3. 初始化向量是128位(16個字符)。

非常感謝。

任何幫助表示讚賞!

+0

行' - (NSData *)AES256EncryptWithKey:(NSString *)key {'確實正確地定義了與PHP相同的密鑰,是嗎? – LSerni

+0

是的。你可以在我的代碼中看到兩個鍵。 – BechD

回答

2

終於拿到了! (在詢問蘋果之後)

顯然,從NSString獲取getCString是錯誤的,因爲例程試圖以null終止字符串,並且32字節的緩衝區不夠大而無法終止32個字符的字符串。

正確的方式來獲得密鑰或IV將是:

[key cStringUsingEncoding:NSASCIIStringEncoding]; 
+0

我沒有得到任何正確的值,與PHP :( –

0

變化:

[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSASCIIStringEncoding]; 

[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

我相信這是一個編碼問題

+0

不...這也是我的初始代碼...如果它是UTF8或ASCII - 加密完全一樣:#yZPbEs¿D6ñ – BechD

0

使用時從頁面的最開始這個代碼,我可以只加密16個文本字符。其實我可以加密任何大小的文本,但是當我解密加密的NSData時,我只能得到16個字符或128位。

這是否與IV有關?這段代碼是否僅對128位進行加密,如果我有更大的文本大小,我需要提供(爲了更好的安全性)新的IV並加密第二塊?

+0

是的,上面的代碼被用來作爲iOS和php之間的兼容性測試來加密16個字節,嘗試用kCCOptionPKCS7Padding替換「CCCrypt(kCCDecrypt,kCCAlgorithmAES128,NULL,...」)中的NULL。再次 - 現在您不會有在php中使用不同的填充函數也是一樣的結果 – BechD

+0

好吧,太棒了,我只是在檢查是否正常實現了這一點,但是等等,PKCS7填充與純文本輸入有什麼關係? - 如果鍵是短的,然後用非零填充它? – jovanjovanovic

+0

不,填充用於文本。AES 128僅適用於128位的文本塊...因此,您的文本必須填充,以便可以精確地分爲塊的128位。 – BechD