LinusU / react-native-get-random-values

A small implementation of `getRandomValues` for React Native
MIT License
350 stars 48 forks source link

`expo-random` deprecated #41

Closed SimenB closed 1 year ago

SimenB commented 1 year ago

See https://blog.expo.dev/expo-sdk-48-ccb8302e231

expo-random merged into expo-crypto. expo-crypto now supports getRandomValues, randomUUID (UUID v4), and digest functions, which are compliant with the Web Crypto API equivalents. With this change,expo-random has become redundant and is now deprecated.

MortadhaFadhlaoui commented 1 year ago

This patch work for me react-native-get-random-values+1.8.0.patch

UPDATED

diff --git a/node_modules/react-native-get-random-values/index.js b/node_modules/react-native-get-random-values/index.js
index 7b5e313..5e332dc 100644
--- a/node_modules/react-native-get-random-values/index.js
+++ b/node_modules/react-native-get-random-values/index.js
@@ -1,5 +1,7 @@
 const base64Decode = require('fast-base64-decode')
+const { fromByteArray } = require('base64-js');
 const { NativeModules } = require('react-native')
+const { NativeModulesProxy } = require('expo-modules-core')

 class TypeMismatchError extends Error {}
 class QuotaExceededError extends Error {}
@@ -23,15 +25,31 @@ function insecureRandomValues (array) {
  * @param {number} byteLength
  * @returns {string}
  */
-function getRandomBase64 (byteLength) {
+ async function getRandomBase64 (byteLength) {
   if (NativeModules.RNGetRandomValues) {
     return NativeModules.RNGetRandomValues.getRandomBase64(byteLength)
+  } else if(NativeModulesProxy.ExpoCrypto) {
+    return await NativeModulesProxy.ExpoCrypto.getRandomBase64StringAsync(byteLength);
   } else if (NativeModules.ExpoRandom) {
     // Expo SDK 41-44
     return NativeModules.ExpoRandom.getRandomBase64String(byteLength)
-  } else if (global.ExpoModules) {
-    // Expo SDK 45+
-    return global.ExpoModules.ExpoRandom.getRandomBase64String(byteLength);
+  } else if (global.expo.modules) {
+      if (global.expo.modules.ExpoRandom){
+      // Expo SDK 45+
+      return global.expo.modules.ExpoRandom.getRandomBase64String(byteLength);
+      } else if (global.expo.modules.ExpoCrypto){
+        // Expo SDK 48+
+        if (global.expo.modules.ExpoCrypto.getRandomBytes){
+          const uint8Array = global.expo.modules.ExpoCrypto.getRandomBytes(byteLength)
+          return fromByteArray(uint8Array)
+        } else if (global.expo.modules.ExpoCrypto.getRandomBase64String){
+          return global.expo.modules.ExpoCrypto.getRandomBase64String(byteLength)
+        } else {
+          throw new Error(`functions getRandomBase64String, getRandomBytes doesn't exist`)
+        }
+      } else {
+        throw new Error(`ExpoCrypto doesn't exist`)
+      }
   } else {
     throw new Error('Native module not found')
   }

wdyt ?

pvinis commented 1 year ago

based on https://docs.expo.dev/versions/latest/sdk/crypto/, i dont think this function exists?

MortadhaFadhlaoui commented 1 year ago

Yes, you are right but when I console.log(global.expo.modules.ExpoCrypto) I got this {"digest": [Function digest], "digestString": [Function digestString], "digestStringAsync": [Function digestStringAsync], "getRandomBase64String": [Function getRandomBase64String], "getRandomBase64StringAsync": [Function getRandomBase64StringAsync], "getRandomValues": [Function getRandomValues], "randomUUID": [Function randomUUID]}

pvinis commented 1 year ago

indeed. i see that there are private kotlin and swift functions. cool! ill try it now.

LinusU commented 1 year ago

Fixed in 🚢 1.9.0 / 2023-05-18

TobyEalden commented 1 year ago

I'm still getting this error because ExpoRandom is still being accessed here: https://github.com/LinusU/react-native-get-random-values/blob/master/index.js#L34.

Running with 1.9.0 on Android via Expo on SDK 48.0.0

Screenshot_20230612-112445

LinusU commented 1 year ago

@TobyEalden could you try running the following code directly in your application?

global.expo.modules.ExpoCrypto.getRandomValues(array)

If it doesn't work, it's probably some setup problem with Expo. There is some discussion around this here: https://github.com/expo/expo/issues/17270

TobyEalden commented 1 year ago

@LinusU thanks for the response.

It looks like global.expo.modules.ExpoCrypto.getRandomValues is undefined in my application. Weird since it's a new (up-to-date) installation of Expo.

I'll look into the Expo issue you mentioned.

lennertcl commented 1 year ago

Should this be fixed now? Because I am still getting this error with 1.9.0 and Expo 48:

TypeError: Cannot read property 'getRandomBase64String' of undefined

I have also tried using polyfilWebCrypto from expo-standard-web-crypto, however then I get this error:

Error: Cannot find native module 'ExpoCrypto', js engine: hermes

I think the second problem might be due to the fact that I need to use expo-dev-client, because I am trying to use MongoDB Realm. If I do not use the dev client I get this error:

Error: Could not find the Realm binary. Please consult our troubleshooting guide: https://www.mongodb.com/docs/realm-sdks/js/latest/#md:troubleshooting-missing-binary, js engine: hermes

And MongoDB Realm and BSON specifically suggest this library:

BSON: For React Native please polyfill crypto.getRandomValues, e.g. using: https://www.npmjs.com/package/react-native-get-random-values.

I tried all the stuff from the Expo issue you mentioned, but nothing seems to work. Anybody found a good fix yet?