2013-03-11 394 views
1

我有一个从HTTP客户端接收消息的Java HTTP服务器。Java加密:Java Encription:javax.crypto.IllegalBlockSizeException:使用填充密码进行解密时,输入长度必须是8的倍数

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

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

我正在通过POST方法发送消息给服务器发送的变量的时候是:m=encryptedMessage.

从某种原因,我总是得到

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

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

我以为最初可能是信息被破坏,但它不..

任何想法?

UPDATE1:

奇怪的是,一些消息发送到服务器正确解密和一些返回该错误。 好消息:

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去我的加密器用于解密:

私人无效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);     
    } 
} 

}

什么想法?

+0

什么是'ServerSettings.ALGORITHM'?将它的实际值添加到您的问题。尽管如此,看起来你正在使用分组密码而不是流密码。 – Perception 2013-03-11 19:18:49

+1

算法是Blowfish – 2013-03-11 19:31:11

+0

你可以包含完整的算法字符串吗?基本上转储'ServerSettings.ALGORITHM'的值并将其包含在您的问题中。 – Perception 2013-03-11 19:40:11

回答

1

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

当通过URL传递数据(POST \得到什么),您必须首先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”

1

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

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

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

在客户端

  • 从字符串获取字节数组
  • 加密它。
  • 编码使用Base64字节数组编码

在服务器侧

  • 解码编码数据以base64得到一个字节数组
  • 解密字节数组。
  • 使用此字节数组构造字符串。
+2

感谢您的详细解答,但您是否阅读过我的代码?这正是我所做的。 – 2013-03-12 06:07:18

0

要缩小的替代品,从甲骨文/ Sun的地方下载和无限强度JCE策略罐子并将其放置你的JVM下。从我使用java加密技术的经验来看,加密时遇到的问题中有90%来自于JVM/JDK具有强大但有限的强度策略,并且每当您尝试使用252k或更多算法时,JVM启动抛出一些奇怪的错误。

相关问题