在加密字节后从Cipher获取更新的IV [英] Get updated IV from Cipher after encrypting bytes

查看:141
本文介绍了在加密字节后从Cipher获取更新的IV的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个需要附加到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具有相同的IV,我传递到ivSpec开始。是否无法获取当前的IV?



这个想法是存储:

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

这种方式可以解密,读取,我们可以开始阅读AES加密文件,或者我们可以使用我们存储的< current IV> 将新数据附加到我们的输出文件。



有关如何实现此操作的任何其他建议?






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

 < NONCE>< COUNTER> 

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



这是作为上面的 IvParameterSpec 提供的。






除了这一点,我想要得到的是计数器,是否要调用IV,或者如果我们想把它称为计数器, nonce + iv + counter。






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

在尝试使用SunJCE提供程序时,AES在CTR模式下遵循 NIST发布的提案,其中初始计数器值简单地每个连续块递增1。这与 NIST SP  800-38A , m 是块中的位数, b



这与RFC 3686相反。也就是说,整个计数器递增,而不只是RFC 3686中规定的有限部分。



您可以通过计算块(从零开始)知道块索引, ,或通过测量密文的长度并按块大小执行整数除法。如果这些选项看起来太容易了,你还可以将最后一个密码文本块与相应的纯文本进行XOR,解密这个结果,然后减去IV以产生块索引。



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

  int BLOCK_SIZE = 16; 
BigInteger MODULUS = BigInteger.ONE.shiftLeft(BLOCK_SIZE * 8);
...
/ *检索原始IV。 * /
byte [] iv = ...;

/ *计算要附加数据的块的索引。 * /
BigInteger block = BigInteger.valueOf(file.length()/ BLOCK_SIZE);
/ *将块添加到随机数以找到当前计数器。 * /
BigInteger nonce = new BigInteger(1,iv);
byte [] tmp = nonce.add(block).mod(MODULUS).toByteArray();
/ *右对齐块大小数组中的计数器值。 * /
byte [] ctr =新字节[BLOCK_SIZE];
System.arraycopy(tmp,0,ctr,BLOCK_SIZE - tmp.length,tmp.length);
/ *使用此来初始化追加密码。 * /
IvParameterSpec param = new IvParameterSpec(ctr);


I am working on a project that requires appending to a AES/CTR encrypted file. Now, since it is counter mode I know that I can advance the counter to any location and start reading at the location in the file. What I am wondering though is if there is a way for me to fetch the current IV that Cipher has access to after it has been used.

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();

Instead I am finding that curIV rather than having the updated IV has the same IV that I passed into the ivSpec to begin with. Is there no way to get the current IV?

The idea is to store:

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

in a asymmetricly encrypted file, this way that can be decrypted, read and we can start reading the AES encrypted file from the beginning or we can append new data to our output file using the <current IV> that we have stored.

Any other suggestions on how to implement this?


Java according to documentation I have found uses the following (close to RFC3686):

<NONCE><COUNTER>

As its input into the CTR, and to update the counter it is considered to be a big endian number.

This is provided as the IvParameterSpec seen above.


Besides the point, what I am trying to get back is the counter, whether we want to call that the IV, or if we want to call it the counter, or the nonce + iv + counter.


More information about Suns implementation of CTR: http://javamex.ning.com/forum/topics/questions-on-aes-ctr-mode

解决方案

In experimenting with the "SunJCE" provider, AES in CTR-mode follows the proposal published by NIST, where an initial counter value is simply incremented by one with each successive block. This is consistent with the general guidance given in NIST SP 800‑38A, Appendix B.1., when the number of incremented bits, m, is the number of bits in the block, b.

This is contrary to RFC 3686. That is, the entire counter is incremented, not just a limited portion as specified in RFC 3686.

You can know the block index by counting blocks (starting with zero), or by measuring the length of the cipher text and performing integer division by the block size. If those options seem too easy, you can also XOR the last block of cipher text with the corresponding plain text, decrypt that result, and subtract the IV to yield the block index.

To append, simply set the IV to the original IV plus the block index. If you are writing streams that can end with a partial block, you'll have some extra work to do to get the stream into the correct state.

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);

这篇关于在加密字节后从Cipher获取更新的IV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆