使用chiper update \ update \ doFinal的Java解密问题

时间:2014-04-21 10:56:23

标签: java encryption

我试图编写一个仅使用密码对象加密\ decrypts文件的函数,即CipherInputStream是不允许的(作业问题)。但经过一段时间的调试后,我无法解决错误的问题。

加密工作尽我所知(使用open-ssl加密并比较我的代码和open-ssl输出的sha1sums,但解密仅适用于前16个字节,然后提供错误的数据,导致结尾处的BadPaddingException。 / p>

代码分为两个函数和一个来自main的调用者:

private static void symetricKeyCriptographyHandler(final int opmode, final Path source,
        final Path destination) {
    try (InputStream in = new BufferedInputStream(Files.newInputStream(source),
            BUFFER_BLOCK_SIZE);

            OutputStream out = new BufferedOutputStream(Files.newOutputStream(destination),
                    BUFFER_BLOCK_SIZE);

            BufferedReader scr = new BufferedReader(new InputStreamReader(System.in,
                    StandardCharsets.UTF_8))) {

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        System.out
        .format("Please provide password as hex-encoded text (16 bytes, i.e. 32 hex-digits):%n> ");
        byte[] key = hexToByte(scr.readLine().trim());
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");

        System.out
        .format("Please provide initialization vector as hex-encoded text (32 hex-digits):%n> ");
        byte[] iv = hexToByte(scr.readLine().trim());
        IvParameterSpec paramSpec = new IvParameterSpec(iv);

        // Writing out key and iv as debugging tools. Checks out as far as I can tell.
        for (byte b : key) {
            System.out.format("%02x", b);
        }
        System.out.println();
        for (byte b : iv) {
            System.out.format("%02x", b);
        }
        System.out.println();

        cipher.init(opmode, keySpec, paramSpec);
        processCryptedData(cipher, in, out);
        System.out.format("%s completed. Generated file %s based on file %s",
                opmode == Cipher.ENCRYPT_MODE ? "Encryption" : "Decription",
                        destination.getFileName(), source.getFileName());

    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
        // Should never happen!!!
        e.printStackTrace();
    } catch (NoSuchFileException ex) {
        System.err.println(ex.getFile() + " does not exist.");
    } catch (AccessDeniedException ex) {
        System.err.println(ex.getFile() + " access is denied.");
    } catch (IOException | InvalidKeyException | InvalidAlgorithmParameterException
            | ShortBufferException | IllegalBlockSizeException | BadPaddingException
            | IllegalArgumentException e) {
        System.err.println(e.getMessage());
    }
}

Helper函数,它使用密码和输入\输出流来完成它的工作:

private static void processCryptedData(final Cipher cipher, final InputStream source,
        final OutputStream destination) throws IOException, ShortBufferException,
        IllegalBlockSizeException, BadPaddingException {

    final int cipherBlockSize = cipher.getBlockSize();
    // BUFFER_BLOCK_SIZE = 4096, chosen arbitrarily.
    // I'm aware it isn't used in the fullest. 
    byte[] buff = new byte[BUFFER_BLOCK_SIZE];
    int r;

    while ((r = source.read(buff, 0, cipherBlockSize)) > 0) {
        r = cipher.update(buff, 0, r, buff);
        destination.write(buff, 0, r);
    }
    destination.write(cipher.doFinal());
}

最后来自main的来电者:

        case "encrypt":
            if (args.length != 3) {
                System.err.println("Invalid number of command line arguments.");
                System.exit(1);
            }
            symetricKeyCriptographyHandler(Cipher.ENCRYPT_MODE, Paths.get(args[1]),
                    Paths.get(args[2]));
            break;
        case "decrypt":
            if (args.length != 3) {
                System.err.println("Invalid number of command line arguments.");
                System.exit(1);
            }
            symetricKeyCriptographyHandler(Cipher.DECRYPT_MODE, Paths.get(args[1]),
                    Paths.get(args[2]));
编辑(感谢@owlstead): 显然使用单独的输入\输出缓冲区可以解决问题,但我很困惑,因为在Cipher文档中注意到.update应该是安全的。 在我测试过的以下代码在processCryptedData:

中工作正常
    byte[] ibuff = new byte[cipher.getOutputSize(BUFFER_BLOCK_SIZE)];
    byte[] obuff = new byte[cipher.getOutputSize(BUFFER_BLOCK_SIZE)];
    int r;
    while ((r = source.read(ibuff, 0, BUFFER_BLOCK_SIZE)) > 0) {
        r = cipher.update(ibuff, 0, r, obuff);
        destination.write(obuff, 0, r);
    }

0 个答案:

没有答案