在Http Request中检索加密值后解密jasypt

时间:2014-12-08 17:05:55

标签: java http url encryption jasypt

我遇到问题,在这种情况下做工作jaspyt:

StrongTextEncryptor textEncryptor = new StrongTextEncryptor();      
textEncryptor.setPassword("myPassword");
String myEncryptedParam = textEncryptor.encrypt("myClearMessage");

myObject.setCallbackUrl("http://myhost/notification?myparam="+myEncryptedParam);

当我收到回调网址并尝试解密请求中使用的相同STRONGTEXTENCRYPTOR网址中提供的参数'myParam'时,它会引发异常:

org.jasypt.exceptions.EncryptionOperationNotPossibleException
at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.decrypt(StandardPBEByteEncryptor.java:1055)
at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.decrypt(StandardPBEStringEncryptor.java:725)
at org.jasypt.util.text.StrongTextEncryptor.decrypt(StrongTextEncryptor.java:118)
at com.softlysoftware.caligraph.util.Util.decryptMessage(Util.java:30)

在我获得的例外中挖掘更多:

BadPaddingException: Given final block not properly padded

如果我在没有httprequest的情况下测试加密/解密过程,那么工作正常。

2 个答案:

答案 0 :(得分:3)

问题是StrongTextEncryptor使用StandardPBEStringEncryptor,后者又使用Base64对密文进行编码。问题是Base64有一个/字符,它不是URL安全的。当您尝试解密时,您使用的参数解析器可能会删除那些使密文不完整的/个字符。

最简单的解决方案可能是使用替换所有内容来更改有问题的字符:

myEncryptedParam.replaceAll("/", "_").replaceAll("\\+", "-");

并在尝试解密之前再次返回:

receivedParam.replaceAll("_", "/").replaceAll("-", "\\+");

这会将编码从普通的Base64编码转换为"URL and Filename safe" Base 64 alphabet

答案 1 :(得分:0)

以Artjom的答案为基础,这是一个Jasypt文本加密器包装器

import org.jasypt.util.text.TextEncryptor;

public class UrlSafeTextEncryptor implements TextEncryptor {

    private TextEncryptor textEncryptor; // thread safe

    public UrlSafeTextEncryptor(TextEncryptor textEncryptor) {
        this.textEncryptor = textEncryptor;
    }

    public String encrypt(String string) {
        String encrypted = textEncryptor.encrypt(string);

        return encrypted.replaceAll("/", "_").replaceAll("\\+", "-");
    }

    public String decrypt(String encrypted) {

        encrypted = encrypted.replaceAll("_", "/").replaceAll("-", "\\+");

        return textEncryptor.decrypt(encrypted);
    }
}

和相应的测试用例

import org.jasypt.util.text.StrongTextEncryptor;
import org.jasypt.util.text.TextEncryptor;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class UrlSafeTextEncryptorTest {

    private String password = "12345678";

    protected TextEncryptor encryptor;
    protected UrlSafeTextEncryptor urlSafeEncryptor;

    @Before
    public void init() {
        StrongTextEncryptor encryptor = new StrongTextEncryptor(); // your implementation here
        encryptor.setPassword(password);

        this.encryptor = encryptor;

        this.urlSafeEncryptor = new UrlSafeTextEncryptor(encryptor);
    }

    @Test
    public void scramble_roundtrip_urlSafe() {

        int i = 0;
        while(true) {
            String key = Integer.toString(i);

            String urlSafeEncrypted = urlSafeEncryptor.encrypt(key);

            Assert.assertFalse(urlSafeEncrypted, urlSafeEncrypted.contains("/"));

            Assert.assertEquals(key, urlSafeEncryptor.decrypt(urlSafeEncrypted));

            if(urlSafeEncrypted.contains("_")) {
                break;
            }

            i++;
        }

    }
}