Encrypted length not the same as decrypted length.

I have been told that when using Triple DES if you are encrypting 8 bytes of data, using a 24 byte key (3 64 bit keys?), the encrypted byte array should be 8 bytes, however, I am getting 16 bytes always (the last 8 bytes are the same within the encrypted data, but it is 16 just the same). Follows is my code;

DESedeKeySpec keyspec = new DESedeKeySpec("012345670123456701234567".getBytes("UTF8"));

SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DESede");

SecretKey expKey = keyfactory.generateSecret(keyspec);

Cipher cipher = Cipher.getInstance("DESede");

cipher.init(Cipher.ENCRYPT_MODE, expKey);

byte[] enc = cipher.doFinal("01234567".getBytes("UTF8"));

byte[] enc1 = cipher.doFinal("77777777".getBytes("UTF8"));

byte[] enc2 = cipher.doFinal("66666666".getBytes("UTF8"));

BASE64Encoder b64e = new BASE64Encoder();

String string1 = b64e.encode(enc);

String string2 = b64e.encode(enc1);

String string3 = b64e.encode(enc2);

System.out.println("enc is " + string1 + ":" + "enc length " + enc.length);

System.out.println("enc is " + string2 + ":" + "enc length " + enc1.length);

System.out.println("enc is " + string3 + ":" + "enc length " + enc2.length);

Altering the key spec length is not an option, as I receive wrong size key.

[1348 byte] By [wlgoldm1a] at [2007-9-21]
# 1

Padding. You're encrypting 8 bytes. DES is an 8-byte block cipher. It wants to add padding-info at the end of your stream. It can't fit it into the first block- that's full. So it has to add it to the second (empty) block, and pad it to an 8-byte boundary.

Shorten your test-data to less than 8 bytes, and notice that the encrypted-size will go to 8. Lengthen it to 8<size><16 and watch the result go to 16. Lengthen it to 16 <= size < 24, and watch it go to 24.

Good luck,

Grant

ggaineya at 2007-7-14 > top of java,Security,Cryptography...
# 2

Just realized something - if you know that your data is always a multiple of 8 bytes, you can skip padding altogether, and your ciphertext will always be the same size as your plaintext. Change thisCipher cipher = Cipher.getInstance("DESede");

to thisCipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");

Good luck,

Grant

ggaineya at 2007-7-14 > top of java,Security,Cryptography...
# 3
Not to "NoPadding", but to "PKCS5Padding" instead.
euxxa at 2007-7-14 > top of java,Security,Cryptography...
# 4

No, because PKCS5Padding is what's causing his problem - it's adding the pad-bytes, and he doesn't want them. Hence my "if you know your data is in multiples of eight bytes" - if that's the case, he uses NoPadding and his ciphertext doesn't grow.

Of course, if "multiples of eight" isn't true, then he gets exceptions. Such is the tradeoff. ;)

Grant

ggaineya at 2007-7-14 > top of java,Security,Cryptography...
# 5
Sorry, I just misreading the original question. Even it does not make any sence...
euxxa at 2007-7-14 > top of java,Security,Cryptography...
# 6
Actualyl is he uses CFB8 or OFB8 modes then he doesn't need to worry about how long his input plain text and the output ciphertext will always be the same length as the input.... Both of these modes operate like a stream cipher... Issue is the **** IV.... ;(
floersha at 2007-7-14 > top of java,Security,Cryptography...
# 7
Changed it to NoPadding and it worked.
wlgoldm1a at 2007-7-14 > top of java,Security,Cryptography...
# 8

Hi,

The NoPadding if we calculate the length on the bytes.

I'm looking for the length of actual string.

I was hoping (from the below code) that string1, string2, and string3 would be length of 8.

Is it possible ?

Thanks..

quent

DESedeKeySpec keyspec = new DESedeKeySpec("012345670123456701234567".getBytes("UTF8"));

SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DESede");

SecretKey expKey = keyfactory.generateSecret(keyspec);

Cipher cipher = Cipher.getInstance("DESede");

cipher.init(Cipher.ENCRYPT_MODE, expKey);

byte[] enc = cipher.doFinal("01234567".getBytes("UTF8"));

byte[] enc1 = cipher.doFinal("77777777".getBytes("UTF8"));

byte[] enc2 = cipher.doFinal("66666666".getBytes("UTF8"));

BASE64Encoder b64e = new BASE64Encoder();

String string1 = b64e.encode(enc);

String string2 = b64e.encode(enc1);

String string3 = b64e.encode(enc2);

System.out.println("enc is " + string1 + ":" + "enc length " + string1.length);

System.out.println("enc is " + string2 + ":" + "enc length " + string2.length);

System.out.println("enc is " + string3 + ":" + "enc length " + string3.length);

querenta at 2007-7-14 > top of java,Security,Cryptography...
# 9

Base64 always enlarges its input, by 4/3rds - it's the way the encoding works. It has nothing to do with padding.

I believe that DESede defaults to PKCS5Padding, which will enlarge the ciphertext by 8 bytes if the plaintext is an exact multiple of 8 bytes (see the discussion at the head of this thread).

So - your three 8-byte strings will encipher to 16 bytes, and then encode to ~22 bytes when Base64'd.

If you don't want any expansion, follow some of the earlier advice regarding padding options, and don't Base64 the resulting ciphertext.

Good luck,

Grant

ggaineya at 2007-7-14 > top of java,Security,Cryptography...