C# to Java DES encryption

2019-02-16 06:18发布

Trying to create java class which will encrypt and decrypt as like C# code in below.

Below is my code for C#, I need to convert it to Java. Can someone help me how to do it?

I've been doing this for almost 2 days yet can't find any solutions on how to convert it. I am new to crypto.

Note - It seems C# code used ACME libraries. But in my java, i should not use ACME jar files.

public static string EncryptBase64(string key, string clearText)
    {
        if (key.Length > 8)
            key = key.Substring(0, 8);

        byte[] keyBytes = System.Text.Encoding.ASCII.GetBytes(key);
        byte[] clearBytes = GetClearTextBytes(clearText);

        // calculate the number of legitimate bytes in the last block
        byte lastByte = (byte)(8 - (clearBytes.Length - textEncoding.GetByteCount(clearText)));

        MemoryStream ms = new MemoryStream();

        DES des = new DESCryptoServiceProvider();
        des.Padding = PaddingMode.None;
        des.GenerateIV();

        System.Security.Cryptography.ICryptoTransform ict = des.CreateEncryptor(keyBytes, des.IV);
        CryptoStream cs = new CryptoStream(ms, ict, CryptoStreamMode.Write);
        cs.Write(clearBytes, 0, clearBytes.Length);
        cs.FlushFinalBlock();
        ms.Close();

        byte[] cipherBytes = ms.ToArray();

        // create a byte output stream for Acme compatibality
        MemoryStream acmeCompatStream = new MemoryStream();

        // Acme writes the IV to the frist block
        acmeCompatStream.Write(des.IV, 0, 8);

        for (int i = 0; i < cipherBytes.Length; i = i + 8)
        {
            // write the next block
            acmeCompatStream.Write(cipherBytes, i, 8);

            // write the number of valid bytes in the block
            if (i == cipherBytes.Length - 8)
                acmeCompatStream.WriteByte(lastByte);
            else
                acmeCompatStream.WriteByte(8);
        }

        acmeCompatStream.Close();

        cipherBytes = acmeCompatStream.ToArray();

        return (System.Convert.ToBase64String(cipherBytes));
    }

Below is the code which i have tried in java. I have two different encryption function. I have tried both of the encryption method. But both are not giving expected encrypted string to decrypt in acme.

    package com.abc.some.common.nativeDES;

    import java.io.ByteArrayOutputStream;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.xml.bind.DatatypeConverter;

public class DESEncrypt {
    public String keyValue = "123456789";
    public static void main(String[] args) {
        String text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><SomeRequest><OrderNumber>1564578</OrderNumber></SomeRequest>";
        String codedtext ="not encrypted";
        try{
            codedtext = new DESEncrypt().Encrypt1(text);
            //codedtext = new DESEncrypt().encrypt(text);
        }catch (Exception e) {
            System.out.println("Exception in Encryption.. " + e.getMessage());
        }

        System.out.println(codedtext);

    }
    public String Encrypt1(String CXML) {
        try {
            KeySpec myKey = new DESKeySpec(keyValue.getBytes("UTF8"));
        SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(myKey);
        Cipher ecipher = Cipher.getInstance("DES");
        ecipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] data = CXML.getBytes("ASCII");

        Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");
        c.init(Cipher.ENCRYPT_MODE, key);

        byte[] crypt = ecipher.doFinal(data);
        //String encoded = DatatypeConverter.printBase64Binary(crypt.toString().getBytes("ASCII"));
        //String encoded = DatatypeConverter.printBase64Binary(crypt.getBytes("ASCII"));

        String encoded = DatatypeConverter.printBase64Binary(crypt).toString();

        System.out.println(encoded);

        return encoded;
        } catch (Exception ex) {
        }

        return null;
    }    
}

But I have used below java file to encrypt the string which is using acme jar files. This was working as expected. But as per my project requirement i should not use the external(ACME) jar files.

package com.abc.common.encryption;

import java.io.FileInputStream;
import java.util.Properties;
import Acme.Crypto.SecurityDES;

public class ESBCryptoDES {

    public static void main(String args[]){
//      DESEncrypt("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><SomeRequest><OrderNumber>1564578</OrderNumber></SomeRequest>"
//              ,"D:\\name\\proj\\order\\Encryption\\st.properties");
        DESDecrypt("vQ9C7ZrLzjQpHvZjtHvUb0mFCr824/aClY2jKbeciczsRVr+kEETFvDuHgdBS/aLskYV3WX3U5TANSlK3pH80r3xOyn9Q8rTjlB/yXyU7J9MgibJ66jJx0wrqeloAkmQzqj+b5+I/lXANSlK3pH80kT1D+jqWAeV"
                ,"D:\\name\\proj\\order\\Encryption\\stDecrypt.properties");
    }
    public static String DESEncrypt(String SourceStrForCrypt,String PropPath) {
        String encrypt = "";
        String decrypt = "";
        // Load the property file.
        Properties prop = new Properties();
        try {
            FileInputStream in = new FileInputStream(PropPath);
            prop.load(in);
            in.close();
        } catch (Exception e) {
            System.out.println("Exception in loading property file.. "
                    + e.getMessage());
        }

        // Encrypt the given content.
        try {
            String keypath = prop.getProperty("proj.sample.DEV");
            System.out.println("sample" + keypath);

            String SourceToEncrypt = SourceStrForCrypt; //This will provide the xml string to encrypt
            // Encryption
            encrypt = SecurityDES.DesEncryptBase64(keypath,SourceToEncrypt);
            System.out.println(encrypt);
            // Decryption
            decrypt = SecurityDES.DesDecryptBase64(keypath, encrypt);
            System.out.println(decrypt);

        } catch (Exception e) {
            System.out.println("Exception in Encryption.. " + e.getMessage());
        }
        return encrypt;
    }

    public static String DESDecrypt(String SourceStrForCrypt,String PropPath) {
        // TODO Auto-generated method stub
        String decrypt = "";

        Properties prop = new Properties();

        try {
            FileInputStream in = new FileInputStream(PropPath);
            prop.load(in);
            in.close();
        } catch (Exception e) {
            System.out.println("Exception in loading property file.. "+ e.getMessage());
        }

        try {
            String abc_keyPath = prop
                    .getProperty("proj.abc.DEV");
            System.out.println("keypath" + abc_keyPath);
            // Decryption
            decrypt = SecurityDES.DesDecryptBase64(abc_keyPath, SourceStrForCrypt);
            System.out.println("decrypted..."+decrypt);

        } catch (Exception e) {
            System.out.println("Exception in Encryption.. " + e.getMessage());
        }
        return decrypt;

    }
}

1条回答
三岁会撩人
2楼-- · 2019-02-16 06:57
  • Calling doFinal() twice doesn't make sense.
  • Printing the value of byte[].toString() doesn't make sense. It doesn't contain the ciphertext.
  • Converting that to base-64 doesn't make sense. It still doesn't contain the ciphertext.

You need to convert the byte[] array returned by the first doFinal() call directly to base-64, without the round-trip to and from String() caused by calling toString() and then `getBytes().

NB For some reason you have a variable called encrypt in your decrypt method, and for some even stranger reason you are returning it instead of decrypt, which is the only variable that actually contains plaintext.

查看更多
登录 后发表回答