Android Open Source - conceal Tail Input Stream






From Project

Back to project page conceal.

License

The source code is released under:

BSD License For Conceal software Copyright (c) 2014, Facebook, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that...

If you think the Android project conceal listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 *  Copyright (c) 2014, Facebook, Inc./*from  ww w .ja v  a  2 s . c  o m*/
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

package com.facebook.crypto.streams;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * An input stream that always maintains a tail of fixed length.
 */
public class TailInputStream extends FilterInputStream {

  private final byte[] mTail;
  private final int mTailTength;

  private int mCount;
  private boolean mEOF;

  protected TailInputStream(InputStream in, int tailLength) {
    super(in);
    mTail = new byte[tailLength];
    mTailTength = tailLength;
  }

  @Override
  public int read() throws IOException {
    byte[] buffer = new byte[1];
    int read = read(buffer, 0, 1);

    while (read == 0) {
      read = read(buffer, 0, 1);
    }
    if (read == -1) {
      return -1;
    } else {
      return buffer[0] & 0xFF;
    }
  }

  @Override
  public int read(byte[] buffer, int offset, int count) throws IOException {
    if (mEOF) {
      return -1;
    }

    if (count == 0) {
      return 0;
    }

    int read = 0;
    while (read == 0) {
      read = readTail(buffer, offset, count);
    }

    return read;
  }

  /**
   * Tries to read data from the delegate input stream into the buffer while extracting
   * a tail from it.
   */
  private int readTail(byte[] buffer, int offset, int count) throws IOException {
    if (count >= mCount) {
      int remain = count - mCount;
      int readBytes = in.read(buffer, offset + mCount, remain);
      if (readBytes == -1) {
        mEOF = true;
        return -1;
      }

      if (mCount > 0) {
        System.arraycopy(mTail, 0, buffer, offset, mCount);
      }
      int dataInBuffer = mCount + readBytes;

      int tailBytes = in.read(mTail, 0, mTailTength);

      if (tailBytes == -1) {
        mEOF = true;
        tailBytes = 0;
      }
      return extractTail(buffer, dataInBuffer, tailBytes, offset);
    } else {
      // count < mCount
      int newLength = mCount - count;
      System.arraycopy(mTail, 0, buffer, offset, count);
      System.arraycopy(mTail, count, mTail, 0, newLength);

      int tailBytes = in.read(mTail, newLength, mTailTength - newLength);

      if (tailBytes == -1) {
        // reverse the copy.
        System.arraycopy(mTail, 0, mTail, count, newLength);
        System.arraycopy(buffer, offset, mTail, 0, count);
        mEOF = true;
        return -1;
      } else {
        return extractTail(buffer, count, tailBytes + newLength, offset);
      }
    }
  }

  /**
   * Constructs the largest tail we can extract given the state of the buffers by attempting
   * to back-fill the tail buffer with bytes from the readBuffer.
   * @param readBuffer The buffer supplied by the client.
   * @param bytesInBuffer The number of bytes currently in the readBuffer.
   * @param tailBytes The number of bytes currently in the tail buffer.
   * @param bufferOffset The current offset in the readBuffer.
   * @return number of bytes read into the readBuffer.
   */
  private int extractTail(byte[] readBuffer, int bytesInBuffer, int tailBytes, int bufferOffset) {
    int toFill = mTailTength - tailBytes;
    int tailOffsetInBuffer = Math.max(0, bytesInBuffer - toFill) + bufferOffset;
    int bytesToCopy = Math.min(toFill, bytesInBuffer);

    if (bytesToCopy > 0) {
      if (tailBytes > 0) {
        System.arraycopy(mTail, 0, mTail, bytesToCopy, tailBytes);
      }
      System.arraycopy(readBuffer, tailOffsetInBuffer, mTail, 0, bytesToCopy);
    }

    mCount = bytesToCopy + tailBytes;
    return tailOffsetInBuffer - bufferOffset;
  }

  @Override
  public boolean markSupported() {
    return false;
  }

  public byte[] getTail() throws IOException {
    if (mCount != mTailTength) {
      throw new IOException("Not enough tail data");
    }
    return mTail;
  }
}




Java Source Code List

com.facebook.android.crypto.keychain.SecureRandomFix.java
com.facebook.android.crypto.keychain.SharedPrefsBackedKeyChainTest.java
com.facebook.android.crypto.keychain.SharedPrefsBackedKeyChain.java
com.facebook.crypto.BouncyCastleHelper.java
com.facebook.crypto.CipherHelper.java
com.facebook.crypto.CryptoSerializerHelper.java
com.facebook.crypto.CryptoTestUtils.java
com.facebook.crypto.Crypto.java
com.facebook.crypto.Entity.java
com.facebook.crypto.FakeKeyChain.java
com.facebook.crypto.FbInstrumentationTestRunner.java
com.facebook.crypto.NativeGCMCipherInputStreamTest.java
com.facebook.crypto.NativeGCMCipherOutputStreamTest.java
com.facebook.crypto.NativeMacLayeredInputStreamTest.java
com.facebook.crypto.NativeMacLayeredOutputStreamTest.java
com.facebook.crypto.SimpleDecryptTest.java
com.facebook.crypto.SimpleEncryptTest.java
com.facebook.crypto.VersionCodes.java
com.facebook.crypto.benchmarks.BenchmarkNativeCryptoLibrary.java
com.facebook.crypto.benchmarks.CipherReadBenchmark.java
com.facebook.crypto.benchmarks.CipherWriteBenchmark.java
com.facebook.crypto.benchmarks.MacBenchmark.java
com.facebook.crypto.benchmarks.cipher.AESCipher.java
com.facebook.crypto.benchmarks.cipher.BaseCipher.java
com.facebook.crypto.benchmarks.cipher.BouncyCastleCCMCipher.java
com.facebook.crypto.benchmarks.cipher.BouncyCastleGCMCipher.java
com.facebook.crypto.benchmarks.cipher.NativeGCMCipherHelper.java
com.facebook.crypto.benchmarks.mac.BaseMac.java
com.facebook.crypto.benchmarks.mac.HMAC.java
com.facebook.crypto.benchmarks.mac.NativeMacHelper.java
com.facebook.crypto.benchmarks.mac.streams.MacLayeredInputStream.java
com.facebook.crypto.benchmarks.mac.streams.MacLayeredOutputStream.java
com.facebook.crypto.cipher.NativeGCMCipherException.java
com.facebook.crypto.cipher.NativeGCMCipher.java
com.facebook.crypto.exception.CryptoInitializationException.java
com.facebook.crypto.exception.KeyChainException.java
com.facebook.crypto.keychain.KeyChain.java
com.facebook.crypto.mac.NativeMac.java
com.facebook.crypto.streams.BetterCipherInputStreamTest.java
com.facebook.crypto.streams.BetterCipherInputStream.java
com.facebook.crypto.streams.FixedSizeByteArrayOutputStream.java
com.facebook.crypto.streams.NativeGCMCipherInputStream.java
com.facebook.crypto.streams.NativeGCMCipherOutputStream.java
com.facebook.crypto.streams.NativeMacLayeredInputStream.java
com.facebook.crypto.streams.NativeMacLayeredOutputStream.java
com.facebook.crypto.streams.TailBufferHelper.java
com.facebook.crypto.streams.TailInputStreamTest.java
com.facebook.crypto.streams.TailInputStream.java
com.facebook.crypto.util.Assertions.java
com.facebook.crypto.util.NativeCryptoLibrary.java
com.facebook.crypto.util.SystemNativeCryptoLibrary.java
com.facebook.proguard.annotations.DoNotStrip.java
com.facebook.proguard.annotations.InternalBuildOnly.java
com.facebook.proguard.annotations.KeepGettersAndSetters.java