0

I'm implementing 3DES EDE3 with 3 different keys each of 56 bits, EK3 DK2 Ek1 plain text, 168 bits. But i don't know how to do it. i'm bigger to java.

import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class DESedeEncryption {
public static void main(String[] args) {

SecretKey k1 = generateDESkey();
SecretKey k2 = generateDESkey();
SecretKey k3 = generateDESkey();

String firstEncryption = desEncryption("plaintext", k1);
String decryption = desDecryption(firstEncryption, k2);
String secondEncryption = desEncryption(decryption, k3);
System.out.println("secondEncryption: "+secondEncryption);
System.out.println("firstEncryption: "+firstEncryption);
System.out.println("decryption: "+decryption);

}

public static SecretKey generateDESkey() {
KeyGenerator keyGen = null;
try {
    keyGen = KeyGenerator.getInstance("DESede");
} catch (Exception ex) {
  ex.printStackTrace();
}
keyGen.init(168); // key length 112 for two keys, 168 for three keys
SecretKey secretKey = keyGen.generateKey();
return secretKey;
}

public static String desEncryption(String strToEncrypt, SecretKey desKey) {
try {
    Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, desKey);
    String encryptedString = new      BASE64Encoder().encode(cipher.doFinal(strToEncrypt.getBytes()));
    return encryptedString;


} catch (Exception ex) {
  ex.printStackTrace();
}
return null;
}

public static String desDecryption(String strToDecrypt, SecretKey desKey) {
try {
    Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, desKey);
    String decryptedString = new String(cipher.doFinal(new     BASE64Decoder().decodeBuffer(strToDecrypt)));
    return decryptedString;


} 
catch (Exception ex) {
  ex.printStackTrace();
}
return null;
}
}

I'm getting following error. tell me what wrong in this. plz help us.

javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
    at com.sun.crypto.provider.DESedeCipher.engineDoFinal(DESedeCipher.java
:294)
    at javax.crypto.Cipher.doFinal(Cipher.java:2087)
    at DESedeEncryption.desDecryption(DESedeEncryption.java:55)
    at DESedeEncryption.main(DESedeEncryption.java:17)
java.lang.NullPointerException
    at DESedeEncryption.desEncryption(DESedeEncryption.java:41)
    at DESedeEncryption.main(DESedeEncryption.java:18)
secondEncryption: null
firstEncryption: sP0ySxvxaUP+0a9l5qWSLQ==
decryption: null

Thanks in advance

user3201607
  • 79
  • 1
  • 1
  • 9

2 Answers2

0

Your code of your main() method doesn't make any sense. You're trying to decrypt with k2 a message which has been encrypted with k1. That can't work.

You don't seem to understand what DESede does. You don't need to encrypt then decrypt then encrypt with 3 different keys. You simply provide a key that has 3 times the length of a simple DES key, and the DESede cipher splits the key in 3 parts and does the three steps for you. So, as with any other Cipher, to check that it works fine, you should simply do:

SecretKey key = generateKey();
byte[] clearText = ...;
byte[] encrypted = encrypt(clearText, key);
byte[] decrypted = decrypt(encrypted, key);
// decrypted should contain the same bytes as clearText
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • can u tell me on thing that, in 3DES EDE3 we have to use 3 different keys each of 56 bits. now i'm implementing this only. i don't know tell me plz. – user3201607 Mar 09 '14 at 18:03
  • No. You pass a single key of 24 bytes (DESedeKeySpec.DES_EDE_KEY_LEN), and the algorithm splits it for you in 3 chunks of 8 bytes. See http://docs.oracle.com/javase/7/docs/api/javax/crypto/spec/DESedeKeySpec.html#DES_EDE_KEY_LEN – JB Nizet Mar 09 '14 at 18:24
  • Is it correct or not http://javatutorialandprojects.blogspot.in/2014/03/3des-in-java.html – user3201607 Mar 09 '14 at 18:33
  • The bytesToString() method is incorrect. It should simply do `new String(bytes, UNICODE_FORMAT)`. Other than that, the code is not well designed, but correct. But what's the point of copy and pasting code from a random site if you don't understand it? Especially security-related code? – JB Nizet Mar 09 '14 at 18:40
  • You've been explained how it works in two different answers and one comment already. Read them. What don't you understand in "You simply provide a key that has 3 times the length of a simple DES key, and the DESede cipher splits the key in 3 parts and does the three steps for you"? Isn't that clear enough? – JB Nizet Mar 09 '14 at 19:19
0

You seem to misunderstand 3DES. The internal algorithm performs the encrypt/decrypt/encrypt operations already, so you don't need to perform that yourself. Just pass a key that's 168 bits long (3 × 56-bit) into your cipher and it'll do the job.

Additionally, the conversion to Base64 is failing. When you're running this:

String encryptedString = new BASE64Encoder().encode(cipher.doFinal(strToEncrypt.getBytes()));

You're actually calling toString() on the result of doFinal() before it's passed to encode(), causing it to return the Java reference rather than the actual contents of the array. Someone else made exactly the same mistake in an earlier question.

That said, you're using ECB for your block cipher mode. ECB (or Electronic Codebook) mode works by running each cryptographic transform on every block independently, resulting in the same ciphertext block being produced for identical ciphertext blocks when the same key is used. Wikipedia's entry on this has a great visual representation of how this kind of cryptographic process is broken.

I suggest using Cipher Block Chaining (CBC) mode instead, which combines each plaintext block with the previous ciphertext block. This ensures that equal blocks of plaintext don't produce the same blocks of ciphertext. The additional requirement here is an Initialisation Vector (IV), which is a unique random value used as the "previous block" for the first plaintext block (which obviously can't have a previous ciphertext block - it's the first one). The IV doesn't have to be secret, so you just generate it, use it, and prepend it to the encrypted message. On decryption you strip that value off, then use it to decrypt along with the key.

Community
  • 1
  • 1
Polynomial
  • 27,674
  • 12
  • 80
  • 107