1

我有一个从 Java 客户端接收消息的 Java HTTP 服务器。

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

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

当发送的变量是:m=encryptedMessage.

由于某种原因,我总是得到

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

而且我无法解密在服务器端收到的消息..

起初我以为消息可能已损坏,但事实并非如此..

有任何想法吗 ?

更新1:

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

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

坏消息:

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

这两条消息都以相同的方式发送并打印到 System.Out 进行测试。正如您所见,由于某种原因,坏消息有空格,而好消息却没有可能给出块错误消息。知道如何解决它吗?

更新 2:

在深入研究我的代码后,我发现我的问题出在解析 POST 方法参数的函数内部。我不能说我是编码方面的专家,但是通过 Base64 编码抛出 POST URLEcoding 存在一些问题。

这是我的解析代码,在获取 URLDecode 后会转到我的 Encrypter 进行解密:

private void parseQuery(String query, HashMap parameters) throws 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);                 
     }
 }

}

有任何想法吗 ?

4

3 回答 3

1

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

请参阅此链接 - [密码]:http ://www.velocityreviews.com/forums/t645364-java-string-encryption-decryption.html

所以基本上这就是你需要做的 -

在客户端

  • 从字符串中获取字节数组
  • 加密它。
  • 使用 base64 编码对字节数组进行编码

在服务器端

  • 解码base64编码数据得到字节数组
  • 解密字节数组。
  • 使用此字节数组构造一个字符串。
于 2013-03-12T01:01:41.277 回答
1

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

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

感谢 Java 强大的URLEncoderURLDecoder类,您可以轻松地做到这一点:

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

//接收数据后 - 为进程解码你的数据 - 服务器端 URLDecoder.decode(your_data,charset_name); //charset_name - 建议使用“UTF-8”

于 2013-03-12T10:30:15.627 回答
0

要缩小选择范围,请从 Oracle/Sun 下载和无限强度的 JCE 策略 jar,并将其放在您的 JVM 下。根据我在 Java 密码学方面的经验,加密时您将面临的 90% 的问题来自 JVM/JDK 附带一个强大但有限的强度策略,并且每当您尝试使用 252k 或更多算法时,JVM 就会启动抛出一些奇怪的错误。

于 2014-08-03T14:35:40.043 回答