2013-03-11 73 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啓動拋出一些奇怪的錯誤。

相關問題