2013-08-28 19 views
1

我在使用C#加密的Java字節中解密時遇到問題。從Java解密返回的某些塊中的錯誤

Java的輸出在五個純文本塊的最後兩個塊中出錯。第四個塊是完全錯誤的,第五個塊有單個字符錯誤。

事情我已經仔細檢查/注意:

  • 鑰匙和工具變量是相同的,但我不得不在末尾,反覆進行16位的C#鍵的第一個字節來創建24位Java密鑰。
  • C#使用CBC和PKCS7。塊大小爲8.
  • Java正在使用CBC和PKCS5(爲此目的,它應該與7相同)。

這裏是C#

byKey = Encoding.UTF8.GetBytes(key); 
TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider(); 
byte[] inputByteArray = Encoding.UTF8.GetBytes(val); 
MemoryStream ms = new MemoryStream(); 
CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(byKey, IV), CryptoStreamMode.Write); 
cs.Write(inputByteArray, 0, inputByteArray.Length); 
cs.FlushFinalBlock(); 
return Convert.ToBase64String(ms.ToArray()); 

和解密加密側的Java

byte[] inputByteArray = Base64.decode(val); 
Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding"); 
c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(byKey, "DESede"), new IvParameterSpec(iv, 0, 8)); 

byte[] decryptedBytes; 
for (int i = 0, j = 0; i < inputByteArray.length; i++) { 
    if ((decryptedBytes = c.update(inputByteArray, i, 1)) == null) 
     continue; 
    else { 
     System.out.println(new String(decryptedBytes)); 
     j += decryptedBytes.length; 
    }   
} 

我期待看到有關sys出明文塊。 我知道.update()循環可以替換爲.doFinal(),但我想要逐塊查看它。

我對Java不是很熟悉,所以我特別感謝那裏的任何建議。

編輯 我不相信文本編碼是問題。這裏是表現出了同樣的問題,只是沒有表現出它的塊逐塊自然的原代碼:

byte[] decrypted = c.doFinal(inputByteArray); 
return new String(decrypted, "UTF-8"); 

回答

0

原來,這畢竟不是加密。

問題出在BASE64編碼和事實上,它通過一個cookie沿着將+變成空間的方式傳播(因此,請感謝rossum提供逐字節的建議)。

0

你不能拿的UTF-8字節任意塊,並將其轉換爲字符串(也,你沒有指定字符集)。您需要將所有字節放在一起並將它們轉換爲字符串,並指定"UTF-8"字符集。

+0

我明白,我的原始doFinal(),顯示相同的錯誤字符,指定了編碼。但在這種情況下,所有原始字符都是低128。所以我不認爲這是問題。 –

0

Java通常會有不同的C#默認值,所以您不應該依賴任何地方的默認值,特別是在字節和字符串之間轉換時。除了@ jtahlborn的約在任意點突破UTF-8字符串評論,你還需要在Java代碼中指定UTF-8,當你在你的C#代碼所做的:

System.out.println(new String(decryptedBytes, "UTF-8")); 

不是檢查字符相反,你可能想嘗試檢查實際字節。這應該讓你更好地處理任何可能發生不匹配的地方。

相關問題