2015-03-03 68 views
0

嗯,這不是一個新程序,我也沒有對有問題的部分做任何更改。
我的系統管理員剛剛將IBM WebSphere Application Server從8.5.0.1修補到8.5.5.4。
我已經加密了過去的文件數量。但升級完成後,我無法再解密這些文件。
我確定我使用的是相同的方法和密鑰,因爲它們都是在我的程序中硬編碼的。而且我沒有更改任何相關代碼。
javax.crypto.BadPaddingException:給定的最終塊在修補後未正確填充WebSphere

這是錯誤。

javax.crypto.BadPaddingException: Given final block not properly padded 
at com.ibm.crypto.provider.AESCipher.engineDoFinal(Unknown Source) 
at com.ibm.crypto.provider.AESCipher.engineDoFinal(Unknown Source) 
at javax.crypto.Cipher.doFinal(Unknown Source) 
at com.xxx.framework.core.common.util.CipherUtil.crypt(CipherUtil.java:175) 
at com.xxx.framework.core.common.util.CipherUtil.decrypt(CipherUtil.java:102) 
at com.xxx.framework.core.common.util.ZipCipherUtil.decryptUnzip(ZipCipherUtil.java:84) 
at xxx(xxx.java:2894) 
at xxx(xxx.java:748) 
at xxx(xxx.java:727) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37) 
at java.lang.reflect.Method.invoke(Method.java:611) 
at yyy(ActionProxy.java:54) 

我已經刪除了一些部件,因爲有一些敏感的商業信息
這是代碼

CipherUtil.java

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.security.GeneralSecurityException; 
import java.security.Key; 
import java.security.SecureRandom; 

import javax.crypto.Cipher; 
import javax.crypto.KeyGenerator; 
import javax.crypto.SecretKey; 

public class CipherUtil { 
    private static String type = "AES"; 

    private static final String HEXES = "ABCDEF"; 

    public void encrypt(String srcFile, String destFile, String privateKey) throws GeneralSecurityException, IOException { 
     Key key = getKey(privateKey); 
     Cipher cipher = Cipher.getInstance(type + "/ECB/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, key); 

     FileInputStream fis = null; 
     FileOutputStream fos = null; 
     try { 
      fis = new FileInputStream(srcFile); 
      fos = new FileOutputStream(mkdirFiles(destFile)); 

      crypt(fis, fos, cipher); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
      throw e; 
     } catch (IOException e) { 
      e.printStackTrace(); 
      throw e; 
     } finally { 
      if (fis != null) { 
       fis.close(); 
      } 
      if (fos != null) { 
       fos.close(); 
      } 
     } 
    } 

    public void decrypt(String srcFile, String destFile, String privateKey) throws GeneralSecurityException, IOException { 
     Key key = getKey(privateKey); 
     Cipher cipher = Cipher.getInstance(type + "/ECB/PKCS5Padding"); 
     cipher.init(Cipher.DECRYPT_MODE, key); 

     FileInputStream fis = null; 
     FileOutputStream fos = null; 
     try { 
      fis = new FileInputStream(srcFile); 
      fos = new FileOutputStream(mkdirFiles(destFile)); 

      crypt(fis, fos, cipher); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
      throw e; 
     } catch (IOException e) { 
      e.printStackTrace(); 
      throw e; 
     } finally { 
      if (fis != null) { 
       fis.close(); 
      } 
      if (fos != null) { 
       fos.close(); 
      } 
     } 
    } 

    private static Key getKey(String secret) throws GeneralSecurityException { 
     KeyGenerator kgen = KeyGenerator.getInstance(type); 
     kgen.init(128, new SecureRandom(secret.getBytes())); 
     SecretKey secretKey = kgen.generateKey(); 
     return secretKey; 
    } 

    private static void crypt(InputStream in, OutputStream out, Cipher cipher) throws IOException, GeneralSecurityException { 
     int blockSize = cipher.getBlockSize() * 1000; 
     int outputSize = cipher.getOutputSize(blockSize); 

     byte[] inBytes = new byte[blockSize]; 
     byte[] outBytes = new byte[outputSize]; 

     int inLength = 0; 
     boolean more = true; 
     while (more) { 
      inLength = in.read(inBytes); 
      if (inLength == blockSize) { 
       int outLength = cipher.update(inBytes, 0, blockSize, outBytes); 
       out.write(outBytes, 0, outLength); 
      } else { 
       more = false; 
      } 
     } 
     if (inLength > 0) 
      outBytes = cipher.doFinal(inBytes, 0, inLength); 
     else 
      outBytes = cipher.doFinal(); 
     out.write(outBytes); 
    } 

    public String encryptString(String srcString, String keyString) throws GeneralSecurityException { 
     Key key = getKey(keyString); 
     Cipher cipher = Cipher.getInstance(type + "/ECB/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, key); 

     byte[] coded = cipher.doFinal(srcString.getBytes()); 

     return byteArrayToHexString(coded); 
    } 

    public String decryptString(String srcString, String keyString) throws GeneralSecurityException { 
     Key key = getKey(keyString); 
     Cipher cipher = Cipher.getInstance(type + "/ECB/PKCS5Padding"); 
     cipher.init(Cipher.DECRYPT_MODE, key); 

     byte[] decoded = cipher.doFinal(hexStringToByteArray(srcString)); 

     return new String(decoded); 
    } 


    private String byteArrayToHexString(byte[] raw) 
    { 
     if (raw == null) 
     { 
      return null; 
     } 

     final StringBuilder hex = new StringBuilder(2 * raw.length); 

     for (final byte b : raw) 
     { 
      hex.append(HEXES.charAt((b & 0xF0) >> 4)) 
       .append(HEXES.charAt((b & 0x0F))); 
     } 
     return hex.toString(); 
    } 

    public static byte[] hexStringToByteArray(String s) { 
     if (s == null || (s.length() % 2) == 1) 
     { 
      throw new IllegalArgumentException(); 
     } 

     final char[] chars = s.toCharArray(); 
     final int len = chars.length; 
     final byte [] data = new byte [len/2]; 

     for (int i=0; i<len; i+=2) 
     { 
      data[i/2] = (byte) ((Character.digit (chars[i], 16) << 4) + Character.digit (chars[i + 1], 16)); 
     } 
     return data; 
    } 
} 

雖然我已經提到的「文件」,該方法只將文件視爲二進制字符串進行加密。

因爲我有DEV和UAT環境來測試(DEV = 8.5.5.4,UAT = 8.5.0.1),我試圖將DEV上的舊加密文件放到UAT上。他們可以在UAT下解密。
另外我試圖在DEV下加密一個新文件並解密它,這沒關係。

有什麼我需要給我的系統管理員打電話嗎?
我只是一名程序員,在服務器安裝方面我不太熟練。

P.S.如果有什麼需要檢查的話,我可以使用管理權限進入WebSphere管理面板。
P.S.2。這些代碼不是我寫的。不要問我這些編碼的原因是什麼。順便說一下,我檢查了代碼,我找不到這些代碼的任何問題,除了一些安全隱患,但我不確定。

+0

嘗試一些字符:'secret.getBytes(「UTF-8」)'。這包含一些字符集:http://docs.oracle.com/javase/1.5.0/docs/api/java/nio/charset/Charset.html – 2015-03-03 12:24:36

+0

我已經嘗試過,但沒有區別。我今天才發現的新事物是生成的帶有8.5.0.1和8.5.5.4的加密文件的文件無法在相反的環境中解密。那麼我已經在environemnt中重新生成了該文件,檢查了md5sum並發現它們不匹配。看起來二進制數據也有很大的不同。 – 2015-03-04 08:01:23

回答

0

不知道這是你的問題或沒有,但此塊:

while (more) { 
    inLength = in.read(inBytes); 
    if (inLength == blockSize) { 
     int outLength = cipher.update(inBytes, 0, blockSize, outBytes); 
     out.write(outBytes, 0, outLength); 
    } else { 
     more = false; 
    } 
} 

在原則上是不正確最少。 in.read()理論上可以在到達文件結束之前讀取小於塊長度的值。 The EOF condition is that in.read() returns -1.也許操作系統的更新已經導致FileInputStream偶爾中斷讀取?在這種情況下,您將首次陷入代碼的inLength> 0塊,並嘗試解密一個部分塊,這肯定會給出錯誤的結果。

您還可以通過使用NoPadding臨時禁用PKCS5Padding,並查看加密的輸出是什麼。

+0

感謝您的回覆。但似乎這不是問題的當前原因,因爲blockSize總是大於inLength。我也檢查了讀取字節,8.5.0.1和8.5.5.4都是正常的。此外,我試圖用NoPadding替換PKCS5Padding,似乎沒有有效的輸出。 – 2015-03-04 07:51:45

+0

您是否檢查過您已經閱讀完整個文件?潛在地,in.read(inBytes)可以在不讀取整個文件的情況下返回,這就是您將執行包含不完整信息的doFinal的情況。唯一要檢查的其他事情是在DEV和UAT環境中使用例如DatatypeConverter.printHexBinary(inBytes)輸出塊,以確保它們獲得相同的輸入。如果可以的話,也可以爲鑰匙做這個。如果輸入相同並且密鑰相同,並且您獲得不同的輸出,則唯一的可能性是加密庫發生故障。 – 2015-03-04 12:15:52

+0

是的,我檢查它確實讀取了doFinal中的整個文件。我明天會做其他檢查。 – 2015-03-04 16:34:46

相關問題