From a56cae626abf6c553cd9756db875c8ab5f903879 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Wed, 15 Jun 2022 22:08:28 -0500 Subject: [PATCH] Move the secure-random code into this project due to build issues with the module, which is no longer maintained --- README.md | 2 +- .../pubsq/AppSecureRandomModule.java | 28 +++++++++++++++++++ .../pubsq/AppSecureRandomPackage.java | 26 +++++++++++++++++ .../xyz/blueskyweb/pubsq/MainApplication.java | 1 + ios/AppSecureRandomModule.h | 5 ++++ ios/AppSecureRandomModule.m | 27 ++++++++++++++++++ ios/Podfile.lock | 6 ---- ios/app.xcodeproj/project.pbxproj | 8 ++++++ ios/app/AppDelegate.mm | 2 +- package.json | 2 +- src/platform/polyfills.native.ts | 12 +++++++- yarn.lock | 9 +----- 12 files changed, 110 insertions(+), 18 deletions(-) create mode 100644 android/app/src/main/java/xyz/blueskyweb/pubsq/AppSecureRandomModule.java create mode 100644 android/app/src/main/java/xyz/blueskyweb/pubsq/AppSecureRandomPackage.java create mode 100644 ios/AppSecureRandomModule.h create mode 100644 ios/AppSecureRandomModule.m diff --git a/README.md b/README.md index 8ebb51f5..55db6fda 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ The `metro.config.js` file rewrites a couple of imports. This is partly to work ### Cryptography -For native builds, we must provide a polyfill of `webcrypto`. We use [react-native-securerandom](https://github.com/robhogan/react-native-securerandom) for the CRNG and [msrcrypto](https://github.com/kevlened/msrCrypto) for the cryptography. +For native builds, we must provide a polyfill of `webcrypto`. We use a custom native module AppSecureRandom (based on [react-native-securerandom](https://github.com/robhogan/react-native-securerandom)) for the CRNG and [msrcrypto](https://github.com/kevlened/msrCrypto) for the cryptography. **NOTE** Keys are not currently stored securely. diff --git a/android/app/src/main/java/xyz/blueskyweb/pubsq/AppSecureRandomModule.java b/android/app/src/main/java/xyz/blueskyweb/pubsq/AppSecureRandomModule.java new file mode 100644 index 00000000..96887c36 --- /dev/null +++ b/android/app/src/main/java/xyz/blueskyweb/pubsq/AppSecureRandomModule.java @@ -0,0 +1,28 @@ +package xyz.blueskyweb.pubsq; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.Promise; + +import java.security.SecureRandom; +import android.util.Base64; + +public class AppSecureRandomModule extends ReactContextBaseJavaModule { + public AppSecureRandomModule(ReactApplicationContext context) { + super(context); + } + + @ReactMethod + public void generateSecureRandomAsBase64(int length, Promise promise) { + SecureRandom secureRandom = new SecureRandom(); + byte[] buffer = new byte[length]; + secureRandom.nextBytes(buffer); + promise.resolve(Base64.encodeToString(buffer, Base64.NO_WRAP)); + } + + @Override + public String getName() { + return "AppSecureRandomModule"; + } +} diff --git a/android/app/src/main/java/xyz/blueskyweb/pubsq/AppSecureRandomPackage.java b/android/app/src/main/java/xyz/blueskyweb/pubsq/AppSecureRandomPackage.java new file mode 100644 index 00000000..1fd65074 --- /dev/null +++ b/android/app/src/main/java/xyz/blueskyweb/pubsq/AppSecureRandomPackage.java @@ -0,0 +1,26 @@ +package xyz.blueskyweb.pubsq; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class AppSecureRandomPackage implements ReactPackage { + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } + + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + List modules = new ArrayList<>(); + modules.add(new AppSecureRandomModule(reactContext)); + return modules; + } + +} \ No newline at end of file diff --git a/android/app/src/main/java/xyz/blueskyweb/pubsq/MainApplication.java b/android/app/src/main/java/xyz/blueskyweb/pubsq/MainApplication.java index abd0f164..8c554a48 100644 --- a/android/app/src/main/java/xyz/blueskyweb/pubsq/MainApplication.java +++ b/android/app/src/main/java/xyz/blueskyweb/pubsq/MainApplication.java @@ -28,6 +28,7 @@ public class MainApplication extends Application implements ReactApplication { 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 AppSecureRandomPackage()); return packages; } diff --git a/ios/AppSecureRandomModule.h b/ios/AppSecureRandomModule.h new file mode 100644 index 00000000..0431684c --- /dev/null +++ b/ios/AppSecureRandomModule.h @@ -0,0 +1,5 @@ +#import + +@interface AppSecureRandomModule : NSObject + +@end diff --git a/ios/AppSecureRandomModule.m b/ios/AppSecureRandomModule.m new file mode 100644 index 00000000..9aba127f --- /dev/null +++ b/ios/AppSecureRandomModule.m @@ -0,0 +1,27 @@ +#import "AppSecureRandomModule.h" + +@implementation AppSecureRandomModule + +RCT_EXPORT_MODULE(); + ++ (BOOL)requiresMainQueueSetup +{ + return NO; +} + +RCT_REMAP_METHOD(generateSecureRandomAsBase64, + withLength:(int)length + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ + NSMutableData* bytes = [NSMutableData dataWithLength:length]; + int result = SecRandomCopyBytes(kSecRandomDefault,length, [bytes mutableBytes]); + if (result == errSecSuccess) { + resolve([bytes base64EncodedStringWithOptions:0]); + } else { + NSError *error = [NSError errorWithDomain:@"RNSecureRandom" code:result userInfo: nil]; + reject(@"randombytes_error", @"Error generating random bytes", error); + } +} + +@end diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 63cc844f..8be1857f 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -296,8 +296,6 @@ PODS: - RNScreens (3.13.1): - React-Core - React-RCTImage - - RNSecureRandom (1.0.0): - - React - Yoga (1.14.0) DEPENDENCIES: @@ -337,7 +335,6 @@ DEPENDENCIES: - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" - RNInAppBrowser (from `../node_modules/react-native-inappbrowser-reborn`) - RNScreens (from `../node_modules/react-native-screens`) - - RNSecureRandom (from `../node_modules/react-native-securerandom`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: @@ -413,8 +410,6 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-inappbrowser-reborn" RNScreens: :path: "../node_modules/react-native-screens" - RNSecureRandom: - :path: "../node_modules/react-native-securerandom" Yoga: :path: "../node_modules/react-native/ReactCommon/yoga" @@ -454,7 +449,6 @@ SPEC CHECKSUMS: RNCAsyncStorage: 466b9df1a14bccda91da86e0b7d9a345d78e1673 RNInAppBrowser: 3ff3a3b8f458aaf25aaee879d057352862edf357 RNScreens: 40a2cb40a02a609938137a1e0acfbf8fc9eebf19 - RNSecureRandom: 0dcee021fdb3d50cd5cee5db0ebf583c42f5af0e Yoga: 99652481fcd320aefa4a7ef90095b95acd181952 PODFILE CHECKSUM: cf94853ebcb0d8e0d027dca9ab7a4ede886a8f20 diff --git a/ios/app.xcodeproj/project.pbxproj b/ios/app.xcodeproj/project.pbxproj index b23ff989..06ea7c61 100644 --- a/ios/app.xcodeproj/project.pbxproj +++ b/ios/app.xcodeproj/project.pbxproj @@ -13,6 +13,8 @@ 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 5CEAE7B7A55582F96F1D5952 /* libPods-app.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FCB672808307A6013805A3FE /* libPods-app.a */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; + E4BD704B285AD57E00A8FED9 /* AppSecureRandomModule.m in Sources */ = {isa = PBXBuildFile; fileRef = E4BD704A285AD57E00A8FED9 /* AppSecureRandomModule.m */; }; + E4BD704C285AD57E00A8FED9 /* AppSecureRandomModule.m in Sources */ = {isa = PBXBuildFile; fileRef = E4BD704A285AD57E00A8FED9 /* AppSecureRandomModule.m */; }; FEB90D21557517F9279AECA4 /* libPods-app-appTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BAD3BC60FA05CF2D4F6F9BA2 /* libPods-app-appTests.a */; }; /* End PBXBuildFile section */ @@ -42,6 +44,8 @@ 970005155A83960D1D13380F /* Pods-app.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.release.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.release.xcconfig"; sourceTree = ""; }; BAD3BC60FA05CF2D4F6F9BA2 /* libPods-app-appTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app-appTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; E4437C9E28581FA7006DA9E7 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = app.entitlements; path = app/app.entitlements; sourceTree = ""; }; + E4BD7049285AD54000A8FED9 /* AppSecureRandomModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppSecureRandomModule.h; sourceTree = ""; }; + E4BD704A285AD57E00A8FED9 /* AppSecureRandomModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppSecureRandomModule.m; sourceTree = ""; }; ED22CAA45207BC18E75DB44B /* Pods-app.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.debug.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.debug.xcconfig"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; FCB672808307A6013805A3FE /* libPods-app.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -94,6 +98,8 @@ 13B07FB61A68108700A75B9A /* Info.plist */, 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, 13B07FB71A68108700A75B9A /* main.m */, + E4BD7049285AD54000A8FED9 /* AppSecureRandomModule.h */, + E4BD704A285AD57E00A8FED9 /* AppSecureRandomModule.m */, ); name = app; sourceTree = ""; @@ -369,6 +375,7 @@ buildActionMask = 2147483647; files = ( 00E356F31AD99517003FC87E /* appTests.m in Sources */, + E4BD704C285AD57E00A8FED9 /* AppSecureRandomModule.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -377,6 +384,7 @@ buildActionMask = 2147483647; files = ( 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, + E4BD704B285AD57E00A8FED9 /* AppSecureRandomModule.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ios/app/AppDelegate.mm b/ios/app/AppDelegate.mm index 8b143fee..474f994e 100644 --- a/ios/app/AppDelegate.mm +++ b/ios/app/AppDelegate.mm @@ -44,7 +44,7 @@ bridge.surfacePresenter = _bridgeAdapter.surfacePresenter; #endif - UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"app", nil); + UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"xyz.blueskyweb.pubsq", nil); if (@available(iOS 13.0, *)) { rootView.backgroundColor = [UIColor systemBackgroundColor]; diff --git a/package.json b/package.json index af95df9e..de09b821 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@react-navigation/native-stack": "^6.6.2", "@react-navigation/stack": "^6.2.1", "@zxing/text-encoding": "^0.9.0", + "base64-js": "^1.5.1", "mobx": "^6.6.0", "mobx-react-lite": "^3.4.0", "mobx-state-tree": "^5.1.5", @@ -31,7 +32,6 @@ "react-native-inappbrowser-reborn": "^3.6.3", "react-native-safe-area-context": "^4.3.1", "react-native-screens": "^3.13.1", - "react-native-securerandom": "^1.0.0", "react-native-web": "^0.17.7", "ucans": "0.9.1" }, diff --git a/src/platform/polyfills.native.ts b/src/platform/polyfills.native.ts index b4d38f04..0c9f3058 100644 --- a/src/platform/polyfills.native.ts +++ b/src/platform/polyfills.native.ts @@ -1,7 +1,17 @@ -import {generateSecureRandom} from 'react-native-securerandom' +// import {generateSecureRandom} from 'react-native-securerandom' +import {NativeModules} from 'react-native' +const {AppSecureRandomModule} = NativeModules +import {toByteArray} from 'base64-js' import crypto from 'msrcrypto' import '@zxing/text-encoding' // TextEncoder / TextDecoder +async function generateSecureRandom(bytes: number) { + console.log('a') + return toByteArray( + await AppSecureRandomModule.generateSecureRandomAsBase64(bytes), + ) +} + export const whenWebCrypto = new Promise(async (resolve, reject) => { try { const bytes = await generateSecureRandom(48) diff --git a/yarn.lock b/yarn.lock index b0eb1149..4de0d188 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3838,7 +3838,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@*, base64-js@^1.1.2, base64-js@^1.3.1, base64-js@^1.5.1: +base64-js@^1.1.2, base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -11059,13 +11059,6 @@ react-native-screens@^3.13.1: react-freeze "^1.0.0" warn-once "^0.1.0" -react-native-securerandom@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/react-native-securerandom/-/react-native-securerandom-1.0.0.tgz#1cff2f727c90c9ec3318b42dbf825a628b53b49b" - integrity sha512-lnhcsWloFzMN/HffyDBlh4VlqdhDH8uxEzUIH3aJPgC1PxV6OKZkvAk409EwsAhcmG/z3yZuVKegKpUr5IM9ug== - dependencies: - base64-js "*" - react-native-web@^0.17.7: version "0.17.7" resolved "https://registry.yarnpkg.com/react-native-web/-/react-native-web-0.17.7.tgz#038899dbc94467a0ca0be214b88a30e0c117b176"