Đúng vậy, nhận thấy tôi chỉ có một huy hiệu Tumbleweed cho điều này, 'yay' ...
tôi đã kết thúc nhìn lên chính xác cách thức IV được cập nhật trong chế độ CTR. Điều này hóa ra làm một +1 đơn giản cho mỗi khối AES mà nó xử lý. Tôi đã thực hiện đọc theo các dòng sau.
Cho một lớp mà thực hiện một read
-like phương pháp mà có thể đọc các byte tiếp theo trong một chuỗi byte được mã hóa và cần phải hỗ trợ tìm kiếm theo thứ tự đó và các biến sau:
BLOCK_SIZE
: cố định tại 16 (128 bit, kích thước khối AES);
cipher
: phiên bản javax.crypto.Cipher
, được khởi tạo để xử lý AES;
delegate
: a java.io.InputStream
bao bọc tài nguyên được mã hóa cho phép truy cập ngẫu nhiên;
input
: a javax.crypto.CipherInputStream
chúng tôi sẽ phân phát lần đọc từ (luồng sẽ xử lý giải mã).
Phương pháp seek
được thực hiện như vậy:
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
}
Lưu ý rằng tìm kiếm tài nguyên đại biểu được bỏ qua ở đây, vì điều này phụ thuộc vào những gì là bên dưới các đại biểu InputStream
. Cũng lưu ý rằng IV ban đầu bắt buộc phải được bắt đầu tại bộ đếm 1 (4 byte cuối cùng).
Unittests cho thấy cách tiếp cận này hoạt động (hiệu suất điểm chuẩn sẽ được thực hiện tại một số điểm trong tương lai :)).
Số lượt truy cập trong CTR phải được khởi tạo thành 0, nếu nó từng cuộn qua có khả năng là cùng một khóa sẽ được sử dụng lại với cùng một 'nonce || Giá trị CTR' là thảm họa cho bảo mật. Bạn nên được rekeying trước khi điều đó xảy ra. –
Bạn nói đúng, tôi đã thay đổi triển khai của mình một chút trong thời gian trung bình để thực sự tuân thủ thông số kỹ thuật (không chắc chắn lý do tại sao tôi không tìm thấy/đi cho điều đó ngay từ đầu ...) – akaIDIOT
Hmm, won ' để tôi chỉnh sửa bình luận nữa. [Một liên kết đến sự tích tụ của IV theo spec] (http://tools.ietf.org/html/rfc3686#section-4). – akaIDIOT