解密服务器上的文件,检查其哈希和数字签名,然后再次加密并保存在文件服务器上

时间:2015-08-13 08:56:05

标签: java encryption cryptography

我的应用程序要求用户上传经过数字签名的pdf,然后加密该文件。然后将此加密文件上载到服务器上,然后对其进行解密。然后通过匹配文件的散列和数字签名来验证解密的文件。现在使用AES算法对此文件进行加密。加密完成后,文件将存储在文件服务器上。文件大小可达80mb。

我现在面临的挑战是当加密文件存储在机器的本地驱动器上时,文件会立即保存,但是当文件服务器在另一台机器上时,最多需要30分钟来保存单个文件。我无法找出原因。

以下是我正在使用的代码。我已经在tomcat 6和IBM WAS中进行了部署和尝试。传输到文件服务器时,文件传输的时间相同。文件服务器通过SAN网络连接到应用程序服务器。

以下是我的加密代码

strSymAlg = rb.getString("SYM_KEY_ALG"); //SYM_KEY_ALG=AES

                cipher = Cipher.getInstance(strSymAlg);

                SecKey = new SecretKeySpec(hex2Byte(sSymmetricKey), strSymAlg);

                cipher.init(Cipher.DECRYPT_MODE, SecKey);

                baos = recoverFile(new FileInputStream(fileEnv), cipher);

                if (baos != null &&  isRecoveredFileValid((InputStream) new ByteArrayInputStream(baos.toByteArray()))) {

                    fileRecovered = (InputStream) new ByteArrayInputStream(baos.toByteArray());
                }

            }


private ByteArrayOutputStream recoverFile(FileInputStream in, Cipher cipher)  {
        int blockSize = cipher.getBlockSize();
        int outputSize = cipher.getOutputSize(blockSize);
        byte[] inBytes = new byte[blockSize];
        byte[] outBytes = new byte[outputSize];

        int inLength = 0;
        int outLength = 0;
        boolean more = true;

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        try {

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

        } catch (Exception e) {
            System.out.println("recoverFile1: " + e.getMessage());
           // e.printStackTrace();
            baos = null;
        }

        return baos;
    }

我的加密代码是

 String strSymKey = "";

        File fileToCreate = null;

        KeyGenerator keygen = KeyGenerator.getInstance(strSymAlg);
        random = new SecureRandom();
        keygen.init(random);
        SecretKey secKey = keygen.generateKey();


        Key publicKey = getPublicKeyFromString(sPubKey.trim());

        //encrypt Symmetric key with public key
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.WRAP_MODE, publicKey);
        byte[] wrappedKey = cipher.wrap(secKey);

        strSymKey = byte2hex(wrappedKey);



        fileToCreate = new File(strFile);
        if (fileToCreate.exists()) {
            fileToCreate.delete();
        }

        //Encrypt Bidder file with symmetric key
        DataOutputStream out = new DataOutputStream(new FileOutputStream(strFile));
        cipher = Cipher.getInstance(strSymAlg);
        cipher.init(Cipher.ENCRYPT_MODE, secKey);
        crypt(fis, out, cipher);
        fis.close();
        out.close();
    //blnDone=true;

    // System.out.println("STRING SYMMETRIC KEY:"+ strSymKey);

    return strSymKey;




public String byte2hex(byte[] b) {

        // String Buffer can be used instead

        String hs = "";
        String stmp = "";

        for (int n = 0; n < b.length; n++) {
            stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));

            if (stmp.length() == 1) {
                hs = hs + "0" + stmp;
            } else {
                hs = hs + stmp;
            }

            if (n < b.length - 1) {
                hs = hs + "";
            }
        }

        return hs;
    }

添加了新功能

 public void crypt(InputStream in, OutputStream out, Cipher cipher) throws IOException, GeneralSecurityException {
        System.out.println("crypt start time :"+ new Date());
        int blockSize = cipher.getBlockSize();
        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();
        }
        System.out.println("crypt end time :"+ new Date());
        out.write(outBytes);
    }

提前致谢

1 个答案:

答案 0 :(得分:0)

你犯了经典的错误,假设每次读取都填充缓冲区,而另一种读取:它在流的末尾不会这样做。两者都不正确。

while ((count = in.read(buffer)) >= 0)
{
    out.write(cipher.update(buffer, 0, count));
}
out.write(cipher.doFinal());

您不需要DataOutputStream