我遇到问题,在这种情况下做工作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的情况下测试加密/解密过程,那么工作正常。
答案 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++;
}
}
}