java - 发送带有密文的 IV

标签 java encryption cryptography aes

我正在 Java 中使用 AES/CTR/NoPadding 使用恒定 key 和随机 IV 来加密我的消息。

我计划将 IV 添加到密文前面,然后对其进行 Base64 编码。

现在有一个问题困扰着我。可以有多个 IV + 密文组合来生成我的原始消息。这不是问题吗?另外,发送 IV 是否安全(即在密文前面/附加)或者我应该遵循一些程序?

我对密码学比较陌生,所以如果这是一个非常简单的问题,请原谅我。我找不到任何令人满意的答案。

编辑:

public static String encrypt(String message) {
    try {
        Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
        byte[] iv = generateRandomIV();
        cipher.init(Cipher.ENCRYPT_MODE, SECRET_KEY, new IvParameterSpec(iv));

        byte[] cipherText = cipher.doFinal(message.getBytes("utf-8"));
        return DatatypeConverter.printBase64Binary(concat(iv, cipherText));
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return null;
}

public static String decrypt(String encryptedMessage) {
    try {
        byte[] bytes = DatatypeConverter.parseBase64Binary(encryptedMessage);
        byte[] iv = getIV(bytes);
        byte[] cipherText = getCipherText(bytes);

        Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, SECRET_KEY, new IvParameterSpec(iv));

        return new String(cipher.doFinal(cipherText));
    } catch (Exception ex) {
        ex.printStackTrace();
        return encryptedMessage;
    }
}

private static byte[] getIV(byte[] bytes) {
    return Arrays.copyOfRange(bytes, 0, 16);
}

private static byte[] getCipherText(byte[] bytes) {
    return Arrays.copyOfRange(bytes, 16, bytes.length);
}

然后

public static void main(String[] args) {
    System.out.println(decrypt("wVroKV1UnL2NXiImS83hLKpLLJKk"));
    System.out.println(decrypt("Q0tWAMZDhqMo0LbtEY7lF9D8Dkor"));
}

这两者都会产生相同的输出——“goody”

最佳答案

There can be multiple IV + Cipher text combinations that can result in my original message. Isn't that a problem?

您使用不同 IV 的原因是您可以使用相同的 key 以不同的密文发送相同的消息两次。

如果它生成相同的密文,对手就会知道发送了相同的消息,从而泄漏有关该消息的信息。因此,IV 的想法是,它生成不同的密文,并且在大多数情况下,这是有益的而不是问题。

是否有问题取决于您的协议(protocol)。请注意,密文长度仍然可能显示有关明文的信息(即“肯定,中士”当然会与“否”的加密不同)。

您需要一个身份验证标记/MAC 值来防止消息发生更改。此外,您可能需要包含消息序列号之类的内容,以确保不会发生重放攻击。

但是,越深入,加密就会变得越复杂。如果您需要安全传输,那么最终使用 TLS 或 SSH(或任何其他适用的传输层安全性)会变得更加容易。

Also, is it safe to send IV as such (i.e. prepend/append to the cipher text) or there is some procedure that I should follow?

前置它(“前置”在许多词典中不是一个词,你也可以使用“前缀”)是处理 IV 的常见方法,是的。 IV 无论如何都可以发送,并且不需要保密。然而,对于 CBC,它必须是随机的,而不是序列号。

关于java - 发送带有密文的 IV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48045751/

相关文章:

c++ - gcrypt 是针对哪个版本的 PKCS#1 规范实现的?

node.js - Node.js 和 WebCrypto 之间的 ECDSA 签名似乎不兼容?

java - 使用 XCA 配置 Tomcat 8.0 的 SSL

java - 根据字符串标识符检查对象字段

java - 采访谜题: How to find all "bad" worker histories?

java - Java中批量插入不自动递增

node.js - 我可以加密一个字符串,以便可以在可计算的时间内破解它吗?

c# - ASP.NET FormsAuthentication - 要解密的数据长度无效

java.lang.ArithmeticException 看不出为什么

python-3.x - 如何使用单字节异或密码破解重复 key 异或挑战