Skip to content
This repository has been archived by the owner on Nov 7, 2023. It is now read-only.

fix: replace deprecated Masterkeys class with Masterkey.Builder #35

Merged
merged 1 commit into from
Jan 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import groovy.json.JsonSlurper

def DEFAULT_COMPILE_SDK_VERSION = 29
def DEFAULT_BUILD_TOOLS_VERSION = '28.0.3'
def DEFAULT_MIN_SDK_VERSION = 23
def DEFAULT_MIN_SDK_VERSION = 21
def DEFAULT_TARGET_SDK_VERSION = 29

def safeExtGet(prop, fallback) {
Expand Down Expand Up @@ -55,10 +55,15 @@ android {
targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION)
versionCode 41
versionName "3.0.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
abortOnError false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

repositories {
Expand All @@ -80,7 +85,13 @@ dependencies {
//noinspection GradleDynamicVersion
implementation 'com.facebook.react:react-native:+'

implementation "androidx.security:security-crypto:1.1.0-alpha02"
implementation "androidx.security:security-crypto:1.1.0-alpha03"

testImplementation 'junit:junit:4.13.1'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
//noinspection GradleDependency
androidTestImplementation 'org.mockito:mockito-android:3.4.6'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

def configureReactNativePom(def pom) {
Expand Down
2 changes: 1 addition & 1 deletion android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.emeraldsanto.encryptedstorage;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

@RunWith(AndroidJUnit4.class)
public class RNEncryptedStorageModuleUnitTest {
private RNEncryptedStorageModule module;

@Before
public void setUp() {
module = new RNEncryptedStorageModule(new ReactApplicationContext(InstrumentationRegistry.getInstrumentation().getTargetContext()));
module.clear(mock(Promise.class));
}

@Test
public void shouldGetAndSet() {
Promise promise1 = mock(Promise.class);
module.getItem("test", promise1);
verify(promise1).resolve(null);

Promise promise2 = mock(Promise.class);
module.setItem("test", "asd", promise2);
verify(promise2).resolve("asd");

Promise promise3 = mock(Promise.class);
module.getItem("test", promise3);
verify(promise3).resolve("asd");
}

@Test
public void shouldRemove() {
Promise promise1 = mock(Promise.class);
module.setItem("test", "asd", promise1);
verify(promise1).resolve("asd");

Promise promise2 = mock(Promise.class);
module.getItem("test", promise2);
verify(promise2).resolve("asd");

Promise promise3 = mock(Promise.class);
module.removeItem("test", promise3);
verify(promise3).resolve("test");

Promise promise4 = mock(Promise.class);
module.getItem("test", promise4);
verify(promise4).resolve(null);
}

@Test
public void shouldClear() {
Promise promise1 = mock(Promise.class);
module.setItem("test", "asd", promise1);
verify(promise1).resolve("asd");

Promise promise2 = mock(Promise.class);
module.getItem("test", promise2);
verify(promise2).resolve("asd");

Promise promise3 = mock(Promise.class);
module.clear(promise3);
verify(promise3).resolve(null);

Promise promise4 = mock(Promise.class);
module.getItem("test", promise4);
verify(promise4).resolve(null);
}

@Test
public void shouldKeepValuesWhenRecreated() {
Promise promise1 = mock(Promise.class);
module.setItem("test", "asd", promise1);
verify(promise1).resolve("asd");

module = new RNEncryptedStorageModule(new ReactApplicationContext(InstrumentationRegistry.getInstrumentation().getTargetContext()));

Promise promise2 = mock(Promise.class);
module.getItem("test", promise2);
verify(promise2).resolve("asd");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,40 @@

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;

import android.util.Log;
import androidx.security.crypto.EncryptedSharedPreferences;
import androidx.security.crypto.MasterKeys;

import androidx.security.crypto.MasterKey;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

public class RNEncryptedStorageModule extends ReactContextBaseJavaModule {

private static String NATIVE_MODULE_NAME = "RNEncryptedStorage";
private static String SHARED_PREFERENCES_FILENAME = "RN_ENCRYPTED_STORAGE_SHARED_PREF";
private static final String NATIVE_MODULE_NAME = "RNEncryptedStorage";
private static final String SHARED_PREFERENCES_FILENAME = "RN_ENCRYPTED_STORAGE_SHARED_PREF";

private SharedPreferences sharedPreferences;

public RNEncryptedStorageModule(ReactApplicationContext context) {
super(context);

try {
MasterKey key = new MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();

this.sharedPreferences = EncryptedSharedPreferences.create(
RNEncryptedStorageModule.SHARED_PREFERENCES_FILENAME,
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
context,
RNEncryptedStorageModule.SHARED_PREFERENCES_FILENAME,
key,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
}

catch (Exception ex) {
Log.e(NATIVE_MODULE_NAME, "Failed to create encrypted shared preferences! Failing back to standard SharedPreferences", ex);
this.sharedPreferences = context.getSharedPreferences(RNEncryptedStorageModule.SHARED_PREFERENCES_FILENAME, Context.MODE_PRIVATE);
}
}
Expand Down