|
1 | | -// This file is based on code from the react-native-get-random-values repository |
| 1 | +// This file is based on code from the fast-base64-decode repository. |
| 2 | +// Source: https://github.com/LinusU/fast-base64-decode/blob/master/index.js |
| 3 | +// Modifications: |
| 4 | +// - None |
| 5 | + |
| 6 | +const lookup = new Uint8Array([ |
| 7 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 8 | + 0, 0, 0, 0, 62, 0, 62, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, |
| 9 | + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, |
| 10 | + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 |
| 11 | +]); |
| 12 | + |
| 13 | +function base64Decode(source, target) { |
| 14 | + const sourceLength = source.length; |
| 15 | + const paddingLength = source[sourceLength - 2] === '=' ? 2 : source[sourceLength - 1] === '=' ? 1 : 0; |
| 16 | + const baseLength = (sourceLength - paddingLength) & 0xfffffffc; |
| 17 | + |
| 18 | + let tmp; |
| 19 | + let i = 0; |
| 20 | + let byteIndex = 0; |
| 21 | + |
| 22 | + for (; i < baseLength; i += 4) { |
| 23 | + tmp = |
| 24 | + (lookup[source.charCodeAt(i)] << 18) | |
| 25 | + (lookup[source.charCodeAt(i + 1)] << 12) | |
| 26 | + (lookup[source.charCodeAt(i + 2)] << 6) | |
| 27 | + lookup[source.charCodeAt(i + 3)]; |
| 28 | + |
| 29 | + target[byteIndex++] = (tmp >> 16) & 0xff; |
| 30 | + target[byteIndex++] = (tmp >> 8) & 0xff; |
| 31 | + target[byteIndex++] = tmp & 0xff; |
| 32 | + } |
| 33 | + |
| 34 | + if (paddingLength === 1) { |
| 35 | + tmp = |
| 36 | + (lookup[source.charCodeAt(i)] << 10) | |
| 37 | + (lookup[source.charCodeAt(i + 1)] << 4) | |
| 38 | + (lookup[source.charCodeAt(i + 2)] >> 2); |
| 39 | + |
| 40 | + target[byteIndex++] = (tmp >> 8) & 0xff; |
| 41 | + target[byteIndex++] = tmp & 0xff; |
| 42 | + } |
| 43 | + |
| 44 | + if (paddingLength === 2) { |
| 45 | + tmp = (lookup[source.charCodeAt(i)] << 2) | (lookup[source.charCodeAt(i + 1)] >> 4); |
| 46 | + |
| 47 | + target[byteIndex++] = tmp & 0xff; |
| 48 | + } |
| 49 | +} |
| 50 | + |
| 51 | +// This file is based on code from the react-native-get-random-values repository. |
2 | 52 | // Source: https://github.com/LinusU/react-native-get-random-values/blob/modern/index.js |
3 | 53 | // Modifications: |
4 | 54 | // - Instead of applying to all global references of crypto, provide a ponyfill export. |
| 55 | +// - Instead of having a package dependency on fast-base64-decode, copy the code here. There are issues with injecting a vendor file in the rollup config. |
5 | 56 |
|
6 | | -const base64Decode = require('fast-base64-decode') |
7 | | -const { NativeModules } = require('react-native') |
| 57 | +const { NativeModules } = require('react-native'); |
8 | 58 |
|
9 | 59 | class TypeMismatchError extends Error {} |
10 | 60 | class QuotaExceededError extends Error {} |
11 | 61 |
|
12 | | -let warned = false |
13 | | -function insecureRandomValues (array) { |
| 62 | +let warned = false; |
| 63 | +function insecureRandomValues(array) { |
14 | 64 | if (!warned) { |
15 | | - console.warn('Using an insecure random number generator, this should only happen when running in a debugger without support for crypto.getRandomValues') |
16 | | - warned = true |
| 65 | + console.warn( |
| 66 | + 'Using an insecure random number generator, this should only happen when running in a debugger without support for crypto.getRandomValues' |
| 67 | + ); |
| 68 | + warned = true; |
17 | 69 | } |
18 | 70 |
|
19 | 71 | for (let i = 0, r; i < array.length; i++) { |
20 | | - if ((i & 0x03) === 0) r = Math.random() * 0x100000000 |
21 | | - array[i] = (r >>> ((i & 0x03) << 3)) & 0xff |
| 72 | + if ((i & 0x03) === 0) r = Math.random() * 0x100000000; |
| 73 | + array[i] = (r >>> ((i & 0x03) << 3)) & 0xff; |
22 | 74 | } |
23 | 75 |
|
24 | | - return array |
| 76 | + return array; |
25 | 77 | } |
26 | 78 |
|
27 | 79 | /** |
28 | 80 | * @param {number} byteLength |
29 | 81 | * @returns {string} |
30 | 82 | */ |
31 | | -function getRandomBase64 (byteLength) { |
| 83 | +function getRandomBase64(byteLength) { |
32 | 84 | if (NativeModules.RNGetRandomValues) { |
33 | | - return NativeModules.RNGetRandomValues.getRandomBase64(byteLength) |
| 85 | + return NativeModules.RNGetRandomValues.getRandomBase64(byteLength); |
34 | 86 | } else if (NativeModules.ExpoRandom) { |
35 | 87 | // Expo SDK 41-44 |
36 | | - return NativeModules.ExpoRandom.getRandomBase64String(byteLength) |
| 88 | + return NativeModules.ExpoRandom.getRandomBase64String(byteLength); |
37 | 89 | } else if (global.ExpoModules) { |
38 | 90 | // Expo SDK 45+ |
39 | 91 | return global.ExpoModules.ExpoRandom.getRandomBase64String(byteLength); |
40 | 92 | } else { |
41 | | - throw new Error('Native module not found') |
| 93 | + throw new Error('Native module not found'); |
42 | 94 | } |
43 | 95 | } |
44 | 96 |
|
45 | 97 | /** |
46 | 98 | * @param {Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Uint8ClampedArray} array |
47 | 99 | */ |
48 | | -function getRandomValues (array) { |
49 | | - if (!(array instanceof Int8Array || array instanceof Uint8Array || array instanceof Int16Array || array instanceof Uint16Array || array instanceof Int32Array || array instanceof Uint32Array || array instanceof Uint8ClampedArray)) { |
50 | | - throw new TypeMismatchError('Expected an integer array') |
| 100 | +function getRandomValues(array) { |
| 101 | + if ( |
| 102 | + !( |
| 103 | + array instanceof Int8Array || |
| 104 | + array instanceof Uint8Array || |
| 105 | + array instanceof Int16Array || |
| 106 | + array instanceof Uint16Array || |
| 107 | + array instanceof Int32Array || |
| 108 | + array instanceof Uint32Array || |
| 109 | + array instanceof Uint8ClampedArray |
| 110 | + ) |
| 111 | + ) { |
| 112 | + throw new TypeMismatchError('Expected an integer array'); |
51 | 113 | } |
52 | 114 |
|
53 | 115 | if (array.byteLength > 65536) { |
54 | | - throw new QuotaExceededError('Can only request a maximum of 65536 bytes') |
| 116 | + throw new QuotaExceededError('Can only request a maximum of 65536 bytes'); |
55 | 117 | } |
56 | 118 |
|
57 | 119 | // Expo SDK 48+ |
58 | | - if (global.expo && global.expo.modules && global.expo.modules.ExpoCrypto && global.expo.modules.ExpoCrypto.getRandomValues) { |
| 120 | + if ( |
| 121 | + global.expo && |
| 122 | + global.expo.modules && |
| 123 | + global.expo.modules.ExpoCrypto && |
| 124 | + global.expo.modules.ExpoCrypto.getRandomValues |
| 125 | + ) { |
59 | 126 | // ExpoCrypto.getRandomValues doesn't return the array |
60 | | - global.expo.modules.ExpoCrypto.getRandomValues(array) |
61 | | - return array |
| 127 | + global.expo.modules.ExpoCrypto.getRandomValues(array); |
| 128 | + return array; |
62 | 129 | } |
63 | 130 |
|
64 | 131 | // Calling getRandomBase64 in remote debugging mode leads to the error |
65 | 132 | // "Calling synchronous methods on native modules is not supported in Chrome". |
66 | 133 | // So in that specific case we fall back to just using Math.random(). |
67 | 134 | if (isRemoteDebuggingInChrome()) { |
68 | | - return insecureRandomValues(array) |
| 135 | + return insecureRandomValues(array); |
69 | 136 | } |
70 | 137 |
|
71 | | - base64Decode(getRandomBase64(array.byteLength), new Uint8Array(array.buffer, array.byteOffset, array.byteLength)) |
| 138 | + base64Decode(getRandomBase64(array.byteLength), new Uint8Array(array.buffer, array.byteOffset, array.byteLength)); |
72 | 139 |
|
73 | | - return array |
| 140 | + return array; |
74 | 141 | } |
75 | 142 |
|
76 | | -function isRemoteDebuggingInChrome () { |
| 143 | +function isRemoteDebuggingInChrome() { |
77 | 144 | // Remote debugging in Chrome is not supported in bridgeless |
78 | 145 | if ('RN$Bridgeless' in global && RN$Bridgeless === true) { |
79 | | - return false |
| 146 | + return false; |
80 | 147 | } |
81 | 148 |
|
82 | | - return __DEV__ && typeof global.nativeCallSyncHook === 'undefined' |
| 149 | + return __DEV__ && typeof global.nativeCallSyncHook === 'undefined'; |
83 | 150 | } |
84 | 151 |
|
85 | 152 | export default { getRandomValues }; |
0 commit comments