简体   繁体   English

寻找 AES-CTR 加密的输入

[英]Seeking in AES-CTR-encrypted input

As AES in CTR mode is great for random access, lets say I have a data source created with a CipherOutputStream in AES-CTR mode.由于 CTR 模式下的 AES 非常适合随机访问,假设我有一个使用 AES-CTR 模式下的CipherOutputStream创建的数据源。 The library underneath—which is not mine—uses a RandomAccessFile that allows to seek to a specific byte offset in the file.下面的库(不是我的)使用RandomAccessFile允许查找文件中的特定字节偏移量。

My initial thought would be to use a CipherInputStream with a Cipher initialized with the right parameters, but the API for that doesn't do seeking and states to not support mark and reset .我最初的想法是将CipherInputStream与用正确参数初始化的Cipher一起使用,但该 API不进行搜索并声明不支持markreset

Is there a part of the API that I've missed that can do this for me, should I look into the configuration of CTR's IV/block counter and recreate that with a custom input stream (which sounds like shotgun aimed at self to me) or take some other approach I've missed?是否有我错过的 API 的一部分可以为我做到这一点,我是否应该查看 CTR 的 IV/块计数器的配置并使用自定义输入流重新创建它(这听起来像是针对我self霰弹枪)或者采取一些我错过的其他方法?

I ended up looking up exactly how the IV is updated in CTR mode.我最终确切地查找了 IV 在 CTR 模式下的更新方式。 This turns out to do a simple +1 for each AES block it processes.事实证明,这对其处理的每个 AES 块都进行了简单的 +1。 I implemented reading along the following lines.我按照以下几行实现了阅读。

Given a class that implements a read -like method that would read the next byte in a byte sequence that is encrypted and needs to support seeking in that sequence and the following variables:给定一个实现类似read方法的类,该方法将读取加密的字节序列中的下一个字节,并需要支持在该序列中查找和以下变量:

  • BLOCK_SIZE : fixed at 16 (128 bits, AES block size); BLOCK_SIZE :固定为 16(128 位,AES 块大小);
  • cipher : an instance of javax.crypto.Cipher , initialized to deal with AES; cipher : javax.crypto.Cipher一个实例,初始化以处理 AES;
  • delegate : a java.io.InputStream that wraps an encrypted resource that allows random access; delegate :一个java.io.InputStream ,它包装了一个允许随机访问的加密资源;
  • input : a javax.crypto.CipherInputStream we'll be serving reads from (the stream will take care of the decryption). input :一个javax.crypto.CipherInputStream我们将提供读取服务(流将负责解密)。

The seek method is implemented as such: seek方法是这样实现的:

void seek(long pos) {
    // calculate the block number that contains the byte we need to seek to
    long block = pos / BLOCK_SIZE;
    // allocate a 16-byte buffer
    ByteBuffer buffer = ByteBuffer.allocate(BLOCK_SIZE);
    // fill the first 12 bytes with the original IV (the iv minus the actual counter value)
    buffer.put(cipher.getIV(), 0, BLOCK_SIZE - 4);
    // set the counter of the IV to the calculated block index + 1 (counter starts at 1)
    buffer.putInt(block + 1);
    IvParameterSpec iv = new IvParameterSpec(buffer.array());
    // re-init the Cipher instance with the new IV
    cipher.init(Cipher.ENCRYPT_MODE, key, iv);
    // seek the delegate wrapper (like seek() in a RandomAccessFile and 
    // recreate the delegate stream to read from the new location)
    // recreate the input stream we're serving reads from
    input = new CipherInputStream(delegate, cipher);
    // next read will be at the block boundary, need to skip some bytes to arrive at pos
    int toSkip = (int) (pos % BLOCK_SIZE);
    byte[] garbage = new byte[toSkip];
    // read bytes into a garbage array for as long as we need (should be max BLOCK_SIZE
    // bytes
    int skipped = input.read(garbage, 0, toSkip);
    while (skipped < toSkip) {
        skipped += input.read(garbage, 0, toSkip - skipped);
    }

    // at this point, the CipherStream is positioned at pos, next read will serve the 
    // plain byte at pos
}

Note that seeking the delegate resource is omitted here, as this depends on what is underneath the delegate InputStream .请注意,此处省略了寻找委托资源,因为这取决于委托InputStream Also note that the initial IV is required to be started at counter 1 (the last 4 bytes).另请注意,初始 IV 需要从计数器 1(最后 4 个字节)开始。

Unittests show that this approach works (performance benchmarks will be done at some point in the future :)).单元测试表明这种方法有效(性能基准测试将在未来的某个时候完成:))。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM