2013-10-05 36 views
1

我正在使用帶有密碼和初始化向量的AES加密對.Net和Java(Android上)進行加密(以及後來解密)字符串。我在各方面都獲得了相應的解密和單獨運行,但我仍然得到不同的結果,因此不允許對其中一個進行加密並在另一個系統上進行解密。我特別不明白爲什麼加密字節數組的前半部分是相同的,而後半部分是不同的(而所有其他字節數組完全相同)?針對Android/Java和.Net的AES加密只有部分相同

這裏是我得到從我用的是兩種加密代碼的字節數組:

的Java(爲便於比較,將其上已經負值加256):148 [202,147,168 ,9,104,213,176,174,157,124,160,54,33,151,246,,,70,63,184,118,228,50,242,224,231,37,34,16 ,123,9,143,81]

.net:[202,147,148,168,9,104,213,176,174,157,124,160,54,33,151,246, 109,127,84,129,168,106,21,159,131,67,75,209,166,2 21,190,243]

我發佈了下面用於加密的兩個代碼段。雖然我正在尋找暗示我現在做了幾個小時的錯誤,但我無法弄清楚我錯在哪裏。真是太好,如果有人可以點我什麼我不知道......

這裏是我所得到的,當我從兩個代碼版本打印出所有相關的值:

Android-Output: 
    Key (String):987654321 
    IV (String): 123456789
    Input (String): Encrypt_this_text 

    Key (Bytes): [54, 53, 52, 51, 50, 49, 48, 57, 56, 55, 54, 53, 52, 51, 50, 49] 
    IV (Bytes): [49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54] 
    Input (Bytes): [69, 110, 99, 114, 121, 112, 116, 95, 116, 104, 105, 115, 95, 116, 101, 120, 116] 

    Encrypted: [-54, -109, -108, -88, 9, 104, -43, -80, -82, -99, 124, -96, 54, 33, -105, -10, 70, 63, -72, 118, -28, 50, -14, -32, -25, 37, 34, 16, 123, 9, -113, 81] 
    Encrypted (+256 if <0): [202, 147, 148, 168, 9, 104, 213, 176, 174, 157, 124, 160, 54, 33, 151, 246, 70, 63, 184, 118, 228, 50, 242, 224, 231, 37, 34, 16, 123, 9, 143, 81] 

VBNet-Output: 
    Key (String)=987654321 
    IV (String)=123456789
    Input (String)=Encrypt_this_text 

    Key (Byte)=[54, 53, 52, 51, 50, 49, 48, 57, 56, 55, 54, 53, 52, 51, 50, 49] 
    IV (Byte)=[49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54] 
    Input (Byte)=[69, 110, 99, 114, 121, 112, 116, 95, 116, 104, 105, 115, 95, 116, 101, 120, 116] 

    Encrypted=[202, 147, 148, 168, 9, 104, 213, 176, 174, 157, 124, 160, 54, 33, 151, 246, 109, 127, 84, 129, 168, 106, 21, 159, 131, 67, 75, 209, 166, 221, 190, 243] 

這是用於生成加密的字節數組的java代碼:

String skey = "987654321"; 
String siv = "123456789"; 
String sinput = "Encrypt_this_text"; 

byte[] key = skey.getBytes("UTF8"); 
byte[] iv = siv.getBytes("UTF8"); 
byte[] input = sinput.getBytes("UTF8"); 

Cipher cipher = Cipher.getInstance("AES/CBC/ZeroBytePadding"); 
SecretKeySpec keyspec = new SecretKeySpec(key, "AES"); 
IvParameterSpec ivparams = new IvParameterSpec(iv); 
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivparams); 

byte[] encrypted = cipher.doFinal(input); 

...這是我的網絡(在這種情況下VB)Testcode:

Dim rm As New System.Security.Cryptography.AesManaged 

Dim skey As String = "987654321" 
Dim siv As String = "123456789" 
Dim sinput As String = "Encrypt_this_text" 

Dim key() As Byte = System.Text.Encoding.ASCII.GetBytes(skey) 
Dim IV() As Byte = System.Text.Encoding.ASCII.GetBytes(siv) 
Dim input() As Byte = System.Text.Encoding.ASCII.GetBytes(sinput) 

Dim ict As System.Security.Cryptography.ICryptoTransform = rm.CreateEncryptor(key, IV) 

Dim encrypted() As Byte = ict.TransformFinalBlock(input, 0, input.Length) 
+0

注意:1)使用ASCII編碼的明文會無聲地破壞外來字符。改用UTF-8。 2)IV和密鑰不應該使用ASCII(或UTF-8)。它們是隨機的二進制值,因此如果必須將它們轉換爲文本,請使用十六進制或Base64。 3)您必須爲每條消息生成一個新的隨機IV 4)爲了抵制主動攻擊,您需要應用MAC。使用加密然後MAC方案。確保包含整個密文,包括MAC在內的IV。並使用恆定時間比較進行MAC驗證。或者,你可以去像GCM的身份驗證模式,而不是自己寫它 – CodesInChaos

回答

2

這是由於.NET的AesManaged.CreateEncryptor中的默認填充爲PKCS7。

在Java中,您使用零填充進行初始化。

您可以通過將rm中的Padding屬性更改爲PaddingMode.Zeros來覆蓋填充。

相關的MSDN文章:MSDN

+1

我會這樣做,改變爲PKCS7。除非知道消息不以零字節結束,否則不能刪除「零」填充。 – CodesInChaos

+0

謝謝,永遠不會有我自己的:我認爲我已經在某個地方讀過Net標準默認爲零填充,這就是爲什麼我在目的中使用了零填充的原因......所以,當然,它的工作原理與你的提示(在VBNet中添加rm.Padding = Security.Cryptography.PaddingMode.Zeros),另一種方式是使用Cipher密碼= Cipher。的getInstance( 「AES/CBC/PKCS7PADDING」);在Java中。 – kiteflight

+0

I second CodesInChaos的評論 - PKCS7更適合大多數用途。 – kobigurk

相關問題