Java加密:Java Encription: javax.crypto。当使用padd密码解密时,输入长度必须是8的倍数。

时间:2021-12-04 15:33:51

I have a Java HTTP server which receive messages from a java client.

我有一个Java HTTP服务器,它接收来自Java客户机的消息。

Both server and client use same Encrypter class:

服务器和客户端都使用相同的加密类:

public class Encrypter {

    private Cipher cipher; //The encryption cipher object
public static final String ALGORITHM = "Blowfish"; //Encryption Algorithm

    /**
     * Constructor
     */
    public Encrypter()
    {       
        try {
            initlizeCipher();
        } catch (Throwable e) {     
            ServerSettings.LOG.logError(e);
            e.printStackTrace();

        }
    }

    /**
     * Initialize the Cipher object
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     */
    private void initlizeCipher() throws NoSuchAlgorithmException, NoSuchPaddingException
    {       
        cipher = Cipher.getInstance(ServerSettings.ALGORITHM);
    }

    /**
     * Encrypt a String
     * @param string String to encrypt
     * @return an encrypted String
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     * @throws UnsupportedEncodingException
     */
    public synchronized String encrypt(String string) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException
    {
        cipher.init(Cipher.ENCRYPT_MODE, ServerSettings.SECRECT_KEY_SPEC);
        byte[] stringBytes = string.getBytes("UTF-8");
        byte[] encryptedBytes = cipher.doFinal(stringBytes);
        return Base64.encodeBytes(encryptedBytes);      
    }

    /**
     * Decrypt a String
     * @param string String to decrypt
     * @return a decrypted String
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     * @throws IOException
     */
    public synchronized String decrypt(String string) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, IOException
    {       
        cipher.init(Cipher.DECRYPT_MODE, ServerSettings.SECRECT_KEY_SPEC);
        byte[] decryptedBytes = Base64.decode(string.getBytes());       
        byte[] encryptedBytes = cipher.doFinal(decryptedBytes);
        return new String(encryptedBytes,"UTF-8");
    }   
}

i'm sending message to server through POST method when the variables being sent are: m=encryptedMessage.

当发送的变量为:m=encryptedMessage时,我将通过POST方法向服务器发送消息。

from some reason i always get the

出于某种原因,我总是得到。

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher

and i'm not able to decrypt the message received on the server side..

我无法解密服务器端收到的消息。

i thought at first that maybe the message is broken but it doesn't..

我一开始以为可能是消息坏了,但是没有。

Any Ideas ?

什么好主意吗?

UPDATE1:

UPDATE1:

The weird thing is that some messages to the server are decrypted properly and some return that error. Good message:

奇怪的是,一些对服务器的消息被正确解密,一些消息返回错误。好的消息:

zuhRpmbtH0xSmv6cnBFkAxaGFmRbDP/97LwF4bcDyhANCTLb4afBzFpP3GI1pGFLok03GRQVCwi81Hsp                                             bCpGtuoIVY9cqWYDzNFgOCx5w2sboR2Qx6oxtTSIFIzj1XadQdk9V8lCxcCVVYEH8vA3tph63wU6qJOo                                             OyROz0OJauLBEiWbn5OUQxJ7Yz9Qc1wzl8z7UQb71v4pswF69c1CM/LWWmAzBDCjlRQ5YIB9wN8mBgoC                                             t8Ngt38XkCg/yRHh0EpXYQfrgP6Ls5I8/FY8BQorMy/le5y2

Bad message:

坏消息:

cjj7yzW v3NDtbIJXurrrf318DcY PBk2inzSfz qoIaTKns2tWvR7ftOKK30XY VAlXDrQlyTLatgKA                                             S4IkAIK3lXQKNcwPh87CybHrTqD3HWEM3tqkpVWdB7GNmpHYsITTLrWsBvaMeDcXEr/gr9KYSZ0ks0gR                                             z12jHxPiZoSKHdy5nZ4zShHUy/wlkslmjFvA1G8A15nTVBhjBI GWSh54tyBZF113lL pm5eZNkZrqzo                                             RWI2QAjfqNPzCpV0tqd/pEO70vdSLbCYi7V0bVQNW2KpBv3Hj3VOTCP92k62/iQhIY4F VuMo2UTgGWV                                             1fqoelrl/eelAvsZO8YNC5/2KTKw2sDFaTOwW9R12AgeyzOuhkKQQro2Umd0KoiGnYL9AaQ6 T2MBnLK                                             ZyROHh3cvI T9chPlGfmUHbCN2f3pHoF5rb383KpJNjvlnmnwtaEhQYw8TQjj4PLenK24Hpcs4 wO8gu                                             XSrUglFzLIkkwjvsA5AyTHx/jP9AwMSnWjDwco184YQGAePeM8PYy42oMOaw7Pg/3jWFy1uOzFok2LN9                                             RJWv1iyXejh5s9zXoAT3kywICQygK2YTLZNIS1d5lc0H0f15EN6itZhaR0YnslhYGmH1KcNwdMWhBKsf                                             PytWnK0N8AzUVzt4P4mtmGSuaLi2t54J2pv7m7/c6WjTi1/E16rd3QyWkmXrghSshOJNRRwcydlhhTLH                                             drHTEFaXSPZyVFqlaFu4 f5kxiBa6ewglKHe6zbmRyM15Mq3lRj8Ab/RWBd2tgvaEO/vhw

Both of these message are sent in the same way and are printed to the System.Out for testing. As u can see the bad message have spaces from some reason while the good message doesn't what probably gives the block error message.. any idea how to solve it ?

这两个消息都以相同的方式发送,并被打印到系统中。为测试。当你看到坏消息时,有一些原因,而好的消息不可能给出块错误信息。知道怎么解决吗?

Update 2:

更新2:

After digging into my code I've found out that my problem is inside the function that parse the POST method parameters. I can't say i'm an expert in encoding but there is some problem with passing Base64 encoding throw POST URLEcoding..

在深入挖掘我的代码之后,我发现我的问题在于解析POST方法参数的函数。我不能说我是编码方面的专家,但是通过Base64编码抛出的URLEcoding是有问题的。

This is my parsing code which after getting URLDecode goes to my Encrypter for decrypt:

这是我的解析代码,在得到URLDecode之后进入我的Encrypter进行解密:

private void parseQuery(String query, HashMap parameters) throws UnsupportedEncodingException {

private void parseQuery(字符串查询、HashMap参数)抛出UnsupportedEncodingException

 if (query != null) {
     String pairs[] = query.split("[&]");

     for (String pair : pairs) 
     {
         String param[] = pair.split("[=]");
         String key = null;
         String value = null;
         if (param.length > 0) 
             key = URLDecoder.decode(param[0], "UTF-8");//System.getProperty("file.encoding"));                 

         if (param.length > 1) 
             value = URLDecoder.decode(param[1], "UTF-8");//System.getProperty("file.encoding"));                 

         if (parameters.containsKey(key)) 
         {
             Object obj = parameters.get(key);
             if(obj instanceof List<?>)
             {
                 @SuppressWarnings("unchecked")
                 List<String> values = (List<String>)obj;
                 values.add(value);
             } 
             else if(obj instanceof String) 
             {
                 List<String> values = new ArrayList<String>();
                 values.add((String)obj);
                 values.add(value);
                 parameters.put(key, values);
             }
         } 
         else 
           parameters.put(key, value);                 
     }
 }

}

}

Any Ideas ?

什么好主意吗?

3 个解决方案

#1


1  

I faced the similar problem yesterday. I solved it by encoding the bytes to base64 at client side and decoding it before use at the server side.

我昨天遇到了类似的问题。我通过在客户端将字节编码到base64并在服务器端使用之前对其进行解码,从而解决了这个问题。

Refer to this link - [cipher]: http://www.velocityreviews.com/forums/t645364-java-string-encryption-decryption.html

请参考这个链接- [cipher]: http://www.velocityreviews.com/forums/t645364-java- string-encryption.html。

SO basically this is what you need to do -

基本上这就是你需要做的。

At client side

在客户端

  • Get the byte array from a string
  • 从字符串获取字节数组。
  • Encrypt it.
  • 加密它。
  • Encode the byte array using base64 encoding
  • 使用base64编码对字节数组进行编码。

At server side

在服务器端

  • Decode the base64 encoded data to get a byte array
  • 解码base64编码的数据以获得一个字节数组。
  • Decrypt the byte array.
  • 解密的字节数组。
  • Construct a string using this byte array.
  • 使用这个字节数组构造一个字符串。

#2


1  

Finely after lots of testing and crying :) , I've found what i was suspecting from the beginning.

经过大量的测试和哭泣:),我从一开始就发现了我的怀疑。

When passing data through URL (POST\GET whatever) you must first URL-Encode it first on your client side before sending it, and URL-Decoding on the server side before processing it.

当通过URL传递数据(POST\GET)时,您必须首先在客户端对其进行URL编码,然后将其发送到服务器端,然后在处理它之前在服务器端进行URL解码。

Thanks to Java's great URLEncoder and URLDecoder class you can easily do it:

多亏了Java的伟大的URLEncoder和URLDecoder类,你可以很容易地做到:

//Before sending encode your data for URL - Client side URLEncoder.encode(your_data,charset_name); //charset_name - the recommendation is to use "UTF-8"

//在发送你的数据为URL -客户端URLEncoder.encode(your_data,charset_name)编码之前;//charset_name -推荐使用“UTF-8”

//After receiving the data - decode you data for process - Server side URLDecoder.decode(your_data,charset_name); //charset_name - the recommendation is to use "UTF-8"

//在接收到数据后,将数据解码为process - Server side URLDecoder.decode(your_data,charset_name);//charset_name -推荐使用“UTF-8”

#3


0  

To narrow down the alternatives, place download and unlimited strength JCE policy jar from Oracle/Sun and place it under your JVM. from my experience with java cryptography, 90% of the problems you will face when encrypting come from the fact that the JVM/JDK is ship with a strong but limited strength policy and whenever you try to use and 252k or more algorithms, the JVM start throwing some weird errors.

要缩小选择的范围,可以从Oracle/Sun中下载和限制JCE策略jar,并将其放置在JVM下。从我对java密码学的经验来看,你在加密时所面临的90%的问题都来自于一个事实,即JVM/JDK是一种强大但有限的强度策略,当你尝试使用和252k或更多的算法时,JVM开始抛出一些奇怪的错误。

#1


1  

I faced the similar problem yesterday. I solved it by encoding the bytes to base64 at client side and decoding it before use at the server side.

我昨天遇到了类似的问题。我通过在客户端将字节编码到base64并在服务器端使用之前对其进行解码,从而解决了这个问题。

Refer to this link - [cipher]: http://www.velocityreviews.com/forums/t645364-java-string-encryption-decryption.html

请参考这个链接- [cipher]: http://www.velocityreviews.com/forums/t645364-java- string-encryption.html。

SO basically this is what you need to do -

基本上这就是你需要做的。

At client side

在客户端

  • Get the byte array from a string
  • 从字符串获取字节数组。
  • Encrypt it.
  • 加密它。
  • Encode the byte array using base64 encoding
  • 使用base64编码对字节数组进行编码。

At server side

在服务器端

  • Decode the base64 encoded data to get a byte array
  • 解码base64编码的数据以获得一个字节数组。
  • Decrypt the byte array.
  • 解密的字节数组。
  • Construct a string using this byte array.
  • 使用这个字节数组构造一个字符串。

#2


1  

Finely after lots of testing and crying :) , I've found what i was suspecting from the beginning.

经过大量的测试和哭泣:),我从一开始就发现了我的怀疑。

When passing data through URL (POST\GET whatever) you must first URL-Encode it first on your client side before sending it, and URL-Decoding on the server side before processing it.

当通过URL传递数据(POST\GET)时,您必须首先在客户端对其进行URL编码,然后将其发送到服务器端,然后在处理它之前在服务器端进行URL解码。

Thanks to Java's great URLEncoder and URLDecoder class you can easily do it:

多亏了Java的伟大的URLEncoder和URLDecoder类,你可以很容易地做到:

//Before sending encode your data for URL - Client side URLEncoder.encode(your_data,charset_name); //charset_name - the recommendation is to use "UTF-8"

//在发送你的数据为URL -客户端URLEncoder.encode(your_data,charset_name)编码之前;//charset_name -推荐使用“UTF-8”

//After receiving the data - decode you data for process - Server side URLDecoder.decode(your_data,charset_name); //charset_name - the recommendation is to use "UTF-8"

//在接收到数据后,将数据解码为process - Server side URLDecoder.decode(your_data,charset_name);//charset_name -推荐使用“UTF-8”

#3


0  

To narrow down the alternatives, place download and unlimited strength JCE policy jar from Oracle/Sun and place it under your JVM. from my experience with java cryptography, 90% of the problems you will face when encrypting come from the fact that the JVM/JDK is ship with a strong but limited strength policy and whenever you try to use and 252k or more algorithms, the JVM start throwing some weird errors.

要缩小选择的范围,可以从Oracle/Sun中下载和限制JCE策略jar,并将其放置在JVM下。从我对java密码学的经验来看,你在加密时所面临的90%的问题都来自于一个事实,即JVM/JDK是一种强大但有限的强度策略,当你尝试使用和252k或更多的算法时,JVM开始抛出一些奇怪的错误。