首页 > 解决方案 > 解密加密文件时获得一堆额外的输出。我的代码中可能有什么问题?

问题描述

我是密码学的新手,这是我编写的填充我的分配者提供的骨架代码的代码(请不要介意结构)。我在这段代码下面描述了问题。

public class FileEncryptor {

    private static final String progName = "FileEncryptor";
    private static final int bufSize = 128;

    public static void main(String[] args) {

        BufferedInputStream in = null;          // A buffered input stream to read from
        BufferedOutputStream out = null;        // And a buffered output stream to write to
        SecretKeyFactory kf = null;             // Something to create a key for us
        KeySpec ks = null;                      // This is how we specify what kind of key we want it to generate
        byte[] salt = new byte[20];             // Some salt for use with PBKDF2, only not very salty
        SecretKey key = null;                   // The key that it generates
        Cipher cipher = null;                   // The cipher that will do the real work
        SecretKeySpec keyspec = null;           // How we pass the key to the Cipher
        int bytesRead = 0;                      // Number of bytes read into the input file buffer

        // First, check the user has provided all the required arguments, and if they haven't, tell them then exit
        if(args.length != 4) {
            printUsageMessage(); System.exit(1);
        }

        // Open the input file
        try {
            in = new BufferedInputStream(new FileInputStream(args[1]));
        } catch (FileNotFoundException e) {
            printErrorMessage("Unable to open input file: " + args[1], null);
            System.exit(1);
        }

        // And then the output file
        try {
            out = new BufferedOutputStream(new FileOutputStream(args[2]));
        } catch (FileNotFoundException e) {
            printErrorMessage("Unable to open output file: " + args[2], e);
            System.exit(1);
        }

        // Create a PBKDF2 secret key factory
        String algorithm = "PBKDF2WithHmacSHA256";
        try {
            kf = SecretKeyFactory.getInstance(algorithm);
        } catch (NoSuchAlgorithmException e) {
            printErrorMessage("Specified algorithm could not be found: " + algorithm , e);
            System.exit(1);
        }

        // Set up a KeySpec for password-based key generation of a 128-bit key
        ks = new PBEKeySpec(args[3].toCharArray(),salt,4096, 128);

        // Now run the passphrase through PBKDF2 to get the key
        try {
            key = kf.generateSecret(ks);
        } catch (InvalidKeySpecException e) {
            printErrorMessage("The key spec provided is invalid: " + keyspec, e);
            System.exit(1);
        }

        // Get the byte encoded key value as a byte array
        byte[] aeskey = key.getEncoded();

        // Now generate a Cipher object for AES encryption in ECBC mode with PKCS #5 padding
        // Use ECB for the first task, then switch to CBC for versions 2 and 3
        try {
            cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        } catch (NoSuchAlgorithmException e) {
            printErrorMessage("No Such Algorithm Exception when creating main cipher", e);
            System.exit(2);
        } catch (NoSuchPaddingException e) {
            printErrorMessage("No Such Padding Exception when creating main cipher",e);
            System.exit(2);
        }

        // Set a variable to indicate whether we're in encrypt or decrypt mode, based upon args[0]
        int cipherMode = -1;
        char mode = Character.toLowerCase(args[0].charAt(0));
        switch (mode) {
            case 'e' : cipherMode = Cipher.ENCRYPT_MODE; break;
            case 'd' : cipherMode = Cipher.DECRYPT_MODE; break;
            default: printUsageMessage(); System.exit(1);
        }

        // Set up a secret key specification, based on the 16-byte (128-bit) AES key array previously generated
        keyspec = new SecretKeySpec(aeskey, "AES");

        // Now initialize the cipher in the right mode, with the keyspec and the ivspec
        try {
            cipher.init(cipherMode, keyspec);
        } catch (InvalidKeyException e) {
            printErrorMessage("Invalid Key Spec",e); System.exit(2);
        }

        // Set up some input and output byte array buffers
        byte[] inputBuffer = new byte[bufSize];
        byte[] outputBuffer = null;

        // "Prime the pump" - we've got to read something before we can encrypt it
        // and not encrypt anything if we read nothing.
        try {
            bytesRead = in.read(inputBuffer);
        } catch (IOException e1) {
            printErrorMessage("Error reading input file " + args[1],e1); System.exit(1);
        }

        // As long as we've read something, loop around encrypting, writing and reading
        // bytesRead will be zero if nothing was read, or -1 on EOF - treat them both the same
        while (bytesRead > 0) {
            byte[] input = inputBuffer;
            // Now encrypt this block
            outputBuffer = cipher.update(input);

            // Write the generated block to file
            try {
                out.write(outputBuffer);
            } catch (IOException e1) {
                printErrorMessage("Error writing to output file " + args[2],e1); System.exit(1);
            }

            // And read in the next block of the file
            try {
                bytesRead = in.read(inputBuffer);
            } catch (IOException e1) {
                printErrorMessage("Error reading input file " + args[1],e1); System.exit(1);
            }
        }

        // Now do the final processing
        try {
            outputBuffer = cipher.doFinal(outputBuffer);
        } catch (IllegalBlockSizeException e2) {
            printErrorMessage("Illegal block size encountered while doing final processing: " + outputBuffer.length , e2);
            System.exit(1);
        } catch (BadPaddingException e2) {
            printErrorMessage("Bad Padding found", e2);
            System.exit(1);
        }

        // Write the final block of output
        try {
            out.write(outputBuffer);
        } catch (IOException e1) {
            printErrorMessage("Error on final write to output file " + args[2],e1); System.exit(1);
        }

        // Close the output files
        try {
            in.close();
            out.close();
        } catch (IOException e1) {
            printErrorMessage("Error closing file", e1);
        }
    }   
}

为方便起见,我省略了printErrorMessage()andprintUsageMessage()方法。

这似乎是问题所在;我得到了一个BadPaddingException,尽管代码捕获了该异常,但我不知道如何处理该异常或如何处理它。我尝试System.exit(1)在最终处理中从我的代码中删除该行,但是输出文件的大小是我的加密文件的两倍,即 256 字节,而不管我的输入文件的大小(大小小于 256 字节)。所以,如果我的输入文件包含:

hello there

我使用key密码对其进行加密,我得到的输出文件包含以下内容:

9`ÃLå7}
syXÀ¢Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`0‹ó‚±G¸Y·IñåsòQœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoÄQé±uTö/ژͤ

现在,当我使用相同的密码解密此文件时,key我得到如下信息:

hello there                                                                                                                     9`Ì巽
syXÀ¢Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`

我怎样才能摆脱这个拖在我解密文本后面的狗屎风暴?所有帮助和建议将不胜感激。谢谢。

标签: javaencryptionaes

解决方案


推荐阅读