2

I received an encrypted string from Java, and I can see the Java encrypted source code. I wrote the decryption code in C#. But always report an error at "FlushFinalBlock". Error message: "System.Security.Cryptography.CryptographicException. Additional information: Incorrect data."

Can any body point out where the problem is in my C# code?

this is java code:

private static byte[] coderByDES(byte[] plainText, String key, int mode)
            throws InvalidKeyException, InvalidKeySpecException,
            NoSuchAlgorithmException, NoSuchPaddingException,
            BadPaddingException, IllegalBlockSizeException,
            UnsupportedEncodingException {
        SecureRandom sr = new SecureRandom();
        byte[] resultKey = makeKey(key);
        DESKeySpec desSpec = new DESKeySpec(resultKey);
        SecretKey secretKey = SecretKeyFactory.getInstance("DES").generateSecret(desSpec);
        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(mode, secretKey, sr);
        return cipher.doFinal(plainText);
    }

private static byte[] makeKey(String key)
            throws UnsupportedEncodingException {
        byte[] keyByte = new byte[8];
        byte[] keyResult = key.getBytes("UTF-8");
        for (int i = 0; i < keyResult.length && i < keyByte.length; i++) {
            keyByte[i] = keyResult[i];
        }
        return keyByte;
    }


private static String byteArr2HexStr(byte[] arrB) {
        int iLen = arrB.length;

        StringBuilder sb = new StringBuilder(iLen * 2);
        for (int i = 0; i < iLen; i++) {
            int intTmp = arrB[i];

            while (intTmp < 0) {
                intTmp = intTmp + 256;
            }

            if (intTmp < 16) {
                sb.append("0");
            }
            sb.append(Integer.toString(intTmp, 16));
        }
        return sb.toString();
    }

this is C# code:

public static string DecryptForDES(string input, string key)
    {
        byte[] inputByteArray = HexStr2ByteArr(input);
        byte[] buffArray = null;
        using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
        {
            des.Key =  Encoding.UTF8.GetBytes(key); 
            des.IV =  Encoding.UTF8.GetBytes(key); 
            des.Mode = System.Security.Cryptography.CipherMode.ECB;
            des.Padding = PaddingMode.PKCS7;
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))
            {
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                cs.FlushFinalBlock();//
                cs.Close();
            }
            buffArray = ms.ToArray();

            ms.Close();    
        }

        string str = string.Empty;
        if (buffArray != null)
        {
            str = Encoding.UTF8.GetString(buffArray);
        }
        return str;
    }



public static byte[] HexStr2ByteArr(string strIn)
    {
        byte[] arrB = Encoding.UTF8.GetBytes(strIn);
        int iLen = arrB.Length;

        byte[] arrOut = new byte[iLen / 2];
        byte[] arrTmp = new byte[2];
        for (int i = 0; i < iLen; i = i + 2)
        {
            string strTmp = Encoding.UTF8.GetString(arrB, i, 2);
            arrOut[i / 2] = (byte)Convert.ToInt32(strTmp, 16);
        }
        return arrOut;
    }
2
  • DES is an antique encryption algorithm (read the first paragraph of it's Wikipedia entry). The CPU in your PC's keyboard could probably crack it in less that a minute. Don't use DES for anything worth encrypting Commented Nov 10, 2018 at 16:47
  • @Flydog57 Can I have your keyboard? Oh, exaggerating a bit eh what? Yes, DES should not be used but it is not nearly that quick or easy to brute force. It took the EFF DES cracker about a day. Commented Nov 10, 2018 at 22:06

1 Answer 1

1

Both, the Java encryption part and the C# decryption part work on my machine if the passwords match. Otherwise a System.Security.Cryptography.CryptographicException: 'Bad Data' is thrown. To get the password match replace in the C#-method DecryptForDES

 des.Key = Encoding.UTF8.GetBytes(key); 

with

 des.Key = MakeKey(key);

with the C#-method:

 private static byte[] MakeKey(String key)
 {
     byte[] keyByte = new byte[8];
     byte[] keyResult = Encoding.UTF8.GetBytes(key); 
     for (int i = 0; i<keyResult.Length && i<keyByte.Length; i++) {
         keyByte[i] = keyResult[i];
     }
     return keyByte;
 }

corresponding to the Java-method makeKey(String key). Moreover, remove in the C#-method DecryptForDES

 des.IV = Encoding.UTF8.GetBytes(key);

since the ECB-mode doesn't use an IV.

In the following testcase

 coderByDES("This is a plain text that needs to be encrypted...", "This is the key used for encryption...", Cipher.ENCRYPT_MODE);

returns the byte-array

 a47b1b2c90fb3b7a0ab1f51f328ff55aae3c1eb7789c31c28346696a8b1f27c7413c14e68fe977d3235b5a6f63c07d7a95d912ff22f17ad6

and

 DecryptForDES("a47b1b2c90fb3b7a0ab1f51f328ff55aae3c1eb7789c31c28346696a8b1f27c7413c14e68fe977d3235b5a6f63c07d7a95d912ff22f17ad6", "This is the key used for encryption...");                

returns the correct plain text.

By the way: As Flydog57 already stated DES is insecure (https://en.wikipedia.org/wiki/Data_Encryption_Standard). And also the ECB mode is not secure (https://crypto.stackexchange.com/questions/20941/why-shouldnt-i-use-ecb-encryption). Better choices are AES (https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) with CBC or GCM mode (https://crypto.stackexchange.com/questions/2310/what-is-the-difference-between-cbc-and-gcm-mode).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.