package com.marshalchen.common.uimodule.utils;
import android.content.Context;
import com.facebook.crypto.Crypto;
import com.facebook.crypto.Entity;
import com.facebook.crypto.cipher.NativeGCMCipher;
import com.facebook.crypto.keychain.KeyChain;
import com.facebook.crypto.keychain.SharedPrefsBackedKeyChain;
import com.facebook.crypto.mac.NativeMac;
import com.facebook.crypto.util.SystemNativeCryptoLibrary;
import com.marshalchen.common.commonUtils.fileUtils.FileUtils;
import com.marshalchen.common.commonUtils.logUtils.Logs;
import java.io.*;
import java.util.Arrays;
/**
* Created by cym on 14-7-22.
*/
public class CryptoUtils {
/**
* could be replace by new SharedPrefsBackedKeyChain(context)
*/
static KeyChain keyChain = new FakeKeyChain();
public static void encryptingContent(Context context, File file, byte[] plainTextBytes) throws Exception {
// Creates a new Crypto object with default implementations of
// a key chain as well as native library.
Crypto crypto = new Crypto(
new SharedPrefsBackedKeyChain(context),
new SystemNativeCryptoLibrary());
// Check for whether the crypto functionality is available
// This might fail if android does not load libaries correctly.
if (!crypto.isAvailable()) {
return;
}
OutputStream fileStream = new BufferedOutputStream(
new FileOutputStream(file));
// Creates an output stream which encrypts the data as
// it is written to it and writes it out to the file.
OutputStream outputStream = crypto.getCipherOutputStream(
fileStream,
new Entity("TEST1"));
// Write plaintext to it.
outputStream.write(plainTextBytes);
outputStream.close();
}
public static void decryptingContent(Context context, File file, String newPath) throws Exception {
// Get the file to which ciphertext has been written.
FileInputStream fileStream = new FileInputStream(file);
Crypto crypto = new Crypto(
new SharedPrefsBackedKeyChain(context),
new SystemNativeCryptoLibrary());
// Creates an input stream which decrypts the data as
// it is read from it.
InputStream inputStream = crypto.getCipherInputStream(
fileStream,
new Entity("TEST1"));
// Read into a byte array.
int read;
byte[] buffer = new byte[1024];
// You must read the entire stream to completion.
// The verification is done at the end of the stream.
// Thus not reading till the end of the stream will cause
// a security bug.
FileOutputStream fs = new FileOutputStream(newPath);
while ((read = inputStream.read(buffer)) != -1) {
fs.write(buffer, 0, read);
}
inputStream.close();
}
public static void testCrypto(Context context) {
try {
CryptoUtils.encryptingContent(context,
new File(FileUtils.getCurrentDataPath(context, "test") + "/aaab"), "hehe1".getBytes());
CryptoUtils.decryptingContent(context, new File(FileUtils.getCurrentDataPath(context, "test") + "/aaab"), FileUtils.getCurrentDataPath(context, "test") + "/aaabc");
} catch (Exception e) {
e.printStackTrace();
Logs.e(e, "");
}
}
}
class FakeKeyChain implements KeyChain {
private final byte[] mKey = new byte[NativeGCMCipher.KEY_LENGTH];
private final byte[] mIV = new byte[NativeGCMCipher.IV_LENGTH];
private final byte[] mMacKey = new byte[NativeMac.KEY_LENGTH];
public static final int NUM_DATA_BYTES = 2752;
public static final int KEY_BYTES = 42;
public static final int MAC_KEY_BYTES = 44;
public static final int IV_BYTES = 43;
public static final String ENTITY_NAME = "TEST";
public static final String FAKE_ENTITY_NAME = "FAKE";
public FakeKeyChain() {
Arrays.fill(mKey, (byte) KEY_BYTES);
Arrays.fill(mIV, (byte) IV_BYTES);
Arrays.fill(mMacKey, (byte) MAC_KEY_BYTES);
}
@Override
public byte[] getCipherKey() {
return mKey;
}
@Override
public byte[] getMacKey() {
return mMacKey;
}
@Override
public byte[] getNewIV() {
return mIV;
}
@Override
public void destroyKeys() {
}
}