public CryptoFSDataInputStream(FSDataInputStream in, CryptoCodec codec, byte[] key, byte[] iv) throws IOException { super(new CryptoInputStream(in, codec, key, iv)); } }
checkStream(); if (isByteBufferReadable || isReadableByteChannel) { final int unread = outBuffer.remaining(); if (n > 0) { decrypt(buf, n, pos); int n = 0; if (buf.hasArray()) { n = read(buf.array(), buf.position(), buf.remaining()); if (n > 0) { buf.position(buf.position() + n); n = read(tmp); if (n > 0) { buf.put(tmp, 0, n);
ByteBuffer inBuffer = getBuffer(); ByteBuffer outBuffer = getBuffer(); Decryptor decryptor = null; try { decryptor = getDecryptor(); byte[] iv = initIV.clone(); updateDecryptor(decryptor, position, iv); byte padding = getPadding(position); inBuffer.put(buffer, offset + n, toDecrypt); decrypt(decryptor, inBuffer, outBuffer, padding); padding = afterDecryption(decryptor, inBuffer, position + n, iv); returnBuffer(inBuffer); returnBuffer(outBuffer); returnDecryptor(decryptor);
@Override public void unbuffer() { cleanBufferPool(); cleanDecryptorPool(); StreamCapabilitiesPolicy.unbuffer(in); }
@Override public boolean seekToNewSource(long targetPos) throws IOException { Preconditions.checkArgument(targetPos >= 0, "Cannot seek to negative offset."); checkStream(); try { boolean result = ((Seekable) in).seekToNewSource(targetPos); resetStreamOffset(targetPos); return result; } catch (ClassCastException e) { throw new UnsupportedOperationException("This stream does not support " + "seekToNewSource."); } }
/** Positioned read fully. It is thread-safe */ @Override public void readFully(long position, byte[] buffer, int offset, int length) throws IOException { checkStream(); try { ((PositionedReadable) in).readFully(position, buffer, offset, length); if (length > 0) { // This operation does not change the current offset of the file decrypt(position, buffer, offset, length); } } catch (ClassCastException e) { throw new UnsupportedOperationException("This stream does not support " + "positioned readFully."); } }
checkStream(); if (b == null) { throw new NullPointerException(); n = readFromUnderlyingStream(inBuffer); ((ReadableByteChannel) in).read(inBuffer); } else { n = readFromUnderlyingStream(inBuffer); decrypt(decryptor, inBuffer, outBuffer, padding); padding = afterDecryption(decryptor, inBuffer, streamOffset, iv); n = Math.min(len, outBuffer.remaining()); outBuffer.get(b, off, n);
@Override public ByteBuffer read(ByteBufferPool bufferPool, int maxLength, EnumSet<ReadOption> opts) throws IOException, UnsupportedOperationException { checkStream(); try { if (outBuffer.remaining() > 0) { // Have some decrypted data unread, need to reset. ((Seekable) in).seek(getPos()); resetStreamOffset(getPos()); } final ByteBuffer buffer = ((HasEnhancedByteBufferAccess) in). read(bufferPool, maxLength, opts); if (buffer != null) { final int n = buffer.remaining(); if (n > 0) { streamOffset += buffer.remaining(); // Read n bytes final int pos = buffer.position(); decrypt(buffer, n, pos); } } return buffer; } catch (ClassCastException e) { throw new UnsupportedOperationException("This stream does not support " + "enhanced byte buffer access."); } }
decryptedDataBuffer.reset(encryptedDataBuffer.getData(), 0, encryptedDataBuffer.getLength()); CryptoInputStream in = new CryptoInputStream(decryptedDataBuffer, decCodec, bufferSize, key, iv); DataInputStream dataIn = new DataInputStream(new BufferedInputStream(in)); decryptedDataBuffer.reset(encryptedDataBuffer.getData(), 0, encryptedDataBuffer.getLength()); in = new CryptoInputStream(decryptedDataBuffer, decCodec, bufferSize, key, iv); expected = originalIn.read(); assertEquals("Decrypted stream read by byte does not match", expected, in.read()); } while (expected != -1); decryptedDataBuffer.reset(encryptedDataBuffer.getData(), 0, encryptedDataBuffer.getLength()); in = new CryptoInputStream(new TestCryptoStreams.FakeInputStream( decryptedDataBuffer), decCodec, bufferSize, key, iv); int seekPos = data.getLength() / 3; in.seek(seekPos); expected = originalInput.read(); assertEquals("Decrypted stream read by byte does not match", expected, in.read()); } while (expected != -1);
public CryptoInputStream(InputStream in, CryptoCodec codec, int bufferSize, byte[] key, byte[] iv, long streamOffset) throws IOException { super(in); CryptoStreamUtils.checkCodec(codec); this.bufferSize = CryptoStreamUtils.checkBufferSize(codec, bufferSize); this.codec = codec; this.key = key.clone(); this.initIV = iv.clone(); this.iv = iv.clone(); this.streamOffset = streamOffset; isByteBufferReadable = in instanceof ByteBufferReadable; isReadableByteChannel = in instanceof ReadableByteChannel; inBuffer = ByteBuffer.allocateDirect(this.bufferSize); outBuffer = ByteBuffer.allocateDirect(this.bufferSize); decryptor = getDecryptor(); resetStreamOffset(streamOffset); }
/** * Decrypt all data in buf: total n bytes from given start position. * Output is also buf and same start position. * buf.position() and buf.limit() should be unchanged after decryption. */ private void decrypt(ByteBuffer buf, int n, int start) throws IOException { final int pos = buf.position(); final int limit = buf.limit(); int len = 0; while (len < n) { buf.position(start + len); buf.limit(start + len + Math.min(n - len, inBuffer.remaining())); inBuffer.put(buf); // Do decryption try { decrypt(decryptor, inBuffer, outBuffer, padding); buf.position(start + len); buf.limit(limit); len += outBuffer.remaining(); buf.put(outBuffer); } finally { padding = afterDecryption(decryptor, inBuffer, streamOffset - (n - len), iv); } } buf.position(pos); }
/** Get underlying stream position. */ @Override public long getPos() throws IOException { checkStream(); // Equals: ((Seekable) in).getPos() - outBuffer.remaining() return streamOffset - outBuffer.remaining(); }
@Override public int read() throws IOException { return (read(oneByteBuf, 0, 1) == -1) ? -1 : (oneByteBuf[0] & 0xff); }
@Override public void close() throws IOException { if (closed) { return; } super.close(); freeBuffers(); codec.close(); closed = true; }
/** Forcibly free the direct buffers. */ private void freeBuffers() { CryptoStreamUtils.freeDB(inBuffer); CryptoStreamUtils.freeDB(outBuffer); cleanBufferPool(); }
/** Calculate the counter and iv, update the decryptor. */ private void updateDecryptor(Decryptor decryptor, long position, byte[] iv) throws IOException { final long counter = getCounter(position); codec.calculateIV(initIV, counter, iv); decryptor.init(key, iv); }
checkStream(); if (b == null) { throw new NullPointerException(); n = readFromUnderlyingStream(inBuffer); ((ReadableByteChannel) in).read(inBuffer); } else { n = readFromUnderlyingStream(inBuffer); decrypt(decryptor, inBuffer, outBuffer, padding); padding = afterDecryption(decryptor, inBuffer, streamOffset, iv); n = Math.min(len, outBuffer.remaining()); outBuffer.get(b, off, n);
@Override public ByteBuffer read(ByteBufferPool bufferPool, int maxLength, EnumSet<ReadOption> opts) throws IOException, UnsupportedOperationException { checkStream(); try { if (outBuffer.remaining() > 0) { // Have some decrypted data unread, need to reset. ((Seekable) in).seek(getPos()); resetStreamOffset(getPos()); } final ByteBuffer buffer = ((HasEnhancedByteBufferAccess) in). read(bufferPool, maxLength, opts); if (buffer != null) { final int n = buffer.remaining(); if (n > 0) { streamOffset += buffer.remaining(); // Read n bytes final int pos = buffer.position(); decrypt(buffer, n, pos); } } return buffer; } catch (ClassCastException e) { throw new UnsupportedOperationException("This stream does not support " + "enhanced byte buffer access."); } }
/** Positioned read. It is thread-safe */ @Override public int read(long position, byte[] buffer, int offset, int length) throws IOException { checkStream(); try { final int n = ((PositionedReadable) in).read(position, buffer, offset, length); if (n > 0) { // This operation does not change the current offset of the file decrypt(position, buffer, offset, n); } return n; } catch (ClassCastException e) { throw new UnsupportedOperationException("This stream does not support " + "positioned read."); } }
decryptedDataBuffer.reset(encryptedDataBuffer.getData(), 0, encryptedDataBuffer.getLength()); CryptoInputStream in = new CryptoInputStream(decryptedDataBuffer, decCodec, bufferSize, key, iv); DataInputStream dataIn = new DataInputStream(new BufferedInputStream(in)); decryptedDataBuffer.reset(encryptedDataBuffer.getData(), 0, encryptedDataBuffer.getLength()); in = new CryptoInputStream(decryptedDataBuffer, decCodec, bufferSize, key, iv); expected = originalIn.read(); assertEquals("Decrypted stream read by byte does not match", expected, in.read()); } while (expected != -1); decryptedDataBuffer.reset(encryptedDataBuffer.getData(), 0, encryptedDataBuffer.getLength()); in = new CryptoInputStream(new TestCryptoStreams.FakeInputStream( decryptedDataBuffer), decCodec, bufferSize, key, iv); int seekPos = data.getLength() / 3; in.seek(seekPos); expected = originalInput.read(); assertEquals("Decrypted stream read by byte does not match", expected, in.read()); } while (expected != -1);