ethers-io / ethers.js

Complete Ethereum library and wallet implementation in JavaScript.
https://ethers.org/
MIT License
7.96k stars 1.85k forks source link

How to use a strong random source on Expo #612

Closed klaop57 closed 4 years ago

klaop57 commented 5 years ago

I'm trying to use ethers.js inside Expo, but whatever I do it keeps telling me:

WARNING: Missing strong random number source; using weak randomBytes

Is there any way to use a strong random source. I know expo has expo-random, but I see no clear way of making ethers.js use that.

ricmoo commented 5 years ago

I need to experiment with expo to figure out how to do this, but haven’t had a chance. I don’t use Expo myself, but this is a common question.

For most operations you do not need this though, as it is only used for Wallet.createRandom.

klaop57 commented 5 years ago

thanks for the quick response.

that's actually the thing i need, creating a random wallet! together with signing a transaction.

I've forked ether.js and am trying to get it to work. Will post here on success.

ricmoo commented 5 years ago

I see. In the meantime, you can implement createRandom easily. :)

function myCreateRandom() {
    const randomBytes = ... // Use expo's method to create 16 bytes of random data
    const mnemonic = ethers.utils.HDNode.entropyToMnemonic(randomBytes);
    return Wallet.fromMnemonic(mnemonic);
}

Which should get you up an running without needing to fork for now. :)

klaop57 commented 5 years ago

thanks, that worked 🎉

for the next person trying to get this to work:

import * as Random from 'expo-random';
import 'ethers/dist/shims.js';
import { ethers } from "ethers";

const createWallet = async () => {
  const randomBytes = await Random.getRandomBytesAsync(16);
  const mnemonic = ethers.utils.HDNode.entropyToMnemonic(randomBytes);
  const wallet = ethers.Wallet.fromMnemonic(mnemonic);
  return wallet;
}
ricmoo commented 5 years ago

Thanks! I’ll add that in the docs for Expo. :)

billtlee commented 5 years ago

In my case, I have

import * as Random from 'expo-random';
import 'ethers/dist/shims.js';
import { ethers } from 'ethers';

export async function generateMnemonics() {
  // return utils.HDNode.entropyToMnemonic(utils.randomBytes(16)).split(' ');
  const randomBytes = await Random.getRandomBytesAsync(16);
  return utils.HDNode.entropyToMnemonic(randomBytes).split(' ');
}

But I am still getting that warning

klaop57 commented 5 years ago

yes, i am also still getting the warning. But I think the unsafe random source is not used since this function takes in random bytes directly from the caller.

pcowgill commented 4 years ago

Here's a version of TweetNaCl.js for React Native that uses expo-random as the source of randomness https://github.com/rajtatata/react-native-expo-tweet-nacl

pcowgill commented 4 years ago

Thanks! I’ll add that in the docs for Expo. :)

@ricmoo Did this land anywhere in the v5 docs? Thanks!

ricmoo commented 4 years ago

I've referenced this loosely here and think the better way to support this is to use the crypto native package it mentions. Does that work in Expo?

ricmoo commented 4 years ago

I'm going to close this now, but if you'd like anything more added to the docs please continue discussing or re-open the issue.

Thanks! :)

Albert-Gao commented 3 years ago

@ricmoo expo indeed has a Crypto polyfill, but using this still gives me a warning

https://www.npmjs.com/package/expo-standard-web-crypto

image

ricmoo commented 3 years ago

@Albert-Gao The import statements in ESM will all occur before any code is executed except in files which also import the same library.

So in your above example, all 3 imports occur before the call to polyFillCrypto(). It is somewhat of a nuisance for polyfilling.

Can you verify the window.random is the secure random functions after the import? To see which shim took priority? I wonder if adding side-effects: true to the crypto shim will help the bundler?