Nowadays, information security is the main concern on the Internet. With web data continuously flowing from one end to another, to ensure data security, there are many procedures that must be implemented. Different organizations are working to find a more secure way to protect data.

There are also some key terms when it comes to information security — like confidentiality, integrity, availability, etc. Confidentiality means that only authorized users can gain access to sensitive data. Integrity confirms that data has not been modified by any mid-level person. Additionally, this means that the data reached the other user without changes or a breach. Lastly, availability means that data is available for any authorized user. There are many procedures that confirm data confidentiality, integrity, and availability. Almost all procedures use some type of encryption/decryption algorithm to keep data secure from middle attacks. And there are two kinds of security algorithms: symmetric algorithms (use the same secret key to encrypt/decrypt data) and asymmetric algorithms (use different secret keys to encrypt/decrypt data). The main goal of this article is to describe DES algorithm and how it secures data. 

DES Algorithm

The DES algorithm is the most popular security algorithm. It's a symmetric algorithm, which means that the same keys are used to encrypt/decrypt sensitive data. Key length is 8 byte (64 bit). So, to encrypt/decrypt data, the DES algorithm uses an 8-byte key, but 1 byte (8 bit) for parity checking. It's a block cipher algorithm — that's why the data block size of DES algorithm is 64 bit. To encrypt/decrypt data, the DES algorithm uses the Feistel structure. So, it uses some round to encrypt/decrypt data. Though data block size is 64 bit, the number of rounds will be 16 rounds. So, it will use different subkeys for each round. so the number of subkeys will be 16 subkeys. For more info on the process of finding subkeys, you can learn more here. However, for this tutorial, we will be skipping this part.

Modes of Operation

There are different modes of operation when using the DES algorithm. If each 64 bit is encrypted or decrypted independently, then this mode is ECB.

ECB

  If each 64-bit data is dependent on the previous one, then this mode is called CBC or CFB mode.

Image title

Here, in CBC mode, we can see that there is a new term called the Initial Vector (IV), which will be the same as the data block size. The data block will be XOR with IV and then encrypted with the key. Then, the output ciphertext uses the IV of the next block. The reverse process is used during decryption. So, we can say that the encryption of the current block is dependent on the encryption of the previous data block. Therefore, it's more secure than that of ECB.

Image title

In CFB mode, the intial vector is encrypted with a key, and then, the data block will XOR with encrypted output. Ciphertext, again, goes to it as an input for encryption function and again XOR with next plaintext block and so on.

Terms to Memorize

  • The DES algorithm is a block cipher algorithm
  • The data block size of the DES algorithm is 64 bit (8 bytes)
  • Key size is 64 bit (8 bytes), but 1 byte is used for parity, so the actual key size is 56 bit
  • Without ECB, for others, IV is mandatory
  • There are different types of padding algorithms. If you use NoPadding, the data size should be a multiple of 8.

Implementation

For implementation, we have to use a security provider. In this case, we will use the bouncycastle provider. We can use a secret key as a plaintext or byte array that will be defined by us, or we can generate a random secret key using the KeyGenerator from javax.crypto package. We will see both methods. So now, we have to add a provider.

Security.addProvider(new BouncyCastleProvider());


And for encryption and decryption, we will use the following methods. I have created an interface to declare these methods.

package des.algo;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public interface DesAlgorithm {
    String encrypt(String data, SecretKey key, String algo) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException;

    String decrypt(String data, SecretKey key, String algo) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException;

    String encrypt(String data, byte[] key, String algo) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException;

    String decrypt(String data, byte[] key, String algo) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException;
}


Here, the first two methods will be used for randomly generated secret keys, and the next two methods will be used for the user-provided secret key. Implementation of this interface is demonstrated below:

package des.algo;

import des.constants.DesConstants;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;

public class DesAlgorithmImpl implements DesAlgorithm {

    public String encrypt(String data, SecretKey key, String algo) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        return cryptoData(algo, key, Cipher.ENCRYPT_MODE, data.getBytes());
    }

    public String decrypt(String data, SecretKey key, String algo) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        return cryptoData(algo, key, Cipher.DECRYPT_MODE, DatatypeConverter.parseHexBinary(data));
    }

    public String encrypt(String data, byte[] sKey, String algo) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        SecretKey key = new SecretKeySpec(sKey, algo);
        return cryptoData(algo, key, Cipher.ENCRYPT_MODE, data.getBytes());
    }

    public String decrypt(String data, byte[] sKey, String algo) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        SecretKey key = new SecretKeySpec(sKey, algo);
        return cryptoData(algo, key, Cipher.DECRYPT_MODE, DatatypeConverter.parseHexBinary(data));
    }

    private String cryptoData(String algo, SecretKey key, int encryptMode, byte[] bytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = Cipher.getInstance(algo);
        if (algo.contains("ECB")) {
            cipher.init(encryptMode, key);
        } else {
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(DesConstants.iv);
            cipher.init(encryptMode, key, paramSpec);
        }
        byte[] encryptedResult = cipher.doFinal(bytes);
        return DatatypeConverter.printHexBinary(encryptedResult);
    }


}


Here, we can see that we are not using IV for ECB. We created a cipher instance and init this with DES parameters. For encryption, we are using the Cipher mode ENCRYPT_MODE, and for decrypt, we are using DECRYPT_MODE. Other parameters remain the same for both encryption and decryption. The key should be the same for encryption and decryption.

Now, we will call these methods from our main application class.

package des;

import des.algo.DesAlgorithm;
import des.algo.DesAlgorithmImpl;
import des.constants.DesConstants;
import des.enums.Algorithm;
import des.enums.ChipperMode;
import des.enums.DesPaddingMode;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.*;
import javax.xml.bind.DatatypeConverter;
import java.security.*;
import java.util.Scanner;

public class DesApp {

    DesAlgorithm desAlgorithm = new DesAlgorithmImpl();

    public String encrypt(String dataToEncrypt, SecretKey key, String algo) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {

        return desAlgorithm.encrypt(dataToEncrypt, key, algo);
    }

    public String decrypt(String dataToDecrypt, SecretKey key, String algo) throws NoSuchAlgorithmException, BadPaddingException, NoSuchPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidAlgorithmParameterException {
        return desAlgorithm.decrypt(dataToDecrypt, key, algo);
    }

    public String encrypt(String dataToEncrypt, byte[] key, String algo) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {

        return desAlgorithm.encrypt(dataToEncrypt, key, algo);
    }

    public String decrypt(String dataToDecrypt, byte[] key, String algo) throws NoSuchAlgorithmException, BadPaddingException, NoSuchPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidAlgorithmParameterException {
        return desAlgorithm.decrypt(dataToDecrypt, key, algo);
    }

    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, NoSuchPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        Security.addProvider(new BouncyCastleProvider());

        SecretKey secretKey = getSecretKey(Algorithm.DES.getValue());
        System.out.println("Secret Key : " + DatatypeConverter.printHexBinary(secretKey.getEncoded()));
        DesApp desApp = new DesApp();

        System.out.println("Enter your data to encrypt : ");

        Scanner scanner = new Scanner(System.in);
        String dataToEncrypt = scanner.next();
        System.out.println("Original data : " + DatatypeConverter.printHexBinary(dataToEncrypt.getBytes()));
        String encryptedData = desApp.encrypt(dataToEncrypt, DesConstants.baseKey, getAlgo(Algorithm.DES.getValue(),ChipperMode.CBC.getValue(),DesPaddingMode.PKCS5_PADDING.getValue()));
        System.out.println("Encrypted Data : " + encryptedData);
        String decryptedData = desApp.decrypt(encryptedData, DesConstants.baseKey, getAlgo(Algorithm.DES.getValue(),ChipperMode.CBC.getValue(),DesPaddingMode.PKCS5_PADDING.getValue()));
        System.out.println("DecryptedData : " + decryptedData);

        System.out.println("#######################################################################");
        System.out.println("Original data : " + DatatypeConverter.printHexBinary(dataToEncrypt.getBytes()));
        encryptedData = desApp.encrypt(dataToEncrypt, secretKey, getAlgo(Algorithm.DES.getValue(),ChipperMode.CBC.getValue(),DesPaddingMode.PKCS5_PADDING.getValue()));
        System.out.println("Encrypted Data : " + encryptedData);
        decryptedData = desApp.decrypt(encryptedData, secretKey, getAlgo(Algorithm.DES.getValue(),ChipperMode.CBC.getValue(),DesPaddingMode.PKCS5_PADDING.getValue()));
        System.out.println("DecryptedData : " + decryptedData);

    }

    private static String getAlgo(String algo,String cipherMode, String paddingMode) {
        return algo + "/" + cipherMode + "/" + paddingMode ;
    }

    private static SecretKey getSecretKey(String algo) throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(algo);
        SecureRandom secureRandom = new SecureRandom();
        int keyBitSize = 56;
        keyGenerator.init(keyBitSize, secureRandom);
        return keyGenerator.generateKey();
    }
}


Here, we can see that we added the bouncy castle provider first and then created a random secret key. Also we are using a user-provided secret key as the byte format. This is shown below:

package des.constants;

public class DesConstants {
    public static final byte[] baseKey = new byte[] { (byte) 0x50, (byte) 0x61, (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47};
    public static final byte[] iv = { 11, 22, 33, 44, 99, 88, 77, 66 };
}


Then, we are calling interface methods and getting the expected output. Yes, we are providing the algorithm, ciphermode, and padding mechanism with the getAlgo() method.  If we run this code exactly as given in this article, we can get this result for the inputsanjoysystem:

/usr/lib/jvm/java-8-oracle/bin/java -javaagent:/home/sanjoy/.local/share/JetBrains/Toolbox/apps/IDEA-C/ch-0/183.4588.61/lib/idea_rt.jar=41591:/home/sanjoy/.local/share/JetBrains/Toolbox/apps/IDEA-C/ch-0/183.4588.61/bin -Dfile.encoding=UTF-8 -classpath /usr/lib/jvm/java-8-oracle/jre/lib/charsets.jar:/usr/lib/jvm/java-8-oracle/jre/lib/deploy.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/cldrdata.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/dnsns.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/jaccess.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/jfxrt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/localedata.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/nashorn.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunec.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunjce_provider.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunpkcs11.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/zipfs.jar:/usr/lib/jvm/java-8-oracle/jre/lib/javaws.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jce.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfr.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfxswt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jsse.jar:/usr/lib/jvm/java-8-oracle/jre/lib/management-agent.jar:/usr/lib/jvm/java-8-oracle/jre/lib/plugin.jar:/usr/lib/jvm/java-8-oracle/jre/lib/resources.jar:/usr/lib/jvm/java-8-oracle/jre/lib/rt.jar:/home/sanjoy/Projects/CryptographicAlgorithms/target/classes:/home/sanjoy/.m2/repository/org/bouncycastle/bcprov-jdk15on/1.60/bcprov-jdk15on-1.60.jar des.DesApp
Secret Key : 1CAB250D767F0E0B
Enter your data to encrypt : 
sanjoysystem
Original data : 73616E6A6F7973797374656D
Encrypted Data : B5DA0BFE5FE1C38608326A41F14A8236
DecryptedData : 73616E6A6F7973797374656D
#######################################################################
Original data : 73616E6A6F7973797374656D
Encrypted Data : 8A3297D18CE21F0CBEDFA392ACEFBBBE
DecryptedData : 73616E6A6F7973797374656D

Process finished with exit code 0


Test With Different Combination

Now, we will check the DES algorithm with a different combination. For example, we will select the ECB mode as a cipher mode. We have to change the following code:

    System.out.println("Original data : " + DatatypeConverter.printHexBinary(dataToEncrypt.getBytes()));
        String encryptedData = desApp.encrypt(dataToEncrypt, DesConstants.baseKey, getAlgo(Algorithm.DES.getValue(),ChipperMode.ECB.getValue(),DesPaddingMode.PKCS5_PADDING.getValue()));
        System.out.println("Encrypted Data : " + encryptedData);
        String decryptedData = desApp.decrypt(encryptedData, DesConstants.baseKey, getAlgo(Algorithm.DES.getValue(),ChipperMode.ECB.getValue(),DesPaddingMode.PKCS5_PADDING.getValue()));
        System.out.println("DecryptedData : " + decryptedData);

        System.out.println("#######################################################################");
        System.out.println("Original data : " + DatatypeConverter.printHexBinary(dataToEncrypt.getBytes()));
        encryptedData = desApp.encrypt(dataToEncrypt, secretKey, getAlgo(Algorithm.DES.getValue(),ChipperMode.ECB.getValue(),DesPaddingMode.PKCS5_PADDING.getValue()));
        System.out.println("Encrypted Data : " + encryptedData);
        decryptedData = desApp.decrypt(encryptedData, secretKey, getAlgo(Algorithm.DES.getValue(),ChipperMode.ECB.getValue(),DesPaddingMode.PKCS5_PADDING.getValue()));
        System.out.println("DecryptedData : " + decryptedData);


Now, if we run this code, we will get the following result.

/usr/lib/jvm/java-8-oracle/bin/java -javaagent:/home/sanjoy/.local/share/JetBrains/Toolbox/apps/IDEA-C/ch-0/183.4588.61/lib/idea_rt.jar=38483:/home/sanjoy/.local/share/JetBrains/Toolbox/apps/IDEA-C/ch-0/183.4588.61/bin -Dfile.encoding=UTF-8 -classpath /usr/lib/jvm/java-8-oracle/jre/lib/charsets.jar:/usr/lib/jvm/java-8-oracle/jre/lib/deploy.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/cldrdata.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/dnsns.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/jaccess.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/jfxrt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/localedata.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/nashorn.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunec.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunjce_provider.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunpkcs11.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/zipfs.jar:/usr/lib/jvm/java-8-oracle/jre/lib/javaws.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jce.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfr.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfxswt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jsse.jar:/usr/lib/jvm/java-8-oracle/jre/lib/management-agent.jar:/usr/lib/jvm/java-8-oracle/jre/lib/plugin.jar:/usr/lib/jvm/java-8-oracle/jre/lib/resources.jar:/usr/lib/jvm/java-8-oracle/jre/lib/rt.jar:/home/sanjoy/Projects/CryptographicAlgorithms/target/classes:/home/sanjoy/.m2/repository/org/bouncycastle/bcprov-jdk15on/1.60/bcprov-jdk15on-1.60.jar des.DesApp
Secret Key : 68E3C28CAD2A10D5
Enter your data to encrypt : 
sanjoysystem
Original data : 73616E6A6F7973797374656D
Encrypted Data : 78A591423E9C877CD57BDFA75B83AA6F
DecryptedData : 73616E6A6F7973797374656D
#######################################################################
Original data : 73616E6A6F7973797374656D
Encrypted Data : E4D973CB640E5344F28F6CF2F449BF73
DecryptedData : 73616E6A6F7973797374656D


Now, if we change the padding mechanism to NoPadding, let's check what the result will be. Just change this for method callings:

DesPaddingMode.NO_PADDING.getValue()


Now, I am getting this result:

/usr/lib/jvm/java-8-oracle/bin/java -javaagent:/home/sanjoy/.local/share/JetBrains/Toolbox/apps/IDEA-C/ch-0/183.4588.61/lib/idea_rt.jar=35051:/home/sanjoy/.local/share/JetBrains/Toolbox/apps/IDEA-C/ch-0/183.4588.61/bin -Dfile.encoding=UTF-8 -classpath /usr/lib/jvm/java-8-oracle/jre/lib/charsets.jar:/usr/lib/jvm/java-8-oracle/jre/lib/deploy.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/cldrdata.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/dnsns.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/jaccess.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/jfxrt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/localedata.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/nashorn.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunec.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunjce_provider.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunpkcs11.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/zipfs.jar:/usr/lib/jvm/java-8-oracle/jre/lib/javaws.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jce.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfr.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfxswt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jsse.jar:/usr/lib/jvm/java-8-oracle/jre/lib/management-agent.jar:/usr/lib/jvm/java-8-oracle/jre/lib/plugin.jar:/usr/lib/jvm/java-8-oracle/jre/lib/resources.jar:/usr/lib/jvm/java-8-oracle/jre/lib/rt.jar:/home/sanjoy/Projects/CryptographicAlgorithms/target/classes:/home/sanjoy/.m2/repository/org/bouncycastle/bcprov-jdk15on/1.60/bcprov-jdk15on-1.60.jar des.DesApp
Secret Key : E362984C946E89C1
Enter your data to encrypt : 
sanjoysystem
Original data : 73616E6A6F7973797374656D
Exception in thread "main" javax.crypto.IllegalBlockSizeException: data not block size aligned
at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(Unknown Source)
at javax.crypto.Cipher.doFinal(Cipher.java:2164)
at des.algo.DesAlgorithmImpl.cryptoData(DesAlgorithmImpl.java:42)
at des.algo.DesAlgorithmImpl.encrypt(DesAlgorithmImpl.java:26)
at des.DesApp.encrypt(DesApp.java:31)
at des.DesApp.main(DesApp.java:50)

Process finished with exit code 1


Yes, this is correct because the data block is not a multiple of 8. The length of the sanjoysystem is 12. There is no padding mechanism being used now. That's why the data remains the same, but if we use another padding mechanism, then the mechanism will add padding with actual data. And the input of the encryption data will be multiplied by 8. And during decryption, this padded data will be removed. Try this with  sanjoysy; we will get the correct result.

Now, we will check this by changing the key size. We will change the key size to 65 (which is more than 8 bytes, and we can define the key size between 56 to 64 for the DES key). The key generator only accepts key sizes 56 to 64 bit. Then, it will generate an 8-byte size key for the Cipher. Change on following keySize to 65:


    private static SecretKey getSecretKey(String algo) throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(algo);
        SecureRandom secureRandom = new SecureRandom();
        int keyBitSize = 65;
        keyGenerator.init(keyBitSize, secureRandom);
        return keyGenerator.generateKey();
    }


We will get the following output because KeyGenerator cannot generate a key for keySize smaller than 56 bit or more than 64 bit.

Exception in thread "main" java.security.InvalidParameterException: Wrong keysize: must be equal to 56
at com.sun.crypto.provider.DESKeyGenerator.engineInit(DESKeyGenerator.java:90)
at javax.crypto.KeyGenerator.init(KeyGenerator.java:517)
at des.DesApp.getSecretKey(DesApp.java:72)
at des.DesApp.main(DesApp.java:41)


Or, we can change the user-defined key (baseKey). 

 public static final byte[] baseKey = new byte[] { (byte) 0x41, (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47};


We will get the following exception. Because the DES key should be 8 bytes, Cipher — for the DES algorithm only — accepts the 8-byte key. With a random key size of 56, KeyGenerator internally generates 8-byte size key and then supplies to Cipher.

/usr/lib/jvm/java-8-oracle/bin/java -javaagent:/home/sanjoy/.local/share/JetBrains/Toolbox/apps/IDEA-C/ch-0/183.4588.61/lib/idea_rt.jar=35195:/home/sanjoy/.local/share/JetBrains/Toolbox/apps/IDEA-C/ch-0/183.4588.61/bin -Dfile.encoding=UTF-8 -classpath /usr/lib/jvm/java-8-oracle/jre/lib/charsets.jar:/usr/lib/jvm/java-8-oracle/jre/lib/deploy.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/cldrdata.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/dnsns.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/jaccess.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/jfxrt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/localedata.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/nashorn.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunec.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunjce_provider.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunpkcs11.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/zipfs.jar:/usr/lib/jvm/java-8-oracle/jre/lib/javaws.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jce.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfr.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfxswt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jsse.jar:/usr/lib/jvm/java-8-oracle/jre/lib/management-agent.jar:/usr/lib/jvm/java-8-oracle/jre/lib/plugin.jar:/usr/lib/jvm/java-8-oracle/jre/lib/resources.jar:/usr/lib/jvm/java-8-oracle/jre/lib/rt.jar:/home/sanjoy/Projects/CryptographicAlgorithms/target/classes:/home/sanjoy/.m2/repository/org/bouncycastle/bcprov-jdk15on/1.60/bcprov-jdk15on-1.60.jar des.DesApp
Secret Key : 8A541A071A8C8AA7
Enter your data to encrypt : 
sanjoysy
Original data : 73616E6A6F797379
Exception in thread "main" java.security.InvalidKeyException: Wrong algorithm: DES required
at com.sun.crypto.provider.DESCrypt.init(DESCrypt.java:533)
at com.sun.crypto.provider.ElectronicCodeBook.init(ElectronicCodeBook.java:94)
at com.sun.crypto.provider.CipherCore.init(CipherCore.java:591)
at com.sun.crypto.provider.CipherCore.init(CipherCore.java:467)
at com.sun.crypto.provider.DESCipher.engineInit(DESCipher.java:186)
at javax.crypto.Cipher.implInit(Cipher.java:801)
at javax.crypto.Cipher.chooseProvider(Cipher.java:863)
at javax.crypto.Cipher.init(Cipher.java:1248)
at javax.crypto.Cipher.init(Cipher.java:1185)
at des.algo.DesAlgorithmImpl.cryptoData(DesAlgorithmImpl.java:37)
at des.algo.DesAlgorithmImpl.encrypt(DesAlgorithmImpl.java:26)
at des.DesApp.encrypt(DesApp.java:31)
at des.DesApp.main(DesApp.java:50)


However, you can try more combinations than just those defined above. 

The entire source code from this article is available here.

Happy encrypting!