加密和编码URL参数spring mvc [英] encrypt and encode URL parameters spring mvc

查看:50
本文介绍了加密和编码URL参数spring mvc的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个Spring mvc应用程序,它需要发送带有链接和加密参数的电子邮件.用户将单击链接,我需要在新页面中解密参数.因此,我正在编写一个util类,以对参数进行编码和解码以及加密和解密.

I am writing a Spring mvc app and it needs to send an email with a link and encrypted params. The user will click on the link and I need to decrypt the params in the new page. So I am writing a util class to encrypt and decrypt along with encoding and decoding the parameters.

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

When I run my stand alone java class(using for testing) - I get the following error when the decryption is called(encrypting, encoding, decoding works fine).

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);

This is the error line - cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

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

Do I need to add anything else? Thanks.

编辑:谢谢,感谢您的工作.由于某种原因,我以为我已经在解码数据了.

Thanks, thanks worked. For some reason, I thought I am already decoding the data.

EDIT2 :如果要解码的文本中带有+,则解码后的文本将带有空格而不是+.所以解密时我必须用+替换所有空格.希望这对某人有帮助.

If the text to decode has + in it, then the decoded text will have space instead of +. So I had to replace all the spaces with + back when decrypting. Hopefully this helps someone.

推荐答案

解密过程应与加密过程相反.

The decryption process should be just reverse of encryption process.

在加密中,您正在执行 URL 编码,然后再将其返回给用户.因此,您必须在解密过程中首先进行URL解码.

Here in encryption you are doing URL encoding before returning it to user. So you must do URL decoding first in your decryption process.

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

Here is complete decryption process working with URL decoding:

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;
    }

这篇关于加密和编码URL参数spring mvc的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆