2012-10-15 45 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 ; 
}