diff --git a/.gitignore b/.gitignore index 475c4ffb..4f38b462 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ jsconfig.json # Xcode # +.cxx/ build/ *.pbxuser !default.pbxuser @@ -28,7 +29,7 @@ DerivedData *.ipa *.xcuserstate project.xcworkspace - +ios/privateKey.m # Android/IJ # .idea @@ -60,6 +61,5 @@ android/keystores/debug.keystore # generated by bob lib/ - **prebuild.log example/ios/tmp.xcconfig diff --git a/README.md b/README.md index ff9621ff..67fed8d2 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ Keep in mind It's [basically impossible to prevent users from reverse engineerin Install the package: ``` -$ yarn add react-native-keys +yarn add react-native-keys ``` Link the library: @@ -123,7 +123,7 @@ Link the library: or later. For earlier versions you need to manually link the module.) ``` -$ react-native link react-native-keys +react-native link react-native-keys ``` if cocoapods are used in the project then pod has to be installed as well: @@ -138,12 +138,12 @@ if cocoapods are used in the project then pod has to be installed as well: - Manual Link (iOS) - 1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]` - 2. Go to `node_modules` ➜ `react-native-keys` and add `Keys.xcodeproj` - 3. Expand the `Keys.xcodeproj` ➜ `Products` folder - 4. In the project navigator, select your project. Add `Keys.a` to your project's `Build Phases` ➜ `Link Binary With Libraries` - 5. And go the Build Settings tab. Make sure All is toggled on (instead of Basic) - 6. Look for Header Search Paths and add `$(SRCROOT)/../node_modules/react-native-keys/ios/**` as `non-recursive` + 1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]` + 2. Go to `node_modules` ➜ `react-native-keys` and add `Keys.xcodeproj` + 3. Expand the `Keys.xcodeproj` ➜ `Products` folder + 4. In the project navigator, select your project. Add `Keys.a` to your project's `Build Phases` ➜ `Link Binary With Libraries` + 5. And go the Build Settings tab. Make sure All is toggled on (instead of Basic) + 6. Look for Header Search Paths and add `$(SRCROOT)/../node_modules/react-native-keys/ios/**` as `non-recursive` - Manual Link (Android) @@ -158,8 +158,8 @@ if cocoapods are used in the project then pod has to be installed as well: ```diff dependencies { - implementation "com.facebook.react:react-native:+" // From node_modules - + implementation project(':react-native-keys') + implementation "com.facebook.react:react-native:+" // From node_modules + + implementation project(':react-native-keys') } ``` @@ -170,9 +170,9 @@ if cocoapods are used in the project then pod has to be installed as well: @Override protected List getPackages() { - return Arrays.asList( - new MainReactPackage() - + new KeysPackage() + return Arrays.asList( + new MainReactPackage() + + new KeysPackage() ); } ``` @@ -189,7 +189,7 @@ you can only read jni key into java file.like this URL url = new URL(BuildConfig.API_URL); // https://example.com ``` -You can also read them from your Gradle configuration: +You can also read them from your Gradle configuration(only public keys): ```groovy defaultConfig { @@ -211,12 +211,24 @@ All variables are strings, so you may need to cast them. For instance, in Gradle versionCode project.keys.get("VERSION_CODE").toInteger() ``` +#### Advanced Android Setup + +In `android/app/build.gradle`, if you use `applicationIdSuffix` or `applicationId` that is different from the package name indicated in `AndroidManifest.xml` in `` tag, for example, to support different build variants: +Add this in `android/app/build.gradle` + +``` +defaultConfig { + ... + resValue "string", "build_config_package", "YOUR_PACKAGE_NAME_IN_ANDROIDMANIFEST_XML_OR_YOUR_NAME_SPACE" +} +``` + #### Secure Keys (JNI) ```java import static com.reactnativekeysjsi.KeysModule.getSecureFor; -String secureValue=getSecureFor("BRANCH_KEY"); // key_test_omQ7YYKiq57vOqEJsdcsdfeEsiWkwxE +String secureValue = getSecureFor("BRANCH_KEY"); // key_test_omQ7YYKiq57vOqEJsdcsdfeEsiWkwxE ``` ### iOS @@ -279,10 +291,19 @@ ios/tmp.xcconfig - Go to _Edit scheme..._ -> _Build_ -> _Pre-actions_, click _+_ and select _New Run Script Action_. Paste below code which will generate KEYS keys on native ios side (into node*modules) Make sure to select your target under \_Provide build settings from*, so `$SRCROOT` environment variables is available to the script. -``` +```sh "${SRCROOT}/../node_modules/react-native-keys/keysIOS.js" ``` +Alternatively, you can define a map in `Pre-actions` associating builds with env files: + +```sh + export KEYSFILE = "path_to_env" + "${SRCROOT}/../node_modules/react-native-keys/keysIOS.js" +``` + + call, and use build cases in lowercase, like: + ### Different environments Save config for different environments in different files: `keys.staging.json`, `keys.production.json`, etc. @@ -292,9 +313,9 @@ By default react-native-keys will read from `keys.development.json`, but you can The simplest approach is to tell it what file to read with an environment variable, like: ``` -$ KEYSFILE=keys.staging.json react-native run-ios # bash -$ SET KEYSFILE=keys.staging.json && react-native run-ios # windows -$ env:KEYSFILE="keys.staging.json"; react-native run-ios # powershell +KEYSFILE=keys.staging.json react-native run-ios # bash +SET KEYSFILE=keys.staging.json && react-native run-ios # windows +env:KEYSFILE="keys.staging.json"; react-native run-ios # powershell ``` This also works for `run-android`. Alternatively, there are platform-specific options below. @@ -303,13 +324,13 @@ This also works for `run-android`. Alternatively, there are platform-specific op The same environment variable can be used to assemble releases with a different config: -``` -$ cd android && KEYSFILE=keys.staging.json ./gradlew assembleRelease +```sh +cd android && KEYSFILE=keys.staging.json ./gradlew assembleRelease ``` Alternatively, you can define a map in `build.gradle` associating builds with env files. Do it before the `apply from` call, and use build cases in lowercase, like: -``` +```groovy project.ext.keyFiles = [ debug: "keys.development.json", release: "keys.staging.json", @@ -323,7 +344,7 @@ apply from: project(':react-native-keys').projectDir.getPath() + "/RNKeys.gradle In `android/app/build.gradle`, if you use `applicationIdSuffix` or `applicationId` that is different from the package name indicated in `AndroidManifest.xml` in `` tag, for example, to support different build variants: Add this in `android/app/build.gradle` -``` +```groovy defaultConfig { ... resValue "string", "build_config_package", "YOUR_PACKAGE_NAME_IN_ANDROIDMANIFEST_XML" diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt index 4cd6a42a..f453363b 100644 --- a/android/CMakeLists.txt +++ b/android/CMakeLists.txt @@ -7,97 +7,88 @@ set(CMAKE_CXX_STANDARD 17) set(BUILD_DIR ${CMAKE_SOURCE_DIR}/build) if(${REACT_NATIVE_MINOR_VERSION} GREATER_EQUAL 71) - # Consume shared libraries and headers from prefabs - find_package(fbjni REQUIRED CONFIG) - find_package(ReactAndroid REQUIRED CONFIG) + # Consume shared libraries and headers from prefabs + find_package(ReactAndroid REQUIRED CONFIG) - include_directories( - ${PACKAGE_NAME} - "${NODE_MODULES_DIR}/react-native/React" - "${NODE_MODULES_DIR}/react-native/React/Base" - "${NODE_MODULES_DIR}/react-native/ReactCommon/jsi" - "./androidcpp" - "../cpp" - ${FOLLY_INCLUDE_DIR} - "." - "${NODE_MODULES_DIR}/react-native/ReactAndroid/src/main/jni/react/turbomodule" - ) + include_directories( + ${PACKAGE_NAME} + "./androidcpp" + "../cpp" + ) - file(GLOB LIBRN_DIR "${BUILD_DIR}/react-native-0*/jni/${ANDROID_ABI}") - message(STATUS "LIBRN_DIR: ${LIBRN_DIR}") + file(GLOB LIBRN_DIR "${BUILD_DIR}/react-native-0*/jni/${ANDROID_ABI}") + message(STATUS "LIBRN_DIR: ${LIBRN_DIR}") - add_library( - ${PACKAGE_NAME} - SHARED - ./androidcpp/mediator.cpp - ./cpp-adapter.cpp - ../cpp/crypto.cpp - ../cpp/decryptor.cpp - ) + add_library( + ${PACKAGE_NAME} + SHARED + ./androidcpp/mediator.cpp + ./cpp-adapter.cpp + ../cpp/crypto.cpp + ../cpp/decryptor.cpp + ) - find_library( - LOG_LIB - log - ) + find_library( + LOG_LIB + log + ) - find_library( - REACT_NATIVE_JNI_LIB - reactnativejni - PATHS ${LIBRN_DIR} - NO_CMAKE_FIND_ROOT_PATH - ) + find_library( + REACT_NATIVE_JNI_LIB + reactnativejni + PATHS ${LIBRN_DIR} + NO_CMAKE_FIND_ROOT_PATH + ) - set_target_properties( - ${PACKAGE_NAME} PROPERTIES - CXX_STANDARD 17 - CXX_EXTENSIONS OFF - POSITION_INDEPENDENT_CODE ON - ) + set_target_properties( + ${PACKAGE_NAME} PROPERTIES + CXX_STANDARD 17 + CXX_EXTENSIONS OFF + POSITION_INDEPENDENT_CODE ON + ) - find_package(openssl REQUIRED CONFIG) + find_package(openssl REQUIRED CONFIG) - target_link_libraries( - ${PACKAGE_NAME} - ReactAndroid::turbomodulejsijni - fbjni::fbjni - ${LOG_LIB} - ReactAndroid::jsi - ReactAndroid::reactnativejni - ReactAndroid::react_nativemodule_core - android - openssl::crypto - ) + target_link_libraries( + ${PACKAGE_NAME} + ${LOG_LIB} + ReactAndroid::jsi + ReactAndroid::reactnativejni + ReactAndroid::react_nativemodule_core + android + openssl::crypto + ) else() - add_library( - ${PACKAGE_NAME} - SHARED - ../../react-native/ReactCommon/jsi/jsi/jsi.cpp - ./androidcpp/mediator.cpp - ./cpp-adapter.cpp - ../cpp/crypto.cpp - ../cpp/decryptor.cpp - ) + add_library( + ${PACKAGE_NAME} + SHARED + ../../react-native/ReactCommon/jsi/jsi/jsi.cpp + ./androidcpp/mediator.cpp + ./cpp-adapter.cpp + ../cpp/crypto.cpp + ../cpp/decryptor.cpp + ) - include_directories( - ../../react-native/React - ../../react-native/React/Base - ../../react-native/ReactCommon/jsi - ./cpp - ../cpp - ) + include_directories( + ../../react-native/React + ../../react-native/React/Base + ../../react-native/ReactCommon/jsi + ./cpp + ../cpp + ) - set_target_properties( - ${PACKAGE_NAME} PROPERTIES - CXX_STANDARD 17 - CXX_EXTENSIONS OFF - POSITION_INDEPENDENT_CODE ON - ) + set_target_properties( + ${PACKAGE_NAME} PROPERTIES + CXX_STANDARD 17 + CXX_EXTENSIONS OFF + POSITION_INDEPENDENT_CODE ON + ) - find_package(openssl REQUIRED CONFIG) + find_package(openssl REQUIRED CONFIG) - target_link_libraries( - ${PACKAGE_NAME} - android - openssl::crypto - ) + target_link_libraries( + ${PACKAGE_NAME} + android + openssl::crypto + ) endif() diff --git a/android/build.gradle b/android/build.gradle index 0670325c..01ea034a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,26 +1,41 @@ import java.nio.file.Paths buildscript { - repositories { google() mavenCentral() - - maven { - url "https://plugins.gradle.org/m2/" - } } + dependencies { - classpath 'com.android.tools.build:gradle:4.2.1' + classpath "com.android.tools.build:gradle:7.2.1" } } -apply plugin: 'com.android.library' +def isNewArchitectureEnabled() { + return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" +} + +apply plugin: "com.android.library" + + +def appProject = rootProject.allprojects.find { it.plugins.hasPlugin('com.android.application') } + +if (isNewArchitectureEnabled()) { + apply plugin: "com.facebook.react" +} def safeExtGet(prop, fallback) { rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback } +def getExtOrDefault(name) { + return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["Keys_" + name] +} + +def getExtOrIntegerDefault(name) { + return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["Keys_" + name]).toInteger() +} + def resolveReactNativeDirectory() { def reactNativeLocation = safeExtGet("REACT_NATIVE_NODE_MODULES_DIR", null) if (reactNativeLocation != null) { @@ -55,10 +70,6 @@ def REACT_NATIVE_VERSION = reactProperties.getProperty("VERSION_NAME") def REACT_NATIVE_MINOR_VERSION = REACT_NATIVE_VERSION.startsWith("0.0.0-") ? 1000 : REACT_NATIVE_VERSION.split("\\.")[1].toInteger() -def getExtOrDefault(name, defaultValue) { - return rootProject.ext.has(name) ? rootProject.ext.get(name) : defaultValue -} - def found = false def basePath = projectDir.toPath().normalize() @@ -93,17 +104,37 @@ def nodeModulesPath = nodeModulesDir.toString().replace("\\", "/") def reactNativePath = reactNativeDir.toString().replace("\\", "/") -android { - compileSdkVersion getExtOrDefault('compileSdkVersion', 28) +def supportsNamespace() { + def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.') + def major = parsed[0].toInteger() + def minor = parsed[1].toInteger() - buildFeatures { - prefab true + // Namespace support was added in 7.3.0 + if (major == 7 && minor >= 3) { + return true } - defaultConfig { - minSdkVersion getExtOrDefault('minSdkVersion', 16) - targetSdkVersion getExtOrDefault('targetSdkVersion', 28) + return major >= 8 +} +android { + if (supportsNamespace()) { + namespace "com.reactnativekeysjsi" + } else { + sourceSets { + main { + manifest.srcFile "src/main/AndroidManifestDeprecated.xml" + } + } + } + + ndkVersion getExtOrDefault("ndkVersion") + compileSdkVersion getExtOrIntegerDefault("compileSdkVersion") + + defaultConfig { + minSdkVersion getExtOrIntegerDefault("minSdkVersion") + targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() externalNativeBuild { cmake { cppFlags "-fexceptions", "-frtti", "-std=c++1y", "-DONANDROID" @@ -114,55 +145,71 @@ android { } } } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - lintOptions{ - abortOnError false - disable 'GradleCompatible' - } - externalNativeBuild { cmake { - path "./CMakeLists.txt" + path "CMakeLists.txt" } } - - packagingOptions { + packagingOptions { excludes = ['**/libc++_shared.so', '**/libfbjni.so', '**/libreactnativejni.so', '**/libjsi.so', '**/libreact_nativemodule_core.so', - '**/libturbomodulejsijni.so' + '**/libturbomodulejsijni.so', + '**/libcrypto.so' ] } + buildTypes { + release { + minifyEnabled false + } + } + buildFeatures { + prefab true + } + lintOptions { + disable "GradleCompatible" + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + sourceSets { + main { + if (isNewArchitectureEnabled()) { + java.srcDirs += [ + "src/newarch", + // This is needed to build Kotlin project with NewArch enabled + "${project.buildDir}/generated/source/codegen/java" + ] + } else { + java.srcDirs += ["src/oldarch"] + } + } + } } repositories { mavenCentral() - mavenLocal() google() - - maven { - url reactNativePath - name 'React Native sources' - } } + dependencies { + // For < 0.71, this will be from the local maven repo + // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin //noinspection GradleDynamicVersion - if (REACT_NATIVE_MINOR_VERSION >= 71) { - implementation "com.facebook.react:react-android:" - implementation "com.facebook.react:hermes-android:" - } - else - { - implementation 'com.facebook.react:react-native:+' - } + implementation "com.facebook.react:react-native:+" implementation 'com.android.ndk.thirdparty:openssl:1.1.1l-beta-1' } + +if (isNewArchitectureEnabled()) { + react { + jsRootDir = file("../src/") + libraryName = "Keys" + codegenJavaPackageName = "com.reactnativekeysjsi" + } +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 00000000..382aa86c --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,5 @@ +Keys_kotlinVersion=1.7.0 +Keys_minSdkVersion=21 +Keys_targetSdkVersion=31 +Keys_compileSdkVersion=31 +Keys_ndkversion=21.4.7075529 diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 7d747e50..a2f47b60 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,4 +1,2 @@ - - + diff --git a/android/src/main/AndroidManifestDeprecated.xml b/android/src/main/AndroidManifestDeprecated.xml new file mode 100644 index 00000000..d3db480f --- /dev/null +++ b/android/src/main/AndroidManifestDeprecated.xml @@ -0,0 +1,3 @@ + + diff --git a/android/src/main/java/com/reactnativekeysjsi/KeysModule.java b/android/src/main/java/com/reactnativekeysjsi/KeysModule.java index 61ea6b12..68cca501 100644 --- a/android/src/main/java/com/reactnativekeysjsi/KeysModule.java +++ b/android/src/main/java/com/reactnativekeysjsi/KeysModule.java @@ -8,24 +8,23 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.JavaScriptContextHolder; import org.json.JSONObject; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; -@ReactModule(name = KeysModule.NAME) -public class KeysModule extends ReactContextBaseJavaModule { +public class KeysModule extends KeysSpec { public static final String NAME = "Keys"; public static ReactApplicationContext reactContext; - private native void nativeInstall(long jsiPtr, String docDir); + private native void nativeInstall(long jsiPtr); public KeysModule(ReactApplicationContext reactContext) { super(reactContext); - this.reactContext=reactContext; + this.reactContext = reactContext; } @Override @@ -37,19 +36,15 @@ public String getName() { @ReactMethod(isBlockingSynchronousMethod = true) public boolean install() { try { - System.loadLibrary("react-native-keys"); - - ReactApplicationContext context = getReactApplicationContext(); - nativeInstall( - context.getJavaScriptContextHolder().get(), - context.getFilesDir().getAbsolutePath()); + JavaScriptContextHolder jsContext = this.reactContext.getJavaScriptContextHolder(); + this.nativeInstall(jsContext.get()); return true; } catch (Exception exception) { return false; } } - static{ + static { System.loadLibrary("react-native-keys"); } @@ -60,7 +55,7 @@ public static String getSecureFor(String key) { JSONObject jniData = null; try { if (jniData == null) { - String privateKey=PrivateKey.privatekey; + String privateKey = PrivateKey.privatekey; String jsonString = getJniJsonStringifyData(privateKey); jniData = new JSONObject(jsonString); } @@ -76,16 +71,16 @@ public static String getSecureFor(String key) { public Map getPublicKeys() { final Map constants = new HashMap<>(); try { - Context context = getReactApplicationContext(); - int resId = context.getResources().getIdentifier("build_config_package", "string", context.getPackageName()); + int resId = this.reactContext.getResources().getIdentifier("build_config_package", "string", this.reactContext.getPackageName()); String className; try { - className = context.getString(resId); + className = this.reactContext.getString(resId); } catch (Resources.NotFoundException e) { - className = getReactApplicationContext().getApplicationContext().getPackageName(); + className = this.reactContext.getPackageName(); } Class clazz = Class.forName(className + ".BuildConfig"); + Field[] fields = clazz.getDeclaredFields(); for (Field f : fields) { try { diff --git a/android/src/main/java/com/reactnativekeysjsi/KeysPackage.java b/android/src/main/java/com/reactnativekeysjsi/KeysPackage.java index f91043fa..e3dc824f 100644 --- a/android/src/main/java/com/reactnativekeysjsi/KeysPackage.java +++ b/android/src/main/java/com/reactnativekeysjsi/KeysPackage.java @@ -1,28 +1,45 @@ package com.reactnativekeysjsi; -import androidx.annotation.NonNull; +import androidx.annotation.Nullable; -import com.facebook.react.ReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; +import com.facebook.react.module.model.ReactModuleInfo; +import com.facebook.react.module.model.ReactModuleInfoProvider; +import com.facebook.react.TurboReactPackage; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.HashMap; +import java.util.Map; -public class KeysPackage implements ReactPackage { - @NonNull - @Override - public List createNativeModules(@NonNull ReactApplicationContext reactContext) { - List modules = new ArrayList<>(); - modules.add(new KeysModule(reactContext)); - return modules; - } +public class KeysPackage extends TurboReactPackage { - @NonNull - @Override - public List createViewManagers(@NonNull ReactApplicationContext reactContext) { - return Collections.emptyList(); + @Nullable + @Override + public NativeModule getModule(String name, ReactApplicationContext reactContext) { + if (name.equals(KeysModule.NAME)) { + return new KeysModule(reactContext); + } else { + return null; } + } + + @Override + public ReactModuleInfoProvider getReactModuleInfoProvider() { + return () -> { + final Map moduleInfos = new HashMap<>(); + boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + moduleInfos.put( + KeysModule.NAME, + new ReactModuleInfo( + KeysModule.NAME, + KeysModule.NAME, + false, // canOverrideExistingModule + false, // needsEagerInit + true, // hasConstants + false, // isCxxModule + isTurboModule // isTurboModule + )); + return moduleInfos; + }; + } } diff --git a/android/src/main/java/com/reactnativekeysjsi/PrivateKey.java b/android/src/main/java/com/reactnativekeysjsi/PrivateKey.java index 2a5f0710..17371ac4 100644 --- a/android/src/main/java/com/reactnativekeysjsi/PrivateKey.java +++ b/android/src/main/java/com/reactnativekeysjsi/PrivateKey.java @@ -3,5 +3,5 @@ package com.reactnativekeysjsi; public class PrivateKey { - public static String privatekey="8sQrHyxSbdJCiVhdrAPceBR0ekPaQfmz8gXuUbJ7cEdqxmiunIb6Va/Nr8Jj8XCdTMZfrr/+iTNVr6/BqWOIdwsMHbpdQgUMMsWtkOM9qg=="; + public static String privatekey="pZoshfXIdCfwBqsc57d31atAUMf0lxCX5NWnCtWzHwFa4YazE8aHeQ009f8GiurSFBtjDNMSoog33YYHZtebu0+PrCTX8su4Y1df5FK1Rg=="; } \ No newline at end of file diff --git a/android/src/newarch/KeysSpec.java b/android/src/newarch/KeysSpec.java new file mode 100644 index 00000000..f2f7ada8 --- /dev/null +++ b/android/src/newarch/KeysSpec.java @@ -0,0 +1,9 @@ +package com.reactnativekeysjsi; + +import com.facebook.react.bridge.ReactApplicationContext; + +abstract class KeysSpec extends NativeKeysSpec { + KeysSpec(ReactApplicationContext context) { + super(context); + } +} diff --git a/android/src/oldarch/KeysSpec.java b/android/src/oldarch/KeysSpec.java new file mode 100644 index 00000000..8b7d9b68 --- /dev/null +++ b/android/src/oldarch/KeysSpec.java @@ -0,0 +1,13 @@ +package com.reactnativekeysjsi; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.Promise; + +abstract class KeysSpec extends ReactContextBaseJavaModule { + KeysSpec(ReactApplicationContext context) { + super(context); + } + public abstract boolean install(); + +} diff --git a/cpp/crypto.cpp b/cpp/crypto.cpp index 90cde486..eca21025 100644 --- a/cpp/crypto.cpp +++ b/cpp/crypto.cpp @@ -10,11 +10,11 @@ } string Crypto::getJniJsonStringifyData(string key) { - std::string base64Secret1 = "U2FsdGVkX18WCoAQlB0qyhBdFJQMwtn2lUeiF3GD1uT1sY6M4m+qzDRxl45EOrUexbEcuYdO"; - std::string base64Secret2 = "v3eNgZZ/kDEPMJNDLu8OAu1dzNo/gLSZWkzl8sQrHyxSbdJCiVhdrAPceBR0ekPaQfmz8gXu"; - std::string base64Secret3 = "UbJ7cEdqxmiunIb6Va/Nr8Jj8XCdTMZfrr/+iTNVr6/BqWOIdwsMHbpdQgUMMsWtkOM9qg=="; + std::string base64Secret1 = "U2FsdGVkX199+I364h5jWqyctRTxfs71VpO171cahBoWf4m/sExs57WYLzGBfHT7YviRpyAt"; + std::string base64Secret2 = "s/Dk7rj1VsY7MvElsDbaLj4jhHT/y0EpT/wCSJw6NgZ3SIlM6eJKqvwDjRCZfMrBoPMwO3Aw"; + std::string base64Secret3 = "pj8YZTX+0gzzQ4OhdLiZpOUa8iPTyjSbUwelLLqD2nWAXT+dWzbsAeN8inNXNaJKbFMSpg=="; std::string base64Secret = base64Secret1 + base64Secret2 + base64Secret3; - std::string password = "nH4QVBty9DRr"; + std::string password = "3seCzMfVxah8"; bool binary = false; std::string plaintext = decryptor::dec(base64Secret, password,binary); diff --git a/example/.gitignore b/example/.gitignore deleted file mode 100644 index 8af56359..00000000 --- a/example/.gitignore +++ /dev/null @@ -1,66 +0,0 @@ -# OSX -# -.DS_Store - -# Xcode -# -build/ -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 -xcuserdata -*.xccheckout -*.moved-aside -DerivedData -*.hmap -*.ipa -*.xcuserstate -ios/.xcode.env.local - -# Android/IntelliJ -# -build/ -.idea -.gradle -local.properties -*.iml -*.hprof -.cxx/ -!debug.keystore - -# node.js -# -node_modules/ -npm-debug.log -yarn-error.log - -# fastlane -# -# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the -# screenshots whenever they are needed. -# For more information about the recommended setup visit: -# https://docs.fastlane.tools/best-practices/source-control/ - -**/fastlane/report.xml -**/fastlane/Preview.html -**/fastlane/screenshots -**/fastlane/test_output - -# Bundle artifact -*.jsbundle - -# Ruby / CocoaPods -/ios/Pods/ -/vendor/bundle/ - -# Temporary files created by Metro to check the health of the file watcher -.metro-health-check* - - -ios/**prebuild.log -ios/tmp.xcconfig diff --git a/example/.watchmanconfig b/example/.watchmanconfig index 9e26dfee..0967ef42 100644 --- a/example/.watchmanconfig +++ b/example/.watchmanconfig @@ -1 +1 @@ -{} \ No newline at end of file +{} diff --git a/example/Gemfile b/example/Gemfile index 1142b1b2..1fa2c2e1 100644 --- a/example/Gemfile +++ b/example/Gemfile @@ -1,6 +1,6 @@ source 'https://rubygems.org' # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version -ruby '>= 2.6.10' +ruby ">= 2.6.10" -gem 'cocoapods', '>= 1.11.3' +gem 'cocoapods', '~> 1.12' diff --git a/example/Gemfile.lock b/example/Gemfile.lock deleted file mode 100644 index 693acddc..00000000 --- a/example/Gemfile.lock +++ /dev/null @@ -1,98 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - CFPropertyList (3.0.6) - rexml - activesupport (7.0.4.3) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 1.6, < 2) - minitest (>= 5.1) - tzinfo (~> 2.0) - addressable (2.8.3) - public_suffix (>= 2.0.2, < 6.0) - algoliasearch (1.27.5) - httpclient (~> 2.8, >= 2.8.3) - json (>= 1.5.1) - atomos (0.1.3) - claide (1.1.0) - cocoapods (1.12.0) - addressable (~> 2.8) - claide (>= 1.0.2, < 2.0) - cocoapods-core (= 1.12.0) - cocoapods-deintegrate (>= 1.0.3, < 2.0) - cocoapods-downloader (>= 1.6.0, < 2.0) - cocoapods-plugins (>= 1.0.0, < 2.0) - cocoapods-search (>= 1.0.0, < 2.0) - cocoapods-trunk (>= 1.6.0, < 2.0) - cocoapods-try (>= 1.1.0, < 2.0) - colored2 (~> 3.1) - escape (~> 0.0.4) - fourflusher (>= 2.3.0, < 3.0) - gh_inspector (~> 1.0) - molinillo (~> 0.8.0) - nap (~> 1.0) - ruby-macho (>= 2.3.0, < 3.0) - xcodeproj (>= 1.21.0, < 2.0) - cocoapods-core (1.12.0) - activesupport (>= 5.0, < 8) - addressable (~> 2.8) - algoliasearch (~> 1.0) - concurrent-ruby (~> 1.1) - fuzzy_match (~> 2.0.4) - nap (~> 1.0) - netrc (~> 0.11) - public_suffix (~> 4.0) - typhoeus (~> 1.0) - cocoapods-deintegrate (1.0.5) - cocoapods-downloader (1.6.3) - cocoapods-plugins (1.0.0) - nap - cocoapods-search (1.0.1) - cocoapods-trunk (1.6.0) - nap (>= 0.8, < 2.0) - netrc (~> 0.11) - cocoapods-try (1.2.0) - colored2 (3.1.2) - concurrent-ruby (1.2.2) - escape (0.0.4) - ethon (0.16.0) - ffi (>= 1.15.0) - ffi (1.15.5) - fourflusher (2.3.1) - fuzzy_match (2.0.4) - gh_inspector (1.1.3) - httpclient (2.8.3) - i18n (1.12.0) - concurrent-ruby (~> 1.0) - json (2.6.3) - minitest (5.18.0) - molinillo (0.8.0) - nanaimo (0.3.0) - nap (1.1.0) - netrc (0.11.0) - public_suffix (4.0.7) - rexml (3.2.5) - ruby-macho (2.5.1) - typhoeus (1.4.0) - ethon (>= 0.9.0) - tzinfo (2.0.6) - concurrent-ruby (~> 1.0) - xcodeproj (1.22.0) - CFPropertyList (>= 2.3.3, < 4.0) - atomos (~> 0.1.3) - claide (>= 1.0.2, < 2.0) - colored2 (~> 3.1) - nanaimo (~> 0.3.0) - rexml (~> 3.2.4) - -PLATFORMS - ruby - -DEPENDENCIES - cocoapods (>= 1.11.3) - -RUBY VERSION - ruby 2.7.6p219 - -BUNDLED WITH - 2.1.4 diff --git a/example/README.md b/example/README.md new file mode 100644 index 00000000..1002ec20 --- /dev/null +++ b/example/README.md @@ -0,0 +1,47 @@ +## Get started + +To try the playground out for yourself, run the following commands: + +```sh +git clone +cd example +yarn +``` + +### iOS + +1. Open the example/ios/KeysExample.xcworkspace file with Xcode +2. Change signing configuration to your developer account +3. Select your device in the devices drop-down +4. Hit run + +### Android + +1. Open the example/android/ folder with Android Studio +2. Select your device in the devices drop-down +3. Hit run + +### Enable New Arch + +#### Android + +You will only need to update your android/gradle.properties file as follows: + +```diff +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +- newArchEnabled=false ++ newArchEnabled=true +``` + +#### IOS + +You will only need to reinstall your pods by running pod install with the right flag: + +```sh +# Run pod install with the flag: +RCT_NEW_ARCH_ENABLED=1 bundle exec pod install +``` diff --git a/example/__tests__/App-test.tsx b/example/__tests__/App-test.tsx deleted file mode 100644 index 4edaa0a8..00000000 --- a/example/__tests__/App-test.tsx +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @format - */ - -import 'react-native'; -import React from 'react'; -import App from '../src/App'; - -// Note: test renderer must be required after react-native. -import renderer from 'react-test-renderer'; - -it('renders correctly', () => { - renderer.create(); -}); diff --git a/example/_node-version b/example/_node-version deleted file mode 100644 index 3c032078..00000000 --- a/example/_node-version +++ /dev/null @@ -1 +0,0 @@ -18 diff --git a/example/_ruby-version b/example/_ruby-version deleted file mode 100644 index a4dd9dba..00000000 --- a/example/_ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.7.4 diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 15708623..30279132 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -1,9 +1,5 @@ apply plugin: "com.android.application" apply plugin: "com.facebook.react" - -import com.android.build.OutputFile - -//IS_EXAMPLE flag is for contribution not for production project.ext.IS_EXAMPLE = true; project.ext.keyFiles = [ development: "keys.development.json", @@ -23,8 +19,8 @@ react { // root = file("../") // The folder where the react-native NPM package is. Default is ../node_modules/react-native // reactNativeDir = file("../node_modules/react-native") - // The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen - // codegenDir = file("../node_modules/react-native-codegen") + // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen + // codegenDir = file("../node_modules/@react-native/codegen") // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js // cliFile = file("../node_modules/react-native/cli.js") @@ -62,14 +58,6 @@ react { // hermesFlags = ["-O", "-output-source-map"] } -/** - * Set this to true to create four separate APKs instead of one, - * one for each native architecture. This is useful if you don't - * use App Bundles (https://developer.android.com/guide/app-bundle/) - * and want to have separate APKs to upload to the Play Store. - */ -def enableSeparateBuildPerCPUArchitecture = false - /** * Set this to true to Run Proguard on Release builds to minify the Java bytecode. */ @@ -88,52 +76,19 @@ def enableProguardInReleaseBuilds = false */ def jscFlavor = 'org.webkit:android-jsc:+' -/** - * Private function to get the list of Native Architectures you want to build. - * This reads the value from reactNativeArchitectures in your gradle.properties - * file and works together with the --active-arch-only flag of react-native run-android. - */ -def reactNativeArchitectures() { - def value = project.getProperties().get("reactNativeArchitectures") - return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] -} - android { ndkVersion rootProject.ext.ndkVersion compileSdkVersion rootProject.ext.compileSdkVersion - namespace "com.jsikeysexample" + namespace "com.keysexample" defaultConfig { - applicationId "com.jsikeysexample" + resValue "string", "build_config_package", "com.keysexample" + applicationId "com.keysexample" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 versionName "1.0" - resValue "string", "build_config_package", "com.jsikeysexample" - } - - splits { - abi { - reset() - enable enableSeparateBuildPerCPUArchitecture - universalApk false // If true, also generate a universal APK - include (*reactNativeArchitectures()) - } - } - signingConfigs { - debug { - storeFile file('debug.keystore') - storePassword 'android' - keyAlias 'androiddebugkey' - keyPassword 'android' - } - release { - storeFile file("keyExample.keystore") - storePassword 'example123' - keyAlias 'example' - keyPassword 'example123' - } } flavorDimensions "default" productFlavors { @@ -147,6 +102,14 @@ android { applicationIdSuffix "" } } + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + } buildTypes { debug { signingConfig signingConfigs.debug @@ -159,30 +122,12 @@ android { proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } - - // applicationVariants are e.g. debug, release - applicationVariants.all { variant -> - variant.outputs.each { output -> - // For each separate APK per architecture, set a unique version code as described here: - // https://developer.android.com/studio/build/configure-apk-splits.html - // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc. - def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] - def abi = output.getFilter(OutputFile.ABI) - if (abi != null) { // null for the universal-debug, universal-release variants - output.versionCodeOverride = - defaultConfig.versionCode * 1000 + versionCodes.get(abi) - } - - } - } } dependencies { // The version of react-native is set by the React Native Gradle Plugin implementation("com.facebook.react:react-android") - implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0") - debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { exclude group:'com.squareup.okhttp3', module:'okhttp' @@ -194,7 +139,6 @@ dependencies { } else { implementation jscFlavor } - implementation project(':reactNativeKeys') } diff --git a/example/android/app/keyExample.keystore b/example/android/app/keyExample.keystore deleted file mode 100644 index 10ac3557..00000000 Binary files a/example/android/app/keyExample.keystore and /dev/null differ diff --git a/example/android/app/src/debug/java/com/jsikeysexample/ReactNativeFlipper.java b/example/android/app/src/debug/java/com/keysexample/ReactNativeFlipper.java similarity index 99% rename from example/android/app/src/debug/java/com/jsikeysexample/ReactNativeFlipper.java rename to example/android/app/src/debug/java/com/keysexample/ReactNativeFlipper.java index 0c2e00fe..354160d4 100644 --- a/example/android/app/src/debug/java/com/jsikeysexample/ReactNativeFlipper.java +++ b/example/android/app/src/debug/java/com/keysexample/ReactNativeFlipper.java @@ -4,7 +4,7 @@ *

This source code is licensed under the MIT license found in the LICENSE file in the root * directory of this source tree. */ -package com.jsikeysexample; +package com.keysexample; import android.content.Context; import com.facebook.flipper.android.AndroidFlipperClient; diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 88ce3dec..4122f36a 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,4 @@ - + diff --git a/example/android/app/src/main/java/com/jsikeysexample/MainApplication.java b/example/android/app/src/main/java/com/jsikeysexample/MainApplication.java deleted file mode 100644 index 9eaae763..00000000 --- a/example/android/app/src/main/java/com/jsikeysexample/MainApplication.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.jsikeysexample; - -import static com.reactnativekeysjsi.KeysModule.getSecureFor; - -import android.app.Application; -import android.util.Log; - -import com.facebook.react.PackageList; -import com.facebook.react.ReactApplication; -import com.facebook.react.ReactNativeHost; -import com.facebook.react.ReactPackage; -import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; -import com.facebook.react.defaults.DefaultReactNativeHost; -import com.facebook.soloader.SoLoader; -import com.reactnativekeysjsi.KeysPackage; -import java.util.List; - -public class MainApplication extends Application implements ReactApplication { - - private final ReactNativeHost mReactNativeHost = new DefaultReactNativeHost(this) { - @Override - public boolean getUseDeveloperSupport() { - return BuildConfig.DEBUG; - } - - @Override - protected List getPackages() { - @SuppressWarnings("UnnecessaryLocalVariable") - List packages = new PackageList(this).getPackages(); - // Packages that cannot be autolinked yet can be added manually here, for - // example: - // packages.add(new MyReactNativePackage()); - packages.add(new KeysPackage()); - return packages; - } - - @Override - protected String getJSMainModuleName() { - return "index"; - } - - @Override - protected boolean isNewArchEnabled() { - return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; - } - - @Override - protected Boolean isHermesEnabled() { - return BuildConfig.IS_HERMES_ENABLED; - } - }; - - @Override - public ReactNativeHost getReactNativeHost() { - return mReactNativeHost; - } - - @Override - public void onCreate() { - super.onCreate(); - SoLoader.init(this, /* native exopackage */ false); - if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { - // If you opted-in for the New Architecture, we load the native entry point for - // this app. - DefaultNewArchitectureEntryPoint.load(); - } - String secureValue=getSecureFor("secure3"); - String publicValue = BuildConfig.APP_NAME; - Log.d("secure(JNI)", "this value is from secure: "+secureValue); - Log.d("secure(JNI)", "this value is from public: " + publicValue); - } -} diff --git a/example/android/app/src/main/java/com/jsikeysexample/MainActivity.java b/example/android/app/src/main/java/com/keysexample/MainActivity.java similarity index 74% rename from example/android/app/src/main/java/com/jsikeysexample/MainActivity.java rename to example/android/app/src/main/java/com/keysexample/MainActivity.java index f1b42f73..17ae3171 100644 --- a/example/android/app/src/main/java/com/jsikeysexample/MainActivity.java +++ b/example/android/app/src/main/java/com/keysexample/MainActivity.java @@ -1,4 +1,4 @@ -package com.jsikeysexample; +package com.keysexample; import com.facebook.react.ReactActivity; import com.facebook.react.ReactActivityDelegate; @@ -13,7 +13,7 @@ public class MainActivity extends ReactActivity { */ @Override protected String getMainComponentName() { - return "Example"; + return "KeysExample"; } /** @@ -27,9 +27,6 @@ protected ReactActivityDelegate createReactActivityDelegate() { this, getMainComponentName(), // If you opted-in for the New Architecture, we enable the Fabric Renderer. - DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled - // If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18). - DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled - ); + DefaultNewArchitectureEntryPoint.getFabricEnabled()); } } diff --git a/example/android/app/src/main/java/com/keysexample/MainApplication.java b/example/android/app/src/main/java/com/keysexample/MainApplication.java new file mode 100644 index 00000000..c8320c19 --- /dev/null +++ b/example/android/app/src/main/java/com/keysexample/MainApplication.java @@ -0,0 +1,69 @@ +package com.keysexample; + +import static com.reactnativekeysjsi.KeysModule.getSecureFor; +import android.util.Log; + +import android.app.Application; +import com.facebook.react.PackageList; +import com.facebook.react.ReactApplication; +import com.facebook.react.ReactNativeHost; +import com.facebook.react.ReactPackage; +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; +import com.facebook.react.defaults.DefaultReactNativeHost; +import com.facebook.soloader.SoLoader; +import java.util.List; + +public class MainApplication extends Application implements ReactApplication { + + private final ReactNativeHost mReactNativeHost = + new DefaultReactNativeHost(this) { + @Override + public boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + @Override + protected List getPackages() { + @SuppressWarnings("UnnecessaryLocalVariable") + List packages = new PackageList(this).getPackages(); + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + return packages; + } + + @Override + protected String getJSMainModuleName() { + return "index"; + } + + @Override + protected boolean isNewArchEnabled() { + return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + } + + @Override + protected Boolean isHermesEnabled() { + return BuildConfig.IS_HERMES_ENABLED; + } + }; + + @Override + public ReactNativeHost getReactNativeHost() { + return mReactNativeHost; + } + + @Override + public void onCreate() { + super.onCreate(); + SoLoader.init(this, /* native exopackage */ false); + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + DefaultNewArchitectureEntryPoint.load(); + } + String secureValue = getSecureFor("secure3"); + String publicValue = BuildConfig.APP_NAME; + Log.d("secure(JNI)", "this value is from secure: " + secureValue); + Log.d("secure(JNI)", "this value is from public: " + publicValue); + ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + } +} diff --git a/example/android/app/src/main/res/drawable/rn_edit_text_material.xml b/example/android/app/src/main/res/drawable/rn_edit_text_material.xml index f35d9962..73b37e4d 100644 --- a/example/android/app/src/main/res/drawable/rn_edit_text_material.xml +++ b/example/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -20,7 +20,7 @@ android:insetBottom="@dimen/abc_edit_text_inset_bottom_material"> -