2

My code so far is:

public class TripleDES {
    /**
     * @param args the command line arguments
     * @throws java.security.NoSuchAlgorithmException
     * @throws javax.crypto.NoSuchPaddingException
     * @throws java.security.InvalidKeyException
     * @throws javax.crypto.IllegalBlockSizeException
     * @throws javax.crypto.BadPaddingException
     */
    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        //Encrypt: C = EK3(DK2(EK1(P)))
        //Decrypt: P = DK3(EK2(DK1(C)))
        
        Scanner sc = new Scanner(System.in);
        
        //Generate key for DES
        KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
        SecretKey secretKey = keyGenerator.generateKey();
        SecretKey secretKey2 = keyGenerator.generateKey();
        SecretKey secretKey3 = keyGenerator.generateKey();
        
        //Text Enc & Dec
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");



        
        //enter msg
        System.out.print("Enter a string: ");
        String x= sc.nextLine();
        
//enc
        cipher.init(Cipher.ENCRYPT_MODE,secretKey);
        byte[] message = x.getBytes();//text
        byte[] messageEnc = cipher.doFinal(message);//encryption with key1
        cipher.init(Cipher.DECRYPT_MODE,secretKey2);
        byte[] deck2 = cipher.doFinal(messageEnc);//decryption with key2
        cipher.init(Cipher.ENCRYPT_MODE,secretKey3);
        byte[] messageEnc1 = cipher.doFinal(deck2);//encryption with key3
        System.out.println("Cipher Text: " + new String(messageEnc1));
        
        //dec
        cipher.init(Cipher.DECRYPT_MODE,secretKey3);
        byte[] dec = cipher.doFinal(messageEnc1);//decryption with key1
        cipher.init(Cipher.ENCRYPT_MODE,secretKey2);
        byte[] messageEnc2 = cipher.doFinal(dec);//encryption with key2
        cipher.init(Cipher.DECRYPT_MODE,secretKey);
        byte[] deck3 = cipher.doFinal(messageEnc2);//decryption with key3
        System.out.println("Plain Text: " + new String(deck3));
    }
}

I get the error:

Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:991)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
    at com.sun.crypto.provider.DESCipher.engineDoFinal(DESCipher.java:314)
    at javax.crypto.Cipher.doFinal(Cipher.java:2164)
    at tripledes.TripleDES.main(TripleDES.java:45)

My guess is that when I try decrypting with a different key at line 45 and it gives the error above, it's because the encrypted text is larger than the key generated, but I am not quite sure.

Can someone please help as I can't figure out the problem.

Anas Nagaty
  • 151
  • 11

1 Answers1

5

I am referring to the originally posted code with the cipher, cipher2 and cipher3 instances: The problem is the padding regarding cipher2 and cipher3. Only cipher may use PKCS5Padding, cipher2 and cipher3 must apply NoPadding.

The generated ciphertext is then indeed identical to the one that would be generated by 3DES, provided that the concatenated bytes of secretKey, secretKey2 and secretKey3 are used as 3DES key.

ECB is an insecure mode, by the way, s. here.


Regarding the comments:
For the decoding of a ciphertext with a charset encoding, see e.g. Problems when converting from byte array to string and back to byte array. Concerning the missing encoding specification, s. e.g. String.getBytes() in different default charsets.

Topaco
  • 40,594
  • 4
  • 35
  • 62
  • 1
    It worked thank you, and will keep in mind that ECB is insecure :D – Anas Nagaty Apr 26 '21 at 21:26
  • 1
    Although trying to process ciphertext with `new String(byte[])` will almost always result in corruption, which with modern crypto destroys all the data. (This post only _displayed_ that way, it didn't process.) And if you encrypt one place and decrypt another as is normal (unlike the posted toy program) using the default charset with `input.getBytes()` and `new String(decrypted)` will often garble _some_ data, just as it does if you transmit the bytes without encryption. – dave_thompson_085 Apr 26 '21 at 21:35
  • @dave_thompson_085 - The missing specification of the encoding and the conversion of the ciphertext into a string with a charset encoding are common, recurring mistakes, but, yes, should also be addressed, even if they are not the actual problem. Links added that elaborate on these issues. – Topaco Apr 27 '21 at 07:01