加密和编码URL参数spring mvc

时间:2015-05-05 20:15:13

标签: java encryption

我正在编写一个Spring mvc应用程序,它需要发送一封带有链接和加密参数的电子邮件。用户将单击该链接,我需要在新页面中解密params。所以我正在编写一个util类来加密和解密以及编码和解码参数。

当我独立运行java类(用于测试)时 - 调用解密时会出现以下错误(加密,编码,解码工作正常)。

java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long
    at com.sun.crypto.provider.CipherCore.init(CipherCore.java:430)
    at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:217)
    at javax.crypto.Cipher.implInit(Cipher.java:791)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:849)
    at javax.crypto.Cipher.init(Cipher.java:1348)

我的课程在下面

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;

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


import org.apache.commons.codec.binary.Base64;

public class TestEncryptionEncode2 {

    private String keyString = "asdfgh";

    public static void main(String[] args) throws Exception {
         TestEncryptionEncode2 api = new TestEncryptionEncode2();

         String input = "abcdwer.comq1234";

        try {       
            String[] encrypted = api.encryptObject(input);  
            // url may differ.. based upon project initial context
            System.out.println("http://localhost:8080/view?d="+encrypted[0]+"&v="+encrypted[1]);

                        Object obj = api.decryptObject(encrypted[0], encrypted[1]);
                        System.out.println("Object Decrypted: "+obj.toString());

        }catch(Exception e) {
            //logger.debug("Unable to encrypt view id: "+id, e);
                    e.printStackTrace();
        }   

                System.out.println("DONEE ");

     }

    private String[] encryptObject(Object obj) throws Exception {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        ObjectOutput out = new ObjectOutputStream(stream);
        try {
            // Serialize the object         
            out.writeObject(obj);       
            byte[] serialized = stream.toByteArray();

                        System.out.println("serialized "+serialized[0]);

            // Setup the cipher and Init Vector
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            byte[] iv = new byte[cipher.getBlockSize()];

                System.out.println("cipher.getBlockSize() "+cipher.getBlockSize());
                System.out.println("iv.length "+iv.length);


            new SecureRandom().nextBytes(iv);
            IvParameterSpec ivSpec = new IvParameterSpec(iv);

            // Hash the key with SHA-256 and trim the output to 128-bit for the 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);

            // Encrypt & Encode the input
            byte[] encrypted = cipher.doFinal(serialized);       
            byte[] base64Encoded = Base64.encodeBase64(encrypted);
            String base64String = new String(base64Encoded);
            String urlEncodedData = URLEncoder.encode(base64String,"UTF-8");

            // Encode the Init Vector
            byte[] base64IV = Base64.encodeBase64(iv);
            String base64IVString = new String(base64IV);
            String urlEncodedIV = URLEncoder.encode(base64IVString, "UTF-8");

                System.out.println("urlEncodedData.length "+urlEncodedData.length());
                System.out.println("urlEncodedIV.length "+urlEncodedIV.length());


            return new String[] {urlEncodedData, urlEncodedIV};
        }finally {
            stream.close();
            out.close();
        }
    }

    /**
     * Decrypts the String and serializes the object
     * @param base64Data
     * @param base64IV
     * @return
     * @throws Exception
     */
    public Object decryptObject(String base64Data, String base64IV) throws Exception {

            System.out.println("decryptObject "+base64Data);
            System.out.println("decryptObject "+base64IV);

        // Decode the data
        byte[] encryptedData = Base64.decodeBase64(base64Data.getBytes()); 

        // Decode the Init Vector
        byte[] rawIV = Base64.decodeBase64(base64IV.getBytes()); 
        System.out.println("rawIV "+rawIV.length);
                for (int i=0;i < rawIV.length;i++ ){
                    System.out.println("---------"+rawIV[i]);
                }
        // Configure the Cipher
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec ivSpec = new IvParameterSpec(rawIV); 
        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");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); //////////////////////////////This is the error line

        // Decrypt the data..
        byte[] decrypted = cipher.doFinal(encryptedData);

        // Deserialize the object       
        ByteArrayInputStream stream = new ByteArrayInputStream(decrypted);
        ObjectInput in = new ObjectInputStream(stream);
        Object obj = null;
        try {
            obj = in.readObject(); 
                        System.out.println("objobj "+obj);

        }
                catch(Exception e) {
            //logger.debug("Unable to encrypt view id: "+id, e);
                    e.printStackTrace();
        }finally {
            stream.close();
            in.close();
        }
        return obj;
    }


}

这是错误行--cipher.init(Cipher.DECRYPT_MODE,keySpec,ivSpec);

我还需要添加其他内容吗?感谢。

编辑:谢谢,谢谢你的工作。出于某种原因,我以为我已经在解码数据了。

EDIT2:如果要解码的文本中有+,那么解码后的文本将有空格而不是+。因此,我必须在解密时用+ back替换所有空格。希望这有助于某人。

1 个答案:

答案 0 :(得分:1)

解密过程应该与加密过程相反。

在加密中,您在将URL编码返回给用户之前进行编码。因此,您必须首先在解密过程中进行URL解码。

以下是使用URL解码的完整解密过程:

public Object decryptObject(String base64Data, String base64IV) throws Exception {

        System.out.println("decryptObject " + base64Data);
        System.out.println("decryptObject " + base64IV);

        String urlDecodedData=URLDecoder.decode(base64Data,"UTF-8");
        // Decode the data
        byte[] encryptedData = Base64.decodeBase64(urlDecodedData.getBytes());

        String urlDecodedIV=URLDecoder.decode(base64IV,"UTF-8");
        // Decode the Init Vector
        byte[] rawIV = Base64.decodeBase64(urlDecodedIV.getBytes());
        System.out.println("rawIV " + rawIV.length);

        // Configure the Cipher
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec ivSpec = new IvParameterSpec(rawIV);
        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");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); //////////////////////////////This is the error line

        // Decrypt the data..
        byte[] decrypted = cipher.doFinal(encryptedData);

        // Deserialize the object       
        ByteArrayInputStream stream = new ByteArrayInputStream(decrypted);
        ObjectInput in = new ObjectInputStream(stream);
        Object obj = null;
        try {
            obj = in.readObject();
            System.out.println("objobj " + obj);

        } catch (Exception e) {
            //logger.debug("Unable to encrypt view id: "+id, e);
            e.printStackTrace();
        } finally {
            stream.close();
            in.close();
        }
        return obj;
    }