4

For a course I am taking we are manually implementing the 3DES scheme, which is pretty straight-forward on paper (Two key, with EDE encryption). I have chosen Java as the implementation language but have run into an issue with how it handles encryption/decryption with differing keys. I keep receiving a javax.crypto.BadPaddingException error when attempting to apply the second round (i.e. "decryption" with K2). The default DES Cipher uses PKCS5Padding and I assume this is the problem, but I'm not sure how to work around it. My code for encryption is below (I hope it is not too straight-forward, less I overlooked something simple). Thank you in advance.

Key Definition (pretty basic and I will look to improve it as I've seen some different approaches while browsing around)

        KeyGenerator kgen = KeyGenerator.getInstance("DES");
        SecretKey sk_1 = kgen.generateKey(); 
        SecretKey sk_2 = kgen.generateKey();
        byte[] raw_1 = sk_1.getEncoded();
        byte[] raw_2 = sk_2.getEncoded();

        spec_1 = new SecretKeySpec(raw_1, "DES"); //key 1
        spec_2 = new SecretKeySpec(raw_2, "DES"); //key 2

        cipher = Cipher.getInstance("DES"); //standard mode is ECB which is block-by-block w/PKCS5Padding
        cipher2 = Cipher.getInstance("DES");


    protected byte[] get3DESEncryption(byte[] plaintext) throws Exception{
        byte[] output = new byte[plaintext.length];
        System.out.println("output len init: " + output.length);
        cipher.init(Cipher.ENCRYPT_MODE, spec_1);
        cipher2.init(Cipher.DECRYPT_MODE, spec_2);

        //first encryption round, key 1 used
        output = cipher.doFinal(plaintext);
        //second "encryption" round, key 2 used but decrypt run
        output = cipher2.doFinal(output);
        //third encryption round, key 1 used
        output = cipher.doFinal(output);

        //return ciphertext
        return output;
    } 
j_l
  • 51
  • 4

1 Answers1

2

The problem is that you should not use any padding on second (decrypting) and third (encrypting) steps. When you actually apply EDE you should pad only the plain text.

A transformation is of the form:

"algorithm/mode/padding" or "algorithm" (in the latter case, provider-specific default values for the mode and padding scheme are used).

So, you should explicitly tell it not to use padding on cipher2 & cipher3 (you did not created the latter one yet).

Thus, you should have three cipher objects:

  • cipher1 DES/ECB/PKCS5Padding
  • cipher2 DES/ECB/NoPadding
  • cipher3 DES/ECB/NoPadding

[EXTRA HINT]

For decryption you should initialize the ciphers differently and you should reorder the ciphers as well.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
Serge
  • 6,088
  • 17
  • 27
  • You shouldn't need to worry about this, because the first encryption should pad the output appropriately; so shouldn't this code still work? – Cory Kendall Oct 09 '12 at 04:05
  • Yes, from what I have seen the initial E will do the correct padding. I've just been using small strings (i.e. "test") and it pads correctly from 4bytes to 8. – j_l Oct 09 '12 at 04:10
  • The OP meets the problem with 2nd step - that is decryption. If it is improperly initialized (with padding) then the crypto engine tries to remove padding after decryption, but it fails as the key to decrypt is differend (as we suppose) that the key to encrypt. – Serge Oct 09 '12 at 04:10
  • The padding with EDE is used only once to pad the plain text to be a multiple of 8 characters (bytes) lenght. Then literally Encryption-Decryption-Encryption occurs without intermediate padding/unpadding – Serge Oct 09 '12 at 04:13
  • Also, if the `cipher` is an instance of Cipher.getInstance("DES/PKCS5Padding") then the third step should not be performed with it as the intermediate result will be padded again – Serge Oct 09 '12 at 04:19
  • Serge, thank you for the insight. I was under the impression that even with padding specified, it would not re-pad if the input was a multiple of 8. – j_l Oct 09 '12 at 04:28
  • it will pad always if padding is specified as there is no way to detect if padding have been applied or not. – Serge Oct 09 '12 at 04:39
  • @Serge is right. PKCS#5 padding is always applied when configured. The reason for this is that the last bytes of plain text could be mistaken for padding: they may have any value, including ones that are compatible with PKCS#5 padding (byte value `01-08` in hexadecimals). – Maarten Bodewes Oct 09 '12 at 17:12