1import { toByteArray } from 'base64-js'; 2import { UnavailabilityError } from 'expo-modules-core'; 3 4import ExpoRandom from './ExpoRandom'; 5 6function assertByteCount(value: any, methodName: string): void { 7 if ( 8 typeof value !== 'number' || 9 isNaN(value) || 10 Math.floor(value) < 0 || 11 Math.floor(value) > 1024 12 ) { 13 throw new TypeError( 14 `expo-random: ${methodName}(${value}) expected a valid number from range 0...1024` 15 ); 16 } 17} 18 19// @needsAudit 20/** 21 * Generates completely random bytes using native implementations. The `byteCount` property 22 * is a `number` indicating the number of bytes to generate in the form of a `Uint8Array`. 23 * Falls back to `Math.random` during development to prevent issues with React Native Debugger. 24 * @param byteCount - A number within the range from `0` to `1024`. Anything else will throw a `TypeError`. 25 * @return An array of random bytes with the same length as the `byteCount`. 26 */ 27export function getRandomBytes(byteCount: number): Uint8Array { 28 assertByteCount(byteCount, 'getRandomBytes'); 29 const validByteCount = Math.floor(byteCount); 30 if (__DEV__) { 31 if (!global.nativeCallSyncHook || global.__REMOTEDEV__) { 32 // remote javascript debugging is enabled 33 const array = new Uint8Array(validByteCount); 34 for (let i = 0; i < validByteCount; i++) { 35 array[i] = Math.floor(Math.random() * 256); 36 } 37 return array; 38 } 39 } 40 if (ExpoRandom.getRandomBytes) { 41 return ExpoRandom.getRandomBytes(validByteCount); 42 } else if (ExpoRandom.getRandomBase64String) { 43 const base64 = ExpoRandom.getRandomBase64String(validByteCount); 44 return toByteArray(base64); 45 } else { 46 throw new UnavailabilityError('expo-random', 'getRandomBytes'); 47 } 48} 49 50// @needsAudit 51/** 52 * Generates completely random bytes using native implementations. The `byteCount` property 53 * is a `number` indicating the number of bytes to generate in the form of a `Uint8Array`. 54 * @param byteCount - A number within the range from `0` to `1024`. Anything else will throw a `TypeError`. 55 * @return A promise that fulfills with an array of random bytes with the same length as the `byteCount`. 56 */ 57export async function getRandomBytesAsync(byteCount: number): Promise<Uint8Array> { 58 assertByteCount(byteCount, 'getRandomBytesAsync'); 59 const validByteCount = Math.floor(byteCount); 60 if (ExpoRandom.getRandomBytesAsync) { 61 return await ExpoRandom.getRandomBytesAsync(validByteCount); 62 } else if (ExpoRandom.getRandomBase64StringAsync) { 63 const base64 = await ExpoRandom.getRandomBase64StringAsync(validByteCount); 64 return toByteArray(base64); 65 } else { 66 throw new UnavailabilityError('expo-random', 'getRandomBytesAsync'); 67 } 68} 69