这是我的困境。我试图从URL参数解密一些值。我的代码在
之下import java.net.URLDecoder;
import java.net.URLEncoder;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class EncTest {
public static String decryptString(String str, String key) throws Exception {
str = URLDecoder.decode(str, "UTF-8");
String result = java.net.URLDecoder.decode(str, "UTF-8");
byte[] keyBytes = key.getBytes("UTF-8");
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "DESede");
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
BASE64Decoder base64decoder = new BASE64Decoder();
byte[] clrtxt = base64decoder.decodeBuffer(result);
byte[] cphtxt = cipher.doFinal(clrtxt);
StringBuffer sBuffer = new StringBuffer();
for (int i = 0; i < cphtxt.length; i++) {
sBuffer.append((char) cphtxt[i]);
}
return sBuffer.toString();
}
public static String encryptString(String str, String key) throws Exception {
byte[] keyBytes = key.getBytes("UTF-8");
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "DESede");
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] clrtxt = str.getBytes("UTF8");
byte[] cphtxt = cipher.doFinal(clrtxt);
BASE64Encoder base64encoder = new BASE64Encoder();
return URLEncoder.encode(base64encoder.encode(cphtxt), "UTF-8");
}
我在其他一些帖子中读到我不应该使用sun.misc.BASE64 *但我不知道如何使用Apache版本。现在,当我解密该值时,问题就出现了。我看到一些时髦的字符:+ T ?? td?我通过加密一些字符串然后解密相同的字符串来运行一些测试,并出现这些奇怪的字符。
我在这里做错了什么?
答案 0 :(得分:1)
编码问题:
decryptString
的输入进行了两次URL解码。一次就够了。new String(byte[],"UTF-8")
来执行此操作。加密问题:
password.getBytes()
,最好使用正确的密钥派生函数,如PBKDF2(在SO上搜索PBKDF2WithHmacSHA1
)。使用CTR密码模式和SHA-1密码哈希的示例:
public static void main( String[] args ) throws Exception {
String password = "a lovely password of any length";
// source file encoding should be UTF-8 to support this literal
String plain = "á pláïn téxt wîth non-ascii characters";
System.out.println( plain );
// proper cipher modes need iv
byte[] ivBytes = new byte[ 8 ];
SecureRandom.getInstance( "SHA1PRNG" ).nextBytes( ivBytes );
String encrypted = encryptString( plain, password, ivBytes );
System.out.println( encrypted );
String decrypted = decryptString( encrypted, password, ivBytes );
System.out.println( decrypted );
}
public static String encryptString( String plainText, String password, byte[] ivBytes ) throws Exception {
MessageDigest sha1 = MessageDigest.getInstance( "SHA1" );
byte[] keyBytes = Arrays.copyOf( sha1.digest( password.getBytes( "UTF-8" ) ), 24 );
SecretKeySpec key = new SecretKeySpec( keyBytes, "DESede" );
IvParameterSpec iv = new IvParameterSpec( ivBytes );
Cipher cipher = Cipher.getInstance( "DESede/CTR/PKCS5Padding" );
cipher.init( Cipher.ENCRYPT_MODE, key, iv );
byte[] plainBytes = plainText.getBytes( "UTF-8" );
byte[] encryptedBytes = cipher.doFinal( plainBytes );
String encryptedBase64 = new BASE64Encoder().encode( encryptedBytes );
String urlEncodedEncryptedBase64 = URLEncoder.encode( encryptedBase64, "UTF-8" );
return urlEncodedEncryptedBase64;
}
public static String decryptString( String urlEncodedEncryptedBase64, String password, byte[] ivBytes ) throws Exception {
MessageDigest sha1 = MessageDigest.getInstance( "SHA1" );
byte[] keyBytes = Arrays.copyOf( sha1.digest( password.getBytes( "UTF-8" ) ), 24 );
SecretKeySpec key = new SecretKeySpec( keyBytes, "DESede" );
IvParameterSpec iv = new IvParameterSpec( ivBytes );
Cipher cipher = Cipher.getInstance( "DESede/CTR/PKCS5Padding" );
cipher.init( Cipher.DECRYPT_MODE, key, iv );
// exact mirror of encryption sequence
String encryptedBase64 = URLDecoder.decode( urlEncodedEncryptedBase64, "UTF-8" );
byte[] encryptedBytes = new BASE64Decoder().decodeBuffer( encryptedBase64 );
byte[] decryptedBytes = cipher.doFinal( encryptedBytes );
String decryptedText = new String( decryptedBytes, "UTF-8" );
return decryptedText;
}