3

I want to encrypt a challenge (like 162236fe0bec620827958c8fdf7e4bc7 ) using this key C6864E7696C686 with the DES algorithm.

Here is my code :

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


def data = prev.getResponseData();
String challenge = javax.xml.bind.DatatypeConverter.printHexBinary(data);
final String strPassPhrase = "C6864E7696C686";

String param = challenge;
System.out.println("Text : " + param);

SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
SecretKey key = factory.generateSecret(new   DESKeySpec(hexStringToByteArray(strPassPhrase)));
Cipher cipher = Cipher.getInstance("DES");

cipher.init(Cipher.ENCRYPT_MODE, key);
String str = DatatypeConverter.printBase64Binary(cipher.doFinal(param.getBytes()));
System.out.println("Text Encryted : " + str);
cipher.init(Cipher.DECRYPT_MODE, key);
String str2 = new String(cipher.doFinal(DatatypeConverter.parseBase64Binary(str)));
System.out.println("Text Decryted : " + str2);

But i get this exception :

java.security.InvalidKeyException: Wrong key size

Edit : I have copy this function to convert my hex string to bytes :

public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
    data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                         + Character.digit(s.charAt(i+1), 16));
}
return data;
}

But I get the same exception ...

Léandre
  • 125
  • 2
  • 13

1 Answers1

6

Your DES key should be 8 bytes (56 bits + 8 parity bits).

The string you're using as a key looks like a hexadecimal representation of 7 bytes, but instead of decoding it as hex, you're getting the bytes for the characters in the hex string.

Since there are 14 characters, you will most likely (depending on your encoding) end up with 14 bytes, which is too long for DES.

There are a couple of approaches described in this question that explain how to convert the hex string to a byte array.

That will however only get you so far, because you're still one byte short. A traditional approach seems to be to take the 56 bits you have and spread them out over 8 bytes, adding one parity bit to each byte. A Java example of how to do that is described in this answer. Another approach could be to just add a null byte at the end of the key. Which approach you should take depends on the key's intended usage, especially the way it is used by the other parties you're exchanging information with.

Robby Cornelissen
  • 91,784
  • 22
  • 134
  • 156
  • Great answer :) ! – N.K Apr 24 '18 at 09:01
  • Tanks to the reply ! I've tried to spread my key out over 8 bytes but i get an ArrayIndexOutOfBoundsException – Léandre Apr 24 '18 at 09:02
  • Sounds like the array you created to hold the 8 bytes is too small. – Robby Cornelissen Apr 24 '18 at 09:10
  • I have a libray posted here [https://github.com/diakogiannis/AESEncryptor] . You can see how it is done and use it out of the box. – Alexius DIAKOGIANNIS Apr 24 '18 at 09:53
  • Just a thing : my key changed with the 64bits "conversion" (and I think it's normal ) but when I encrypt my challenge, the result is not the same if I encrypt the challenge in a site like [des-tools](http://des.online-domain-tools.com/) – Léandre Apr 24 '18 at 10:00
  • What that site does is just add a null byte to the end of the key to pad it out to 8 bytes. Encrypting with `C6864E7696C686` yields the same result as encrypting with `C6864E7696C68600`. You could easily use the same approach. In fact, far easier than adding the parity bits. I'll update my answer. – Robby Cornelissen Apr 24 '18 at 10:02
  • I like you ! It's almost the same result but there is some chars at the end of the crypted result and I don't know what they mean (Site result : `f5 f6 22 90 05 eb 3f d7 76 fd 2c ab 0c b1 79 c1` and java result : `F5 F6 22 90 05 EB 3F D7 76 FD 2C AB 0C B1 79 C1 36 95 FA 56 32 A1 80 50 `) – Léandre Apr 24 '18 at 10:18
  • Could be padding. Try specifying `Cipher.getInstance("DES/ECB/NoPadding");` for your cipher. – Robby Cornelissen Apr 24 '18 at 10:22
  • Exactly ! I think you're my hero – Léandre Apr 24 '18 at 10:27