2012-10-15 80 views
2

我想在C#和Java中加密相同的數據。如果數據超過7個字節,則Java和C#加密值不相同。C#和Java DES加密值不相同

  • 輸入1:一個
    java的輸出:FrOzOp/2Io8 =
    C#輸出:FrOzOp/2Io8 =

  • 輸入2:ABC
    Y: H9A/ahl8K7I =
    c#:H9A/ahl8K7I =

  • 輸入3:AAAAAAAA問題
    Y:Gxl7e0aWPd7j6l7uIEuMxA ==
    C#:Gxl7e0aWPd7sf1xR6hK4VQ ==

這裏是實現C#和Java方法。
C#代碼:

public String saltTxt = "12345678"; 
public String Encrypt(String txt) 
{ 
     byte[] data = Encrypt(Encoding.UTF8.GetBytes(txt)); 

     DESCryptoServiceProvider alg = new DESCryptoServiceProvider(); 

     alg.Key = Encoding.UTF8.GetBytes(saltTxt.ToCharArray(), 0, cprovider.KeySize/8); 
     alg.IV = new byte[8]; 

     MemoryStream ms = new MemoryStream(); 
     CryptoStream stem = new CryptoStream(ms, cprovider.CreateEncryptor(),CryptoStreamMode.Write); 

     stem.Write(txt, 0, txt.Length); 
     stem.FlushFinalBlock(); 

     data = ms.ToArray(); 

     return Convert.ToBase64String(data); 
} 

Java代碼:

public String saltTxt = "12345678"; 
public String Encrypt(String str) { 
    try { 
     KeySpec myKey = new DESKeySpec(saltTxt.getBytes("UTF8")); 
     SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(myKey); 
     Cipher ecipher = Cipher.getInstance("DES"); 
     ecipher.init(Cipher.ENCRYPT_MODE, key); 

     byte[] data = str.getBytes("UTF8"); 

     byte[] crypt = ecipher.doFinal(data); 

     return new BASE64Encoder().encode(crypt); 
    } catch (Exception ex) { 
    } 

    return null; 
} 

任何想法,爲什麼它如預期不工作?

+1

聽起來像填充問題。請參閱http://msdn.microsoft.com/en-us/library/system.security.cryptography.symmetricalgorithm.padding.aspx –

+0

重要的是兩者之間的往返應該起作用。可以? – spender

+0

@JonSkeet是的,它是填充問題。 java的默認填充機制是什麼? 如果我在java部分中指定'DES/CBC/PKCS5Padding',那麼兩個值都變得相同。 –

回答

8

問題出在mode的加密。

SunJCE提供使用ECB爲默認模式,並且PKCS5Padding作爲DES,DES-EDE和河豚密碼默認填充方案。 (JCA Doc

.Net,對稱算法的默認操作模式是CipherMode.CBC和默認填充是PaddingMode.PKCS7。 (msdn..SymmetricAlgorithm

以下更改解決了問題。

// in C# 
DESCryptoServiceProvider alg = new DESCryptoServiceProvider(); 
alg.Mode = CipherMode.ECB; // specified 

// in java 
chiper = Cipher.getInstance("DES/CBC/PKCS5Padding"); 

不要在兩側改變。

1

您可能會看到ISO 10126填充,它將隨機字節附加到明文以填充多個塊大小。
此行爲是設計使然。

+0

但默認填充是'PKCS7'。我錯了嗎 ? –

+0

@NiksonKantiPaul:不在Java中。 – SLaks

0

該代碼(Java/Android)波紋管爲我工作。 我在C#上使用了相同的方法。

public static String Cripto(String Password) 
{ 
    String PasswordCripto = ""; 
    try 
    { 
     String encryptionKey = "anyEncryptionString"; 
     MessageDigest messageDigest = MessageDigest.getInstance("MD5"); 
     messageDigest.update(encryptionKey.getBytes("UTF-8"), 0, encryptionKey.length()); 
     byte[] encryptionKeyBytes = messageDigest.digest(); 

     SecretKeySpec Key = new SecretKeySpec(encryptionKeyBytes,"DESede"); 
     Cipher cipher = Cipher.getInstance("DESEDE/ECB/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, Key); 
     byte[] encryptedBytes = cipher.doFinal(Password.getBytes("UTF-8")); 

     PasswordCripto = new String(Base64.encode(encryptedBytes, Base64.DEFAULT), "UTF-8"); 
    } catch(Exception e) { } 
    return PasswordCripto ; 
}