Files
safe-wallet/.yarn/patches/react-native-device-crypto-npm-0.1.7-dbd2698fc4.patch
df7946ec14 fix(mobile): upgrade react-native-quick-crypto for Android 16KB page size (#7480)
* fix(mobile): upgrade react-native-quick-crypto for Android 16KB page size support

Upgrade react-native-quick-crypto from 0.7.x to 1.0.17 to support
Android 16KB page size requirement. Add react-native-nitro-modules and
react-native-quick-base64 as new peer dependencies. Update
react-native-device-crypto patch to remove deprecated jcenter()
repository references for Gradle 9.0 compatibility.

* chore(mobile): remove unused config/ethers.ts

Dead code — crypto-shims.ts in platform/ is the active version
imported by the root layout.

* fix(mobile): deduplicate react-native-quick-base64 via resolution

Add root resolution to force a single copy of react-native-quick-base64
(2.2.2), avoiding version skew between the direct dependency and the
transitive one from @craftzdog/react-native-buffer.

* fix(mobile): upgrade react-native-mmkv to v4 and pin MMKV pod

- Upgrade react-native-mmkv from 3.x to 4.2.0 (Nitro-based rewrite)
- Migrate API: new MMKV() -> createMMKV(), .delete() -> .remove()
- Pin MMKV pod to ~> 2.3.0 in notification extension plugin instead
  of master branch, fixing sharedApplication build error in App
  Extensions
- Update expo plugin config.ts (source of truth for Podfile template)

* docs: add solution doc for Expo native file editing workflow

Document that generated native files (ios/Podfile etc.) must be
modified through Expo config plugins, not directly. Also unignore
docs/solutions/ from .gitignore.

* fix(mobile): add jest mocks for react-native-nitro-modules and mmkv v4

MMKV v4 uses NitroModules under the hood, which requires mocking in
the test environment. Add mocks for both react-native-nitro-modules
and the new react-native-mmkv createMMKV API.

---------

Co-authored-by: Hanzo Dev <[email protected]>
2026-03-19 13:28:26 +01:00

126 lines
5.4 KiB
Diff

diff --git a/android/build.gradle b/android/build.gradle
index 8eb758ed063d1905f538f72e3ee55a8c41e01d18..d1ee770a3594017357465e031c2edb4aae6a448c 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -3,7 +3,6 @@ buildscript {
repositories {
google()
mavenCentral()
- jcenter()
}
dependencies {
@@ -52,7 +51,6 @@ repositories {
}
google()
mavenCentral()
- jcenter()
}
dependencies {
diff --git a/android/src/main/java/com/reactnativedevicecrypto/Helpers.java b/android/src/main/java/com/reactnativedevicecrypto/Helpers.java
index 03fd79e8a389f33a2841ecf0e177ffc9ea01b78c..d903b5dc4b0110dab9a8c1a648d349200dd4e20f 100644
--- a/android/src/main/java/com/reactnativedevicecrypto/Helpers.java
+++ b/android/src/main/java/com/reactnativedevicecrypto/Helpers.java
@@ -39,6 +39,7 @@ public class Helpers {
private static final int AES_IV_SIZE = 128;
public static final String PEM_HEADER = "-----BEGIN PUBLIC KEY-----\n";
public static final String PEM_FOOTER = "-----END PUBLIC KEY-----";
+ private static Boolean sIsStrongBoxSupported = null; // Cache for StrongBox support
public interface KeyType {
@Retention(SOURCE)
@@ -81,6 +82,64 @@ public class Helpers {
}
}
+ public static boolean isStrongBoxSupported() {
+ // Return cached result if available
+ if (sIsStrongBoxSupported != null) {
+ return sIsStrongBoxSupported;
+ }
+
+ // Try to create a key with StrongBox requirement and see if it succeeds
+ String testAlias = "test_strongbox_support";
+ try {
+ // First, clean up any existing test key
+ try {
+ KeyStore keyStore = getKeyStore();
+ if (keyStore.containsAlias(testAlias)) {
+ keyStore.deleteEntry(testAlias);
+ }
+ } catch (Exception e) {
+ // Ignore errors during cleanup
+ }
+
+ // Attempt to create a key with StrongBox backing
+ KeyGenParameterSpec testSpec = new KeyGenParameterSpec.Builder(testAlias, KeyProperties.PURPOSE_ENCRYPT)
+ .setIsStrongBoxBacked(true)
+ .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ .setKeySize(256)
+ .build();
+ KeyGenerator testKeyGen = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, KEY_STORE);
+ testKeyGen.init(testSpec);
+ testKeyGen.generateKey();
+
+ // If we reach here, StrongBox is supported
+ // Clean up the test key
+ KeyStore keyStore = getKeyStore();
+ keyStore.deleteEntry(testAlias);
+
+ // Cache the result
+ sIsStrongBoxSupported = true;
+ Log.i(RN_MODULE, "StrongBox is supported on this device");
+ return true;
+ } catch (Exception e) {
+ Log.i(RN_MODULE, "StrongBox not supported on this device: " + e.getMessage());
+
+ // Clean up any test key that might have been created
+ try {
+ KeyStore keyStore = getKeyStore();
+ if (keyStore.containsAlias(testAlias)) {
+ keyStore.deleteEntry(testAlias);
+ }
+ } catch (Exception cleanupEx) {
+ // Ignore errors during cleanup
+ }
+
+ // Cache the result
+ sIsStrongBoxSupported = false;
+ return false;
+ }
+ }
+
public static boolean isKeyExists(@NonNull String alias, @KeyType.Types int keyType) throws Exception {
KeyStore keyStore = Helpers.getKeyStore();
if (!keyStore.containsAlias(alias)) {
@@ -134,17 +193,22 @@ public class Helpers {
case AccessLevel.AUTHENTICATION_REQUIRED:
// Sets whether this key is authorized to be used only if the user has been authenticated.
builder.setUserAuthenticationRequired(true);
+
// Allow pin/pass as a fallback on API 30+
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
- builder.setUserAuthenticationParameters(0, KeyProperties.AUTH_DEVICE_CREDENTIAL | KeyProperties.AUTH_BIOMETRIC_STRONG);
- }
+ // Disabled this as it prevents invalidation of the user removes the biometric
+ // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ // builder.setUserAuthenticationParameters(0, KeyProperties.AUTH_DEVICE_CREDENTIAL | KeyProperties.AUTH_BIOMETRIC_STRONG);
+ // }
+
// Invalidate the keys if the user has registered a new biometric
// credential. The variable "invalidatedByBiometricEnrollment" is true by default.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
builder.setInvalidatedByBiometricEnrollment(invalidateOnNewBiometry);
}
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
- builder.setIsStrongBoxBacked(true);
+ // Only try to enable StrongBox if API level is high enough and the device
+ // actually supports it
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && isStrongBoxSupported()) {
+ builder.setIsStrongBoxBacked(true);
}
break;
}