簡體   English   中英

Java等效於C#DESCrypto

[英]Java equivalent of C# DESCrypto

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

//這在主函數中,它將在安全性類(C#)中調用crypto函數。

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

    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:0123456789
}

//這是一個安全類(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)中調用crypto函數。

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

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:[B@6801b34

//這是安全類(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 = "0123456789" ,加密的預期輸出為4F792B474936462B6A4F62635A6142464D54782F4E413D3D(類似於C#),但得到3B2F8623A17E8CE6DC65A045313C7F34。

在C#中,您使用Security類內部的Base64編碼密文,然后使用其外部的Hex再次對其進行編碼。 在Java中,您僅執行十六進制編碼。 您應該堅持一種編碼方式,而不要同時使用兩種編碼方式。


其他注意事項:

  • 如今,確實不應使用DES。 蠻力很容易。
  • 如果使用CBC模式,則每次都需要使用新的且不可預測的IV(隨機生成)。 它不一定是秘密的,因此您可以將其放在密文之前,並在解密之前將其切成薄片。
  • 您確實應該考慮將身份驗證添加到密文中。 否則,可能會在系統中運行padding oracle攻擊。 可以使用GCM或EAX等身份驗證模式,也可以使用具有HMAC-SHA256等強MAC的先加密后MAC方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM