2016-01-09 226 views
1

我在C#和Java中有DESCrypto,如下所示。使用C#時我會得到正確的結果。使用Java時遇到問題。如何解決這個問題?Java相當於C#DESCrypto

//這是主要函數,它將調用安全類(C#)中的加密函數。

private void button1_Click(object sender, EventArgs e) 
{  
    string plainText = ""; 
    Debug.WriteLine("plainText:" + plainText); 
    // plainText:

    byte[] encrypted = Security.Encrypt(Encoding.ASCII.GetBytes(plainText)); 
    Debug.WriteLine("encrypted:" + Security.GetString(encrypted)); 
    // encrypted:4F792B474936462B6A4F62635A6142464D54782F4E413D3D 

    byte[] decrypted = Security.Decrypt(encrypted); 
    Debug.WriteLine("decrypted:" + Encoding.ASCII.GetString(decrypted)); //        
    // decrypted:
} 

//這是一個安全類(C#)

public class Security 
{ 
    private static byte[] IV_64 = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }; 
    private static byte[] KEY_64 = new byte[] { 7, 1, 7, 7, 5, 5, 4, 7 }; 

    public static byte[] GetBytes(string value) 
    { 
     SoapHexBinary shb = SoapHexBinary.Parse(value); 
     return shb.Value; 
    } 

    public static string GetString(byte[] value) 
    { 
     SoapHexBinary shb = new SoapHexBinary(value); 
     return shb.ToString(); 
    } 

    public static byte[] Decrypt(byte[] value) 
    { 
     MemoryStream mstream = new MemoryStream(Convert.FromBase64String(Encoding.ASCII.GetString(value))); 
     CryptoStream cstream = new CryptoStream(mstream, new DESCryptoServiceProvider().CreateDecryptor(KEY_64, IV_64), CryptoStreamMode.Read); 
     StreamReader reader = new StreamReader(cstream); 
     return Encoding.ASCII.GetBytes(reader.ReadToEnd()); 
    } 

    public static byte[] Encrypt(byte[] value) 
    { 
     MemoryStream mstream = new MemoryStream(); 
     CryptoStream cstream = new CryptoStream(mstream, new DESCryptoServiceProvider().CreateEncryptor(KEY_64, IV_64), CryptoStreamMode.Write); 
     StreamWriter writer = new StreamWriter(cstream); 
     writer.Write(Encoding.UTF8.GetString(value)); 
     writer.Flush(); 
     cstream.FlushFinalBlock(); 
     mstream.Flush(); 
     return Encoding ASCII.GetBytes(Convert.ToBase64String(mstream.GetBuffer(), 0, Convert.ToInt32(mstream.Length))); 
    } 
} 

//這是其主要功能將調用在安全類(JAVA)的加密功能。

String plainText = ""; 
Log.d("test", String.format("plainText:%s\n", plainText)); 
// plainText:

byte[] encrypted = Security.Encrypt(plainText.getBytes()); 
Log.d("test", String.format("encrypted:%s\n", Security.GetString(encrypted))); 
// encrypted:3B2F8623A17E8CE6DC65A045313C7F34 

byte[] decrypted = Security.Decrypt(encrypted); 
Log.d("test", String.format("decrypted: %s\n", String.valueOf(decrypted)));  
// decrypted:[[email protected] 

//這是一個安全的類(JAVA)

import java.security.InvalidAlgorithmParameterException; 
import java.security.InvalidKeyException; 
import java.security.NoSuchAlgorithmException; 
import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 

public class Security { 
    private static byte[] IV_64 = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }; 
    private static byte[] KEY_64 = new byte[] { 7, 1, 7, 7, 5, 5, 4, 7 }; 

    private static String KEY_TYPE = "DES"; 
    private static String ALGORITHM = "DES/CBC/PKCS5Padding"; 

    public static String GetString(byte[] value) { 
     StringBuilder builder = new StringBuilder(); 
     for (byte i : value) { 
      builder.append(String.format("%02X", i & 0xff)); 
     } 
     return builder.toString(); 
    } 

    public static byte[] GetByte(String value) { 
     StringBuilder builder = new StringBuilder(); 
     for (char i : value.toCharArray()) { 
      builder.append(String.format("%02X", i & 0xff)); 
     } 
     return String.valueOf(builder).getBytes(); 
    } 

    public static byte[] Encrypt(byte[] value) { 
     try { 
      Cipher cipher = Cipher.getInstance(ALGORITHM); 
      cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(KEY_64, KEY_TYPE), new IvParameterSpec(IV_64)); 
      return cipher.doFinal(value); 
     } catch (InvalidKeyException e) { 
      e.printStackTrace(); 
     } catch (InvalidAlgorithmParameterException e) { 
      e.printStackTrace(); 
     } catch (NoSuchAlgorithmException e) { 
      e.printStackTrace(); 
     } catch (NoSuchPaddingException e) { 
      e.printStackTrace(); 
     } catch (BadPaddingException e) { 
      e.printStackTrace(); 
     } catch (IllegalBlockSizeException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    public static byte[] Decrypt(byte[] value) { 
     try { 
      Cipher cipher = Cipher.getInstance(ALGORITHM); 
      cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(KEY_64, KEY_TYPE), new IvParameterSpec(IV_64)); 
      return cipher.doFinal(value); 
     } catch (InvalidKeyException e) { 
      e.printStackTrace(); 
     } catch (InvalidAlgorithmParameterException e) { 
      e.printStackTrace(); 
     } catch (NoSuchAlgorithmException e) { 
      e.printStackTrace(); 
     } catch (NoSuchPaddingException e) { 
      e.printStackTrace(); 
     } catch (BadPaddingException e) { 
      e.printStackTrace(); 
     } catch (IllegalBlockSizeException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 
} 

在java中,當plainText = "",從加密預期輸出是4F792B474936462B6A4F62635A6142464D54782F4E413D3D(如在C#),但我得到3B2F8623A17E8CE6DC65A045313C7F34。

+0

我添加了java代碼。將C#轉換爲Java時出現問題。請幫幫我。謝謝。 – ant

回答

2

在C#中,您使用Security類中的Base64對密文進行編碼,然後在外面用Hex重新編碼它。在Java中,你只是在執行十六進制編碼。你應該堅持一種編碼,而不是兩種。


其他注意事項:

  • DES其實它不應該採用時下。暴力相當容易。
  • 如果您使用CBC模式,那麼您需要每次使用新的不可預測的IV(隨機生成)。它不必是保密的,所以你可以在密文之前加上它,並在解密之前切斷它。
  • 你真的應該考慮給密文添加認證。否則,可能會在系統中運行填充oracle攻擊。可以使用GCM或EAX等認證模式,也可以使用帶有強大MAC的HMAC-SHA256的encrypt-then-MAC方案。
+0

謝謝指出,我的問題解決了。 – ant