/* * Copyright (c) 2014, Facebook, Inc. * 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.android.crypto.keychain; import java.util.Arrays; import android.content.Context; import android.content.SharedPreferences; import com.facebook.crypto.exception.KeyChainException; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import static junit.framework.Assert.*; @RunWith(RobolectricTestRunner.class) @Config(manifest = "javatests/com/facebook/crypto/TestAndroidManifest.xml") public class SharedPrefsBackedKeyChainTest { private SharedPreferences mSharedPreferences; private Context mContext; @Before public void setUp() { mContext = Robolectric.application.getApplicationContext(); mSharedPreferences = Robolectric.application.getSharedPreferences( SharedPrefsBackedKeyChain.SHARED_PREF_NAME, Context.MODE_PRIVATE); } @Test public void testKeyGeneratedOnFirstUse() throws KeyChainException { SharedPrefsBackedKeyChain keyChain = new SharedPrefsBackedKeyChain(mContext); byte[] cipherKey = keyChain.getCipherKey(); assertNotNull(cipherKey); byte[] prefCipherKey = keyChain.decodeFromPrefs( mSharedPreferences.getString(SharedPrefsBackedKeyChain.CIPHER_KEY_PREF, null)); assertTrue(Arrays.equals(prefCipherKey, cipherKey)); byte[] macKey = keyChain.getMacKey(); assertNotNull(cipherKey); byte[] prefMacKey = keyChain.decodeFromPrefs( mSharedPreferences.getString(SharedPrefsBackedKeyChain.MAC_KEY_PREF, null)); assertTrue(Arrays.equals(prefMacKey, macKey)); } @Test public void testSubsequentInvocationsGenerateSameKey() throws KeyChainException { SharedPrefsBackedKeyChain keyChain = new SharedPrefsBackedKeyChain(mContext); byte[] cipherKey = keyChain.getCipherKey(); byte[] cipherKey2 = keyChain.getCipherKey(); assertTrue(Arrays.equals(cipherKey, cipherKey2)); byte[] macKey = keyChain.getMacKey(); byte[] macKey2 = keyChain.getMacKey(); assertTrue(Arrays.equals(macKey, macKey2)); } @Test public void testDestroyCleansKeys() throws KeyChainException { VerifiableSharedPrefsBackedKeyChain keyChain = new VerifiableSharedPrefsBackedKeyChain(mContext); keyChain.getCipherKey(); keyChain.getMacKey(); keyChain.destroyKeys(); assertFalse(keyChain.isCipherKeySet()); assertFalse(keyChain.isMacKeySet()); assertFalse(mSharedPreferences.contains(SharedPrefsBackedKeyChain.CIPHER_KEY_PREF)); assertFalse(mSharedPreferences.contains(SharedPrefsBackedKeyChain.MAC_KEY_PREF)); } @Test public void testNewKeyGeneratedAfterDestroy() throws KeyChainException { SharedPrefsBackedKeyChain keyChain = new SharedPrefsBackedKeyChain(mContext); byte[] cipherKey = keyChain.getCipherKey(); byte[] macKey = keyChain.getMacKey(); keyChain.destroyKeys(); byte[] cipherKey2 = keyChain.getCipherKey(); byte[] macKey2 = keyChain.getMacKey(); assertNotNull(cipherKey); assertNotNull(cipherKey2); assertNotNull(macKey); assertNotNull(macKey2); assertFalse(Arrays.equals(cipherKey, cipherKey2)); assertFalse(Arrays.equals(macKey, macKey2)); } @Test public void testDifferentKeysGeneratedForMacAndCipher() throws KeyChainException { SharedPrefsBackedKeyChain keyChain = new SharedPrefsBackedKeyChain(mContext); byte[] cipherKey = keyChain.getCipherKey(); byte[] macKey = keyChain.getMacKey(); assertFalse(Arrays.equals(cipherKey, macKey)); } private class VerifiableSharedPrefsBackedKeyChain extends SharedPrefsBackedKeyChain { public VerifiableSharedPrefsBackedKeyChain(Context context) { super(context); } public boolean isMacKeySet() { return mSetMacKey && mMacKey != null; } public boolean isCipherKeySet() { return mSetCipherKey && mCipherKey != null; } } }