2015-03-03 64 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

相关问题