2015-06-26 55 views
3

我試圖使用目標c和C#加密和解密字符串。這兩個在本地代碼工作正常,但當我嘗試解密C#中的字符串在iOS中加密。我得到一些錯誤。c#中解密字符串如何在iOS中使用Rijndael加密

這是我的目標用c

- (NSData *)AES256EncryptWithKey:(NSString *)key Data: (NSData *) data 
{ 
    char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused) 

    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) 

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

    NSUInteger dataLength = [data length]; 

    NSData *iv = [@"abcdefghijklmnopqrstuvwxyz123456" dataUsingEncoding:NSUTF8StringEncoding]; 

    size_t bufferSize = dataLength + kCCBlockSizeAES128; 

    void *buffer = malloc(bufferSize); 

    size_t numBytesEncrypted = 0; 

    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, 
              keyPtr, kCCKeySizeAES256, 
              [iv bytes] /* initialization vector (optional) */, 
              [data bytes], dataLength, /* input */ 
              buffer, bufferSize, /* output */ 
              &numBytesEncrypted); 

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

    free(buffer); //free the buffer; 

    return nil; 
} 

在想知道如何在C#解密代碼,我給的塊大小是256,ivsize爲32,使用「RijndaelManaged的()」。我不使用密碼&。 錯誤:類似「填充無效且無法刪除」。 我試圖設置填充太PKCS7,沒有,零,但沒有任何幫助解密。

任何一個可以幫助嗎?

編輯: 我的C#代碼在這裏

public string DecryptString(string encrypted) 
{ 
    string result = null; 
    _encoder = new UTF8Encoding(); 
    if (!string.IsNullOrWhiteSpace(encrypted) && (encrypted.Length >= 32)) 
    { 
     var messageBytes = Convert.FromBase64String(encrypted); 
     using (var rm = new RijndaelManaged()) 
     { 
      rm.BlockSize = _blockSize; 
      rm.Key = _encoder.GetBytes("mykey_here"); 
      rm.IV = _encoder.GetBytes("abcdefghijklmnopqrstuvwxyz123456"); ; 
      rm.Padding = PaddingMode.Zeros; 
      var decryptor = rm.CreateDecryptor(rm.Key, messageBytes.Take(_ivSize).ToArray()); 
      result = _encoder.GetString(Transform(messageBytes.Skip(_ivSize).ToArray(), decryptor)); 
     } 
    } 

    return result; 
} 

protected byte[] Transform(byte[] buffer, ICryptoTransform transform) 
{ 
    byte[] result; 
    using (var stream = new MemoryStream()) 
    using (var cs = new CryptoStream(stream, transform, CryptoStreamMode.Write)) 
    { 
     cs.Write(buffer, 0, buffer.Length); 
     cs.FlushFinalBlock(); 
     result = stream.ToArray(); 
    } 

    return result; 
} 
+0

你試過kCCOptionECBMode | kCCOptionPKCS7Padding作爲CCCrypt的第三個參數? – Doro

+0

是的,我試過但沒用。如果我試試這個kCCOptionECBMode我不能在ios本身加密 – Rajesh

+0

@Doro不使用iv和ECB模式。一般來說,ECB模式不應該被使用,因爲它比CBC模式更安全。 – zaph

回答

4

的iOS(公共密碼)明確規定了所有的密碼參數,C#代碼隱式確定很多參數。嘗試實現互操作性時,這些隱含參數在簡化使用情況時存在問題。

的C#類RijndaelManaged允許明確指定參數,更改代碼使用這些,尤其是BlockSize128),KeySize128ModeCipherMode.CBC)和PaddingPaddingMode.PKCS7)。 modePadding的默認值是OK。請參閱RijndaelManaged Documentation

AES和Rijndael不一樣,特別是AES只使用128位(16字節)的塊大小,而Rijndael允許多個塊大小。所以需要爲Rijndael指定128位的塊大小。因此,iv也是128位(16字節)。 兩者都支持128,192和256字節的加密密鑰。

你可能會比RijndaelManaged類使用AESManaged類更好。請參閱AesManaged Documentation

C#端希望數據爲Base64編碼,iOS端不顯示該編碼操作,請確保正在iOS端完成。

由於您使用的是iv,請確保您在兩側都使用CBC模式。在通用加密CBC模式是默認的,確保CBC模式正在C#端使用。

確保C#端使用PKCS#7或PKCS#5填充,它們是等效的。看起來PKCS#7是C#端的默認設置,所以這應該是可以的。

最好使用指定大小的密鑰,而不要依賴於默認填充。在Common Crypto中,密鑰大小是明確指定的,如果提供的密鑰太短,則填充空值。 C#看起來像是通過提供的密鑰來確定密鑰大小,在這種情況下密鑰是10個字節,所以解密密鑰可能默認爲128位,並且密鑰在內部用空值填充。在iOS上,您明確指定了256位的密鑰大小。這是一個需要修復的錯誤匹配。提供一個在iOS端指定的確切大小的密鑰。

最後是iv,C#代碼期望iv被加到數據的前面,但是iOS代碼沒有提供這個。解決方案是將iOS代碼更改爲將iv加到加密的代碼中。將iv更改爲16個字節,即AES塊大小。

如果您需要更多幫助,最後在加密調用之前和之後提供十六進制轉儲的測試數據,數據輸出,iv和密鑰。

+0

感謝您的幫助,爲我工作。 – Rajesh

+0

如何在ios中使用Rijndael加密算法? – Rajesh

+0

我有檢查你的另一個答案,你說, 對於一個256位的塊大小,你需要使用來自第三方實現的Rijndael。你可以請建議在iOS中的任何第三方代碼。 – Rajesh

相關問題