java - 加密字节后从 Cipher 获取更新的 IV

标签 java cryptography

我正在从事一个需要附加到 AES/CTR 加密文件的项目。现在,由于它是计数器模式,我知道我可以将计数器推进到任何位置并从文件中的位置开始读取。不过,我想知道的是,是否有办法让我获取 Cipher 在使用后可以访问的当前 IV。

Cipher c = Cipher.getInstance("AES/CTR/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(aeskey, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv);

c.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

CipherOutputStream cipher_out = new CipherOutputStream(output, c);

try {
    while (true) {
        cipher_out.write(input.readByte());
    }
} catch (EOFException e) {
}

byte curIV[] = c.getIV();

相反,我发现 curIV 而不是更新后的 IV 与我一开始传入 ivSpec 的 IV 相同。没有办法得到当前的IV吗?

想法是存储:

<AES key><begin IV><current IV>

在非对称加密文件中,这种方式可以解密、读取,我们可以从头开始读取 AES 加密文件,或者我们可以使用 <current IV> 将新数据附加到我们的输出文件中。我们已经存储。

关于如何实现这个的任何其他建议?


根据我发现的文档,Java 使用以下内容(接近 RFC3686 ):

<NONCE><COUNTER>

作为 CTR 的输入,并更新计数器,它被认为是一个大端数。

这是作为 IvParameterSpec 提供的见上图。


除此之外,我想找回的是计数器,无论我们想称它为 IV,还是我们想称它为计数器,还是 nonce + iv + 计数器。


有关 Sun 实现 CTR 的更多信息:http://javamex.ning.com/forum/topics/questions-on-aes-ctr-mode

最佳答案

在使用“SunJCE”提供程序进行试验时,CTR 模式下的 AES 遵循 the proposal published by NIST,其中初始计数器值在每个连续 block 中简单地增加 1。这与 NIST SP 800‑38A, Appendix B.1. 中给出的一般指导一致。 ,当递增的位数 m 是 block 中的位数 b

这违反了 RFC 3686。也就是说,整个计数器都会递增,而不仅仅是 RFC 3686 中指定的有限部分。

您可以通过对 block 进行计数(从零开始)或通过测量密文的长度并用 block 大小进行整数除法来获知 block 索引。如果这些选项看起来太简单,您还可以将最后一个密文 block 与相应的纯文本进行异或,解密该结果,然后减去 IV 以生成 block 索引。

要附加,只需将 IV 设置为原始 IV 加上 block 索引。如果您正在编写可以以部分块结束的流,您将需要做一些额外的工作才能使流进入正确的状态。

int BLOCK_SIZE = 16;
BigInteger MODULUS = BigInteger.ONE.shiftLeft(BLOCK_SIZE * 8);
...
/* Retrieve original IV. */
byte[] iv = ... ;

/* Compute the index of the block to which data will be appended. */
BigInteger block = BigInteger.valueOf(file.length() / BLOCK_SIZE);
/* Add the block to the nonce to find the current counter. */
BigInteger nonce = new BigInteger(1, iv);
byte[] tmp = nonce.add(block).mod(MODULUS).toByteArray();
/* Right-justify the counter value in a block-sized array. */
byte[] ctr = new byte[BLOCK_SIZE];
System.arraycopy(tmp, 0, ctr, BLOCK_SIZE - tmp.length, tmp.length);
/* Use this to initialize the appending cipher. */
IvParameterSpec param = new IvParameterSpec(ctr);

关于java - 加密字节后从 Cipher 获取更新的 IV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7642871/

相关文章:

java - "table * has no column named * "错误,SQLite

java - 如何修复 "More than one file was found with OS independent path ' project.properties'"Android Studio 3.0 Beta-6 中的错误

c# - 如何在 db c# 中存储 X509Certificate2

android - 适用于所有 Android 版本的安全随机数生成

ruby - PBEWithMD5AndDES 在 Ruby 中的实现

node.js - Cardano (ada) 的私钥和签名 key 是什么?

java - 监听SQS队列时org.springframework.core.task.TaskRejectedException?

java - 声明数组增量元素的快速方法 - Java

java - 为 SP 生成 OpenSaml 元数据

java - 如何使用 Maven 部署多项目?