Rahul Sahu
Rahul Sahu

Reputation: 284

How to encrypt URL request parameter values in java for use in an emailed link

I am facing one problem related to encrypt url request parameter values. My scene is this I am sending one hyperlink to user through email and I want to hide url contains data from user. Url contains data that I am accessing through request object in struts application. and same values I am using on jsp page by using EL. So how can I encrypt data and how to maintain on jsp page and struts also?

below code I am using for encrypt ans decrypt the data... but If i encrypt my request parameter value then how I can get decrypted value at jsp?

import java.security.Key;

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

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

@SuppressWarnings("restriction")
public class EncryptDecrypt {

    private static final String ALGO = "AES";
    private static final byte[] keyValue = new byte[] { 'T', 'h', 'e', 'B',
            'e', 's', 't', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y' };

    public static String encrypt(String Data) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.ENCRYPT_MODE, key);
        byte[] encVal = c.doFinal(Data.getBytes());
        String encryptedValue = new BASE64Encoder().encode(encVal);
        return encryptedValue;
    }

    public static String decrypt(String encryptedData) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }

    private static Key generateKey() throws Exception {
        Key key = new SecretKeySpec(keyValue, ALGO);
        return key;
    }

}

Upvotes: 5

Views: 19304

Answers (1)

Tim B
Tim B

Reputation: 41168

You can use any encryption scheme you like since you are sending the already-encrypted data to the user and then processing it again. You don't even need public/private key approaches for this.

https://stackoverflow.com/questions/4319496/how-to-encrypt-and-decrypt-data-in-java

Just encrypt the data before you send it in the email link - then when you get it back decrypt it again.


The linked question has been deleted, I've tried to get it undeleted but in case it does not here is the content. All credit to ataylor who wrote it.

Unless you have very unusual requirements, Java has most of the crypto tools you'll need.

Symmetric Encryption

Symmetric encryption uses the same key for both encryption and decryption. In Java, use an instance of javax.crypto.Cipher.

Encrypting and Decrypting

Initialize cipher in the appropriate mode and call the update and doFinal methods to encrypt or decrypt. Example:

import java.security.*;
import javax.crypto.*;

Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
aes.init(Cipher.ENCRYPT_MODE, key);
byte[] ciphertext = aes.doFinal("my cleartext".getBytes());

aes.init(Cipher.DECRYPT_MODE, key);
String cleartext = new String(aes.doFinal(ciphertext));

Creating the Keys

The key for the cipher should be an instance of javax.crypto.spec.SecretKeySpec. AES in particular requires its key to be created with exactly 128 bits (16 bytes).

A simple way to get the required number of bytes is to take a variable length passphrase and hash it with a java.security.MessageDigest such as SHA1. For example:

import java.security.*;
import javax.crypto.spec.*;

String passphrase = "correct horse battery staple";
MessageDigest digest = MessageDigest.getInstance("SHA");
digest.update(passphrase.getBytes());
SecretKeySpec key = new SecretKeySpec(digest.digest(), 0, 16, "AES");

A better way to create a key is with a SecretKeyFactory using a salt:

byte[] salt = "choose a better salt".getBytes();
int iterations = 10000;
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecretKey tmp = factory.generateSecret(new PBEKeySpec(passphrase.toCharArray(), salt, iterations, 128));
SecretKeySpec key = new SecretKeySpec(tmp.getEncoded(), "AES");

PBKDF2 is an algorithm specially designed for generating keys from passwords that is considered more secure than a simple SHA1 hash. The salt ensures your encryption won't match another encryption using the same key and cleartext and helps prevent dictionary attacks. The iterations value is an adjustable parameter. Higher values use more computing power, making brute force attacks more difficult.

Initialization Vectors

As noted in the comments, ECB almost never a good mode to use in practice. To use better modes like CBC, you'll need to provide and preserve an initialization vector.

When encrypting with CBC mode, Java will automatically generate a random initialization vector. To be able to decrypt it later, you'll need to save it along with the ciphertext:

Cipher aes = Cipher.getInstance("AES/CBC/PKCS5Padding");
aes.init(Cipher.ENCRYPT_MODE, key);
byte[] ciphertext = aes.doFinal("my cleartext".getBytes());
byte[] iv = aes.getIV();

When decrypting, pass it to the Cipher.init() method as a parameter:

Cipher aes = Cipher.getInstance("AES/CBC/PKCS5Padding");
aes.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
String cleartext = new String(aes.doFinal(ciphertext));

Asymmetric Encryption

Asymmetric encryption, also called public key encryption, uses a key pair. One part of the key is used to encrypt and the other to decrypt. This allows you to make the encryption key public, allowing anyone to generate messages only you, the holder of the private decryption key, can read. Alternatively, you can encrypt with the private key, useful for digital signatures.

Encrypting and Decrypting

As with symmetric encryption, use an instance of javax.crypto.Cipher:

import java.security.*;

Cipher rsa = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsa.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] ciphertext = rsa.doFinal("my cleartext".getBytes());

rsa.init(Cipher.DECRYPT_MODE, privateKey);
String cleartext = new String(rsa.doFinal(ciphertext));

Generating and Storing the Keys

In this case the keys will be instances of java.security.PublicKey and java.security.PrivateKey. To generate a new pair:

import java.security.*;

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();

Public and private keys can also be transformed into byte arrays for storage and transmission:

import java.security.*;
import java.security.spec.*;

KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] publicKeyBytes = publicKey.getEncoded();
KeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
PublicKey keyFromBytes = keyFactory.generatePublic(keySpec);

Upvotes: 2

Related Questions