Triple DES Encrypt C# - Decrypt in Java

后端 未结 3 1837
孤独总比滥情好
孤独总比滥情好 2021-01-07 14:45

I\'m getting a Triple DES decrypted string from the clients server, which has been coded in c# (see below):

using System.IO;
using System;
using System.Secur         


        
相关标签:
3条回答
  • 2021-01-07 15:32

    If someone find himself/herself in the same problem like I did, here is a java implementation (android) of the same .NET decrypt function:

     public static byte[] byteArrayConcat(byte[] array1, byte[] array2) {
            byte[] result = new byte[array1.length + array2.length];
            System.arraycopy(array1, 0, result, 0, array1.length);
            System.arraycopy(array2, 0, result, array1.length, array2.length);
            return result;
        }
    
    
     private byte[] fGPKeyTo3DESKey(byte[] GPKey) {
    
            byte[] _3DESKey = new byte[24];
            byte[] tmp = new byte[8];
    
            arraycopy(GPKey, 0, tmp, 0, 8);
    
            _3DESKey = DaPlugUtils.byteArrayConcat(GPKey, tmp);
    
            return _3DESKey;
        }
    
     private static byte[] hexStringtoByteArray(String hex) {
            int len = hex.length();
    
            byte[] data = new byte[len / 2];
            for (int i = 0; i < len; i += 2) {
                data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) + Character.digit(hex.charAt(i + 1), 16));
            }
            return data;
        }
    
    public String desDecryptPin(String pin, String encryptKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidKeySpecException {
    
            int bytesCount = 0;
            int positionCount = 0;
    
    
            byte[] bytEncryptedChunk = new byte[8];
    
            ArrayList<byte[]> Input = new ArrayList();
            bytesCount = pin.length();
    
            for (int i = 0; i < bytesCount; i += 2) {
                if (positionCount == 8) {
                    positionCount = 0;
                    Input.add(bytEncryptedChunk);
                    bytEncryptedChunk = new byte[8];
                }
                bytEncryptedChunk[positionCount] = (byte) (Integer.parseInt(pin.substring(i, i + 2), 16));
                positionCount++;
            }
    
            if (positionCount != 0) {
                Input.add(bytEncryptedChunk);
            }
    
    
            byte[] _3DESKey = fGPKeyTo3DESKey(hexStringtoByteArray(encryptKey));
    
            DESedeKeySpec keySpec = new DESedeKeySpec(_3DESKey);
            SecretKey k = SecretKeyFactory.getInstance("DESede").generateSecret(keySpec);
            Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
            cipher.init(Cipher.DECRYPT_MODE, k);
    
    
            String res = "";
    
            for (byte[] bs : Input) {
                byte[] decryptPin = cipher.doFinal(bs);
                String a = new String(decryptPin, StandardCharsets.US_ASCII);
    
                res += a;
            }
    
            return res.trim();
        }
    
    0 讨论(0)
  • 2021-01-07 15:38

    acording https://stackoverflow.com/a/33768305/1140304 you can use unicode instead of UTF-8 in java code

    encrypt in c# :

    public static string Encrypt2(string clearText,string key)
    {
        try
        {
            string encryptedText = "";
            MD5 md5 = new MD5CryptoServiceProvider();
            TripleDES des = new TripleDESCryptoServiceProvider();
            des.KeySize = 128;
            des.Mode = CipherMode.CBC;
            des.Padding = PaddingMode.PKCS7;
    
            byte[] md5Bytes = md5.ComputeHash(Encoding.Unicode.GetBytes(key));
    
            byte[] ivBytes = new byte[8];
    
    
            des.Key = md5Bytes;
    
            des.IV = ivBytes;
    
            byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
    
            ICryptoTransform ct = des.CreateEncryptor();
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(clearBytes, 0, clearBytes.Length);
                    cs.Close();
                }
                encryptedText = Convert.ToBase64String(ms.ToArray());
            }
            return encryptedText;
        }
        catch (Exception exception)
        {
            return "";
        }
    }
    

    for decode in c# you can use:

    public static string Decrypt2(string cipher,string key)
    {
        try
        {
            byte[] clearBytes = Convert.FromBase64String(cipher);
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] md5Bytes = md5.ComputeHash(Encoding.Unicode.GetBytes(key));
            string encryptedText = "";
            TripleDES des = new TripleDESCryptoServiceProvider();
            des.KeySize = 128;
            des.Mode = CipherMode.CBC;
            des.Padding = PaddingMode.PKCS7;
            byte[] ivBytes = new byte[8];
            des.Key = md5Bytes;
            des.IV = ivBytes;
            ICryptoTransform ct = des.CreateDecryptor();
            byte[] resultArray = ct.TransformFinalBlock(clearBytes, 0, clearBytes.Length);
            encryptedText = Encoding.Unicode.GetString(resultArray);
            return encryptedText;
        }
        catch (Exception exception)
        {
            return "";
        }
    }
    

    now, for encrypt in java you can use :

    private String _encrypt2(String clearText,String key )
    {
        try
        {
            /**
             * create md5
             */
            MessageDigest md = MessageDigest.getInstance("md5");
            byte[] digestOfPassword = md.digest(key.getBytes("UTF-16LE"));
            byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
            for (int j = 0, k = 16; j < 8; )
            {
                keyBytes[k++] = keyBytes[j++];
            }
    
    
            SecretKey secretKey = new SecretKeySpec(keyBytes, 0, 24, "DESede");
            IvParameterSpec iv = new IvParameterSpec(new byte[8]);
            Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
    
            byte[] plainTextBytes = clearText.getBytes("UTF-16LE");
            byte[] cipherText = cipher.doFinal(plainTextBytes);
    
            String output = Base64.encodeToString(cipherText,Base64.DEFAULT);
            return output;
        }
        catch (Exception ex) {}
        return "";
    }
    

    and for decrypt in java :

    private String _decrypt2(String encryptText,String key)
    {
    
        MessageDigest md = null;
        byte[] digestOfPassword = null;
    
        try
        {
            byte[] message = Base64.decode(encryptText.getBytes("UTF-16LE"), Base64.DEFAULT);
    
            /**
             * make md5
             */
            md = MessageDigest.getInstance("md5");
            digestOfPassword = md.digest(key.getBytes("UTF-16LE"));
            byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
            for (int j = 0, k = 16; j < 8; )
            {
                keyBytes[k++] = keyBytes[j++];
            }
    
            SecretKey secretKey = new SecretKeySpec(keyBytes, 0, 24, "DESede");
            IvParameterSpec iv = new IvParameterSpec(new byte[8]);
            Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
            byte[] cipherText = cipher.doFinal(message);
    
            return new String(cipherText, "UTF-16LE");
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }
        catch (InvalidKeyException e)
        {
            e.printStackTrace();
        }
        catch (InvalidAlgorithmParameterException e)
        {
            e.printStackTrace();
        }
        catch (NoSuchPaddingException e)
        {
            e.printStackTrace();
        }
        catch (BadPaddingException e)
        {
            e.printStackTrace();
        }
        catch (IllegalBlockSizeException e)
        {
            e.printStackTrace();
        }
        return "";
    }
    
    0 讨论(0)
  • 2021-01-07 15:48

    In your C# code, you use ASCII:

    bytClearText = ASCIIEncoding.ASCII.GetBytes(strClearText);
    

    While in Java you use UNICODE:

    byte[] encryptKeyBytes = encryptKey.getBytes(UNICODE_FORMAT);
    

    Try to change your C# to use UNICODE or your java code to use ASCII.

    Also, since the C# is padding the output :

    strEncryptedChar = strEncryptedChar.PadLeft(2, Convert.ToChar("0"));
    

    You probably must check to remove all the '00' in the crypted string, so 1D30CC3DE1641D7F5E821D13FC1200C3 will become 1D30CC3DE1641D7F5E821D13FC12C3

    (you must check if it's in the boundaries of an hex expression: 1C01A1 should probably be modified since it got a padding on the second Hexa 1C 01 A1: 1C1A1

    0 讨论(0)
提交回复
热议问题