Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Encrypting and Decrypting Using Java: Unable to get same output

I am trying to learn and test the java 1.6 encryption/decryption API. I want to know what I am doing wrong and what I am missing in terms of knowledge.

In the code that follows below, I create two ciphers: one to encrypt and another to decrypt. When I use these ciphers, I initialize them with different SecretKey's, but I am still able to get the same value back out. Why is this?

    String algorithm = "DES";
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);

    byte[] encBytes = "12345678".getBytes("UTF8");
    byte[] decBytes = "56781234".getBytes("UTF8");

    DESKeySpec keySpecEncrypt = new DESKeySpec(encBytes);
    DESKeySpec keySpecDecrypt = new DESKeySpec(decBytes);


    SecretKey keyEncrypt = keyFactory.generateSecret(keySpecEncrypt);
    SecretKey keyDecrypt = keyFactory.generateSecret(keySpecDecrypt);

    Cipher cipherEncrypt = Cipher.getInstance(algorithm);
    Cipher cipherDecrypt = Cipher.getInstance(algorithm);

    String input = "john doe";

    cipherEncrypt.init(Cipher.ENCRYPT_MODE, keyEncrypt);
    byte[] inputBytes = cipherEncrypt.doFinal(input.getBytes());
    System.out.println("inputBytes: " + new String(inputBytes));

    cipherDecrypt.init(Cipher.DECRYPT_MODE, keyDecrypt);
    byte[] outputBytes = cipherDecrypt.doFinal(inputBytes);
    System.out.println("outputBytes: " + new String(outputBytes));
like image 500
jake Avatar asked Apr 02 '11 02:04

jake


People also ask

Does IV have to be same for encryption and decryption?

You need to use the same IV for encryption and decryption.

Can you encrypt and decrypt with the same key?

Two types of encryption algorithms can be used by the encryption key server: symmetric algorithms and asymmetric algorithms. Symmetric, or secret key encryption, uses a single key for both encryption and decryption.

Which algorithm is best for encryption and decryption in Java?

The symmetric-key block cipher plays an important role in data encryption. It means that the same key is used for both encryption and decryption. The Advanced Encryption Standard (AES) is a widely used symmetric-key encryption algorithm.

What kind of encryption can not be reversed?

Data encrypted with hashing cannot be deciphered or reversed back into its original form. That's why hashing is used only as a method of verifying data.


1 Answers

Welcome to encryption! As mentioned DES is symmetric and requires the same key for encryption as decryption. That key needs to be the right number of bits for the cipher that you're using. For DES that's 56-bit. Before you go too far with that though, here are a few things you might want to consider:

  1. You should use a stronger encryption standard like AES. It's possible to break DES encryption now.
  2. If you want to use a string as the key, then you should use a strong hash function like SHA-256 against that key string. Then take as many bits from that hash output as you need for the encryption key, 128-bit is plenty sufficient for AES. Your key string should be long like you have.
  3. It'll be best to use a block cipher mode that doesn't generate the same output for the same input each time. See block cipher modes of operation for info and a visualization of why ECB mode is bad.

Here's a working example of using 128-bit AES encryption in CBC mode with PKCS #5 padding:

import java.security.MessageDigest;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class EncryptDecrypt {
    public static void main(String[] args) throws Exception {
        // here are your inputs
        String keyString = "averylongtext!@$@#$#@$#*&(*&}{23432432432dsfsdf";
        String input = "john doe";

        // setup AES cipher in CBC mode with PKCS #5 padding
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        // setup an IV (initialization vector) that should be
        // randomly generated for each input that's encrypted
        byte[] iv = new byte[cipher.getBlockSize()];
        new SecureRandom().nextBytes(iv);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);

        // hash keyString with SHA-256 and crop the output to 128-bit for key
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        digest.update(keyString.getBytes());
        byte[] key = new byte[16];
        System.arraycopy(digest.digest(), 0, key, 0, key.length);
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");

        // encrypt
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
        byte[] encrypted = cipher.doFinal(input.getBytes("UTF-8"));
        System.out.println("encrypted: " + new String(encrypted));

        // include the IV with the encrypted bytes for transport, you'll
        // need the same IV when decrypting (it's safe to send unencrypted)

        // decrypt
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        byte[] decrypted = cipher.doFinal(encrypted);
        System.out.println("decrypted: " + new String(decrypted, "UTF-8"));
    }
}
like image 101
WhiteFang34 Avatar answered Nov 15 '22 00:11

WhiteFang34