在 Java 中使用 CipherOutputStream

发布于 2024-12-08 04:35:02 字数 2741 浏览 5 评论 0原文

我正在尝试使用 AES 密码来加密一些字节,但它返回一个无提示错误,这意味着我输入类似以下内容:

byte[] raw = new String("Test","UTF8").getBytes("UTF8");

并且它不会返回任何内容。我认为问题出在 ByteArrayInput/OutputStreams 但我不知道如何以其他方式做到这一点。

这是有问题的代码。

public byte[] encrypt(byte[] in) {
    byte[] encrypted = null;
    try {
        aesCipher.getInstance("AES/CBC/PKCS5Padding");
        aesCipher.init(Cipher.ENCRYPT_MODE, aeskeySpec);
        ByteArrayInputStream bais = new ByteArrayInputStream(in);
        ByteArrayOutputStream baos = new ByteArrayOutputStream(bais.available());
        CipherOutputStream os = new CipherOutputStream(baos, aesCipher);
        copy(bais, os);
        os.flush();
        byte[] raw = baos.toByteArray();
        os.close();
        encrypted = Base64.encodeBase64(raw);

    } catch (FileNotFoundException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InvalidKeyException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchPaddingException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    }
    return encrypted;
}

这是同一个类中另一个有效的函数:

public void encrypt(File in, File out) {


    try {
        aesCipher.getInstance("AES/CBC/PKCS5Padding");
        aesCipher.init(Cipher.ENCRYPT_MODE, aeskeySpec);
        FileInputStream is;
        is = new FileInputStream(in);
        CipherOutputStream os = new CipherOutputStream(new FileOutputStream(out), aesCipher);
        copy(is, os);
        os.close();
    } catch (FileNotFoundException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InvalidKeyException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchPaddingException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    }

}

private void copy(InputStream is, OutputStream os) throws IOException {
    int i;
    byte[] b = new byte[2048];
    while ((i = is.read(b)) != -1) {
        os.write(b, 0, i);
    }
}

I'm trying to use an AES cipher to encrypt some bytes but it's returning a silent error, meaning I enter something like:

byte[] raw = new String("Test","UTF8").getBytes("UTF8");

and it won't return anything. I think the problem is the ByteArrayInput/OutputStreams but I don't know how to do it any other way..

Here's the code in question.

public byte[] encrypt(byte[] in) {
    byte[] encrypted = null;
    try {
        aesCipher.getInstance("AES/CBC/PKCS5Padding");
        aesCipher.init(Cipher.ENCRYPT_MODE, aeskeySpec);
        ByteArrayInputStream bais = new ByteArrayInputStream(in);
        ByteArrayOutputStream baos = new ByteArrayOutputStream(bais.available());
        CipherOutputStream os = new CipherOutputStream(baos, aesCipher);
        copy(bais, os);
        os.flush();
        byte[] raw = baos.toByteArray();
        os.close();
        encrypted = Base64.encodeBase64(raw);

    } catch (FileNotFoundException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InvalidKeyException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchPaddingException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    }
    return encrypted;
}

Here's another function in the same class that does work:

public void encrypt(File in, File out) {


    try {
        aesCipher.getInstance("AES/CBC/PKCS5Padding");
        aesCipher.init(Cipher.ENCRYPT_MODE, aeskeySpec);
        FileInputStream is;
        is = new FileInputStream(in);
        CipherOutputStream os = new CipherOutputStream(new FileOutputStream(out), aesCipher);
        copy(is, os);
        os.close();
    } catch (FileNotFoundException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InvalidKeyException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchPaddingException ex) {
        Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
    }

}

private void copy(InputStream is, OutputStream os) throws IOException {
    int i;
    byte[] b = new byte[2048];
    while ((i = is.read(b)) != -1) {
        os.write(b, 0, i);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

护你周全 2024-12-15 04:35:02

首先引起我注意的是这一行:

aesCipher.getInstance("AES/CBC/PKCS5Padding");

假设 aesCipher 是 Cipher 类型的变量,您在此处调用静态 Cipher.getInstance 并丢弃结果(不将其分配给任何多变的)。即这行根本没有任何效果,aesCipher 与此行之前相同。

如果之前是 null,那么它仍然是 null,并且下一行(调用非静态方法)将为您提供 NullPointerException。如果您的代码默默地吞噬未知异常(这可能超出了显示的代码),那么这是一个普遍问题。

除此之外,我认为 CipherOutputStream 上的刷新并不会真正刷新整个缓冲区,而只是刷新可以写入的块而无需添加任何填充。此处使用 close() 而不是 flush() (这似乎也适用于第二个示例)。


一般性评论:小型独立完整的可编译示例将使我能够尝试并给你一个明确的答案,而不是仅仅猜测。例如,“不返回任何内容”并不是对方法行为的良好描述 - 该方法是否返回 null、空数组、抛出异常、永远阻塞?

The first thing that catches my eye is this line:

aesCipher.getInstance("AES/CBC/PKCS5Padding");

Assuming aesCipher is a variable of type Cipher, you are calling here the static Cipher.getInstance and throwing away the result (not assigning it to any variable). I.e. this line has no effect at all, aesCipher is the same as before this line.

If it was null before, then it still is null, and the next line (which calls a non-static method) will give you a NullPointerException. If your code is silently gobbling unknown exceptions (this might be outside the code shown), this is a general problem.

Other than this, I suppose that the flush on the CipherOutputStream does not really flush the whole buffer, but only as many blocks that can be written without adding any padding. Use close() instead of flush() here (which also seems to work in the second example).


A general remark: A small self-contained complete compilable example would have enabled me to try it and give you a definite answer, instead of only guessing. For example, "does not return anything" is not a good description for the behavior of your method - does the method return null, an empty array, throw an exception, block eternally?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文