Android Open Source - conceal Native G C M Cipher Input Stream Test






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  .  j a  v  a2  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;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;

import com.facebook.crypto.cipher.NativeGCMCipher;
import com.facebook.crypto.cipher.NativeGCMCipherException;
import com.facebook.crypto.keychain.KeyChain;
import com.facebook.crypto.util.NativeCryptoLibrary;
import com.facebook.crypto.util.SystemNativeCryptoLibrary;

import android.annotation.TargetApi;
import android.os.Build;
import android.test.InstrumentationTestCase;

import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables;

@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public class NativeGCMCipherInputStreamTest extends InstrumentationTestCase {

  private Crypto mCrypto;
  private NativeCryptoLibrary mNativeCryptoLibrary;
  private byte[] mData;

  private ByteArrayInputStream mCipherInputStream;
  private byte[] mCipheredData;
  private byte[] mIV;
  private byte[] mKey;

  protected void setUp() throws Exception {
    super.setUp();
    mNativeCryptoLibrary = new SystemNativeCryptoLibrary();
    KeyChain keyChain = new FakeKeyChain();
    mCrypto = new Crypto(keyChain, mNativeCryptoLibrary);
    mIV = keyChain.getNewIV();
    mKey = keyChain.getCipherKey();

    // Encrypt some data before each test.
    mData = new byte[CryptoTestUtils.NUM_DATA_BYTES];
    ByteArrayOutputStream cipherOutputStream = new ByteArrayOutputStream();

    OutputStream outputStream = mCrypto.getCipherOutputStream(
        cipherOutputStream,
        new Entity(CryptoTestUtils.ENTITY_NAME));
    outputStream.write(mData);
    outputStream.close();

    mCipheredData = cipherOutputStream.toByteArray();
    mCipherInputStream = new ByteArrayInputStream(mCipheredData);
  }

  public void testDecryptionFailsOnIncorrectEntity() throws Exception {
    InputStream inputStream = null;
    try {
      inputStream = mCrypto.getCipherInputStream(
          mCipherInputStream,
          new Entity(CryptoTestUtils.FAKE_ENTITY_NAME)
      );

      // We expect an exception when all the bytes are read.
      try {
        ByteStreams.toByteArray(inputStream);
      } catch (IOException e) {
        return;
      }
      Closeables.closeQuietly(inputStream);
    } finally {
      Closeables.closeQuietly(inputStream);
    }
    fail(CryptoTestUtils.EXCEPTION_EXPECTED);
  }

  public void testDecryptionFailsOnIncorrectTag() throws Exception {
    byte[] fakeTag = new byte[NativeGCMCipher.TAG_LENGTH];
    Arrays.fill(fakeTag, (byte) CryptoTestUtils.KEY_BYTES);

    // Overwrite the tag bytes.
    System.arraycopy(fakeTag,
        0,
        mCipheredData,
        mCipheredData.length - NativeGCMCipher.TAG_LENGTH,
        NativeGCMCipher.TAG_LENGTH);

    InputStream inputStream = null;
    try {
      inputStream = mCrypto.getCipherInputStream(
          mCipherInputStream,
          new Entity(CryptoTestUtils.ENTITY_NAME)
      );
      ByteStreams.toByteArray(inputStream);
    } catch (IOException e) {
      return;
    } finally {
      Closeables.closeQuietly(inputStream);
    }
    fail(CryptoTestUtils.EXCEPTION_EXPECTED);
  }

  public void testDecryptionFailsOnIncorrectData() throws Exception {
    byte[] fakeData = new byte[CryptoTestUtils.NUM_DATA_BYTES];
    Arrays.fill(fakeData, (byte) CryptoTestUtils.KEY_BYTES);
    byte[] realTag = CryptoSerializerHelper.tag(mCipheredData);
    byte[] tamperedCipherData = CryptoSerializerHelper.createCipheredData(mIV,
        fakeData,
        realTag);

    ByteArrayInputStream fakeCipherInputStream = new ByteArrayInputStream(tamperedCipherData);
    InputStream inputStream = null;
    try {
      inputStream = mCrypto.getCipherInputStream(
          fakeCipherInputStream,
          new Entity(CryptoTestUtils.ENTITY_NAME)
      );

      // We expect an exception after reading all the bytes
      try {
        ByteStreams.toByteArray(inputStream);
      } catch (IOException e) {
        return;
      }
    } finally {
      Closeables.closeQuietly(inputStream);
    }
    fail(CryptoTestUtils.EXCEPTION_EXPECTED);
  }

  public void testDecryptValidData() throws Exception {
    InputStream inputStream = mCrypto.getCipherInputStream(
        mCipherInputStream,
        new Entity(CryptoTestUtils.ENTITY_NAME));
    byte[] decryptedData = ByteStreams.toByteArray(inputStream);
    inputStream.close();
    assertTrue(CryptoTestUtils.DECRYPTED_DATA_IS_DIFFERENT, Arrays.equals(mData, decryptedData));
  }

  public void testDecryptValidDataInSmallIncrements() throws Exception {
    InputStream inputStream = mCrypto.getCipherInputStream(
        mCipherInputStream,
        new Entity(CryptoTestUtils.ENTITY_NAME));

    ByteArrayOutputStream decryptedData = new ByteArrayOutputStream();
    byte[] buffer = new byte[NativeGCMCipher.TAG_LENGTH / 6];
    int read;
    while ((read = inputStream.read(buffer)) != -1) {
      assertTrue(read > 0);
      decryptedData.write(buffer, 0, read);
    }

    inputStream.close();
    assertTrue(CryptoTestUtils.DECRYPTED_DATA_IS_DIFFERENT,
        Arrays.equals(mData, decryptedData.toByteArray()));
  }

  public void testDecryptValidDataReadUsingOffsets() throws Exception {
    byte[] decryptedData = new byte[CryptoTestUtils.NUM_DATA_BYTES];
    InputStream inputStream = mCrypto.getCipherInputStream(
        mCipherInputStream,
        new Entity(CryptoTestUtils.ENTITY_NAME));

    int readSize = decryptedData.length / 2;
    ByteStreams.readFully(inputStream, decryptedData, 0, readSize);
    ByteStreams.readFully(inputStream, decryptedData, readSize, decryptedData.length - readSize);

    // read the remaining bytes.
    ByteStreams.toByteArray(inputStream);
    inputStream.close();
    assertTrue(CryptoTestUtils.DECRYPTED_DATA_IS_DIFFERENT, Arrays.equals(mData, decryptedData));
  }

  public void testThrowsOnCloseWhenAllDataNotRead() throws Exception {
    byte[] decryptedData = new byte[CryptoTestUtils.NUM_DATA_BYTES];
    InputStream inputStream = mCrypto.getCipherInputStream(
        mCipherInputStream,
        new Entity(CryptoTestUtils.ENTITY_NAME));

    int readSize = decryptedData.length / 2;
    ByteStreams.readFully(inputStream, decryptedData, 0, readSize);
    try {
      inputStream.close();
    } catch (NativeGCMCipherException e) {
      return;
    }
    fail(CryptoTestUtils.EXCEPTION_EXPECTED);
  }

  public void testCompatibleWithBouncyCastle() throws Exception {
    Entity entity = new Entity(CryptoTestUtils.ENTITY_NAME);
    byte[] aadData = CryptoSerializerHelper.computeBytesToAuthenticate(entity.getBytes(),
        VersionCodes.CIPHER_SERALIZATION_VERSION,
        VersionCodes.CIPHER_ID);
    BouncyCastleHelper.Result result = BouncyCastleHelper.bouncyCastleEncrypt(mData,
        mKey,
        mIV,
        aadData);

    byte[] cipheredData = CryptoSerializerHelper.createCipheredData(mIV, result.cipherText, result.tag);

    InputStream inputStream = mCrypto.getCipherInputStream(
        new ByteArrayInputStream(cipheredData),
        new Entity(CryptoTestUtils.ENTITY_NAME));
    byte[] decryptedData = ByteStreams.toByteArray(inputStream);
    inputStream.close();
    assertTrue(CryptoTestUtils.DECRYPTED_DATA_IS_DIFFERENT, Arrays.equals(mData, decryptedData));
  }
}




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