aka*_*IOT 10 java encryption aes random-access
由于点亮率模式下的AES非常适合随机访问,因此我假设我使用CipherOutputStreamAES-CTR模式创建了数据源.下面的库 - 不是我的 - 使用RandomAccessFile允许在文件中寻找特定字节偏移的库.
我最初的想法是使用CipherInputStream带有Cipher正确参数的初始化,但是用于此的API不会寻求并声明不支持mark和reset.
我是否错过了可以为我做的这一部分API,我应该查看CTR的IV /块计数器的配置并使用自定义输入流(听起来像是针对self我的霰弹枪)重新创建它采取我错过的其他方法?
是的,注意到我刚拿到一个Tumbleweed徽章,'yay'......
我最终查找了如何在CTR模式下更新IV.事实证明,它为每个处理的AES块做了一个简单的+1.我按照以下几行实施了阅读.
给定一个实现类似read方法的类,该方法将读取加密的字节序列中的下一个字节,并且需要支持在该序列中搜索以及以下变量:
BLOCK_SIZE:固定为16(128位,AES块大小);cipher:javax.crypto.Cipher初始化为处理AES 的实例;delegate:a java.io.InputStream包装允许随机访问的加密资源;input:javax.crypto.CipherInputStream我们将服务读取(流将负责解密).该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
}
Run Code Online (Sandbox Code Playgroud)
请注意,这里省略了寻找委托资源,因为这取决于委托下面的内容InputStream.另请注意,初始IV需要在计数器1(最后4个字节)处启动.
Unittests表明这种方法有效(性能基准测试将在未来的某个时候完成:)).