2013-02-17 39 views
0

我有一個問題..當我解密從我的PHP頁面返回的數據, 如果字符串的長度小於16,字符\ 0被追加到字符串。 原始字符串是: 我解密加密字符串使用此功能:aes解密 0字符ios

#define FBENCRYPT_ALGORITHM  kCCAlgorithmAES128 
#define FBENCRYPT_BLOCK_SIZE kCCBlockSizeAES128 
#define FBENCRYPT_KEY_SIZE  kCCKeySizeAES256 

+ (NSData*)decryptData:(NSData*)data key:(NSData*)key iv:(NSData*)iv; 
{ 
    NSData* result = nil; 

    // setup key 
    unsigned char cKey[FBENCRYPT_KEY_SIZE]; 
    bzero(cKey, sizeof(cKey)); 
    [key getBytes:cKey length:FBENCRYPT_KEY_SIZE]; 

    // setup iv 
    char cIv[FBENCRYPT_BLOCK_SIZE]; 
    bzero(cIv, FBENCRYPT_BLOCK_SIZE); 
    if (iv) { 
     [iv getBytes:cIv length:FBENCRYPT_BLOCK_SIZE]; 
    } 

    // setup output buffer 
    size_t bufferSize = [data length] + FBENCRYPT_BLOCK_SIZE; 
    void *buffer = malloc(bufferSize); 

    int length = [data length]; 

    // do decrypt 
    size_t decryptedSize = 0; 
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, 
              FBENCRYPT_ALGORITHM, 
              0, 
              cKey, 
              FBENCRYPT_KEY_SIZE, 
              cIv, 
              [data bytes], 
              [data length], 
              buffer, 
              bufferSize, 
              &decryptedSize); 

    if (cryptStatus == kCCSuccess) { 
     result = [NSData dataWithBytesNoCopy:buffer length:decryptedSize]; 
    } else { 
     free(buffer); 
     NSLog(@"[ERROR] failed to decrypt| CCCryptoStatus: %d", cryptStatus); 
    } 

    return result; 
} 

我送一個零「IV」參數的功能後,我在函數中使用「文明」,它包含此: cIv description

結果正好,但字符串的長度是16而不是15(字符串:100000065912248)。實際上,最後一個字符是\ 0。

爲什麼?我怎麼解決?

編輯:

PHP加密函數:

function encrypt($plaintext) { 

    $key = 'a16byteslongkey!a16byteslongkey!'; 

    $base64encoded_ciphertext = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC)); 
    $base64encoded_ciphertext = trim($base64encoded_ciphertext); 

    return $base64encoded_ciphertext; 
} 
+2

一般去除填充'上ciphertext' trim'是不是一個好主意。 – zaph 2013-02-17 23:55:45

回答

2

AES是塊暗號和加密/解密長度的塊128位(16個字節)。因此,如果數據不是塊大小,則必須添加一些填充。 Apple最受歡迎和支持的是PKCS7。

與PHP接口必須考慮填充和可能的base64編碼。

解決方案是在兩側使用相同的填充,PHP和iOS。

AES總是在16個字節上運行,沒有選項 - 所以,如果你有15個字節,一個字節將不得不被添加,那就是填充。根據我的理解(對PHP加密不太瞭解)PHP並沒有真正實現PCKS7padding,最好是自己來填充。在Wikipedia中查找PKCS7。

+0

但我在php中的功能不使用填充(我已經編輯過php功能) – 2013-02-17 22:33:39

+0

AES在ECB/CBC模式*通常*使用填充。流模式不需要填充,ECB/CBC可能會部署密文竊取。作爲分組密碼的AES始終以16字節操作,但您仍然可以選擇不需要填充的模式。 – 2013-02-20 01:45:19

+0

@owlstead雖然流模式在某些情況下很好,並且看起來非常有吸引力,但它們很難正確使用:從不使用相同的隨機數等等。因此我個人不推薦他們。 – zaph 2013-02-20 02:40:12

0

如果您只對字符串進行操作,那麼您應該使用零填充(默認設置),但如果僅出於互操作性原因,我會推薦使用PKCS#7填充。

使用零填充明文填充值爲00的值字節,但僅在必要時填充。這與始終部署的PKCS#7填充不同。解密後,您可以在解密後使用上的trim函數產生明文。你應該得到原始的字符串。

這顯然不會在二進制數據上工作,因爲它可能以trim函數刪除的字符結尾。請注意,PHP中的trim似乎會剝離00字節。這不是一個給定的,正式的00不是空白,儘管它在很多運行時都是這樣處理的。

-1

你必須從解密的數據

function removePadding($decryptedText){ 
    $strPad = ord($decryptedText[strlen($decryptedText)-1]); 
    $decryptedText= substr($decryptedText, 0, -$strPad); 
    return $decryptedText; 
} 
+0

答案代碼將不適用於PHP mcrypt默認使用的null填充,而OP正在使用該填充。對於PKCS#7/PKCS#5填充,需要檢查填充是否有效。考慮使用錯誤的鍵,'$ strPad'很可能是錯誤的,可能是一個大於數據長度的值。但是不要返回一個*錯誤的填充錯誤*,這往往會創建一個填充oracle,而不會執行任何操作。大多數庫支持PKCS#7填充,並將自動添加填充加密和刪除解密填充 - 沒有更多的需要完成。 – zaph 2017-12-22 13:29:18