Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/234.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android React本地同步安全随机数生成_Android_Ios_React Native_Asynchronous_Random - Fatal编程技术网

Android React本地同步安全随机数生成

Android React本地同步安全随机数生成,android,ios,react-native,asynchronous,random,Android,Ios,React Native,Asynchronous,Random,我正在尝试在React本地项目中生成密钥对。密钥对生成工具依赖于crypto模块的随机字节生成,该模块使用随机字节值生成指定长度的缓冲区 为了在React Native中使用crypto模块,必须对其进行Browserialized,Browserialized random number generator如下所示: 以下是关键部分: var crypto = global.crypto || global.msCrypto if (crypto && crypto.get

我正在尝试在React本地项目中生成密钥对。密钥对生成工具依赖于
crypto
模块的随机字节生成,该模块使用随机字节值生成指定长度的缓冲区

为了在React Native中使用
crypto
模块,必须对其进行Browserialized,Browserialized random number generator如下所示:

以下是关键部分:

var crypto = global.crypto || global.msCrypto

if (crypto && crypto.getRandomValues) {
  module.exports = randomBytes
} else {
  module.exports = oldBrowser
}
事实上,使用Chrome调试应用程序时,一切正常,但在iOS的JavaScriptCore引擎上运行时,会调用
oldBrowser
方法,引发以下错误:

此浏览器不支持安全随机数生成 使用chrome、FireFox或Internet Explorer 11

因此,我试图找到随机字节生成的替代方法。我发现的一个模块是:

它使用设备的本机库生成一个随机数,并通过Obj-C/JS接口将其公开为本机响应。应该注意的是,这种方法只在iOS上有效,而且该库的作者还没有Android解决方案,但这是另一个时代的问题

这种方法可以工作,因为它可以生成随机字节,但它有一个主要缺点。React只支持Objective-C和JavaScript之间的异步接口,这意味着该方法异步返回其结果。最初的
randomBytes
方法是同步的,几乎所有依赖它的SDK都同步使用它。因此,如果我们使用异步版本,所有SDK都必须为其重写,包括所有依赖于以前是同步的方法的依赖项,现在不再是同步的

因此,我试图找到一种方法,使异步本机随机数生成器同步工作。有几个节点包可以做到这一点,其中最突出的是
deasync
,但是
deasync
依赖于一些无法浏览的核心节点模块,因此同步版本不起作用

或者,我尝试将其包装到一个方法中,该方法将设置信号量,调用异步生成器,并在while循环中等待信号量的值更改。该尝试失败,因为while循环阻止了回调的执行。这里是我尝试的一个近似值,其中对异步方法的调用已被替换为
setTimeout
,并且返回的随机数是4,由公平掷骰子决定

function testSynchronicity() {
  var isDone = false;
  setTimeout(function() {
    isDone = true;
  }, 1000); // set isDone to true after a second

  while (!isDone) {
    // do nothing
  }
  return 4;
};
由于这不起作用,我想我应该尝试一个完全不同的随机数生成器,而不使用依赖于
react native randombytes
模块的本机代码,并使用此模块进行JavaScript:

它在节点本身中运行良好,但在浏览它并尝试在React Native中运行第一个示例后,它抛出了一个错误,表示主对象不是构造函数。下面是示例的内容:

var RNG = require('./rng_react'); // rng_react is rng-js browserified
var rng = new RNG();
var randomValue = rng.random(0, 255, false);
因此,在这一点上,我有点不知所措,并将感谢任何帮助。谢谢


编辑:如果其他方法都失败了,那么这就是问题所在,但我认为这几乎超出了问题的目的

我找到了一个通常有效的答案。但是,它是不完美的,因为只有在应用程序启动期间不需要使用
randomBytes
方法时,它才能工作

我的解决方案涉及使用
react native randombytes
库。它依靠iOS内置的CSPRNG生成随机缓冲区,然后异步返回。为了支持同步响应,我扩展了moduel的
randomBytes
,在没有提供回调方法时不会抛出错误,而是使用斯坦福大学的JavaScript加密库生成随机“字”,正如它们被调用的那样,将它们转换为缓冲区,然后相应地对其进行修剪:

var sjcl = require('sjcl');
var sjclRandom = new sjcl.prng(10);

var RNRandomBytes = require('react-native').NativeModules.RNRandomBytes;

module.exports.randomBytes = function(length, cb) {

  if (!cb) {
    var size = length;
    var wordCount = Math.ceil(size * 0.25);
    var randomBytes = sjclRandom.randomWords(wordCount, 10);
    var hexString = sjcl.codec.hex.fromBits(randomBytes);
    hexString = hexString.substr(0, size * 2);

    return new Buffer(hexString, 'hex');
  }

  RNRandomBytes.randomBytes(length, function(err, base64String) {
    if (err) {
      cb(err);
    } else {
      cb(null, new Buffer(base64String, 'base64'));
    }
  });

};
关键是,为了使SJCL库具有足够的熵,需要对其进行适当的种子设定。因此,在启动时,我们使用异步CSPRNG功能为SJCL随机数生成器种子:

module.exports.randomBytes(4096, function(err, buffer) {
  var hexString = buffer.toString('hex');
  // we need to convert the hex string to bytes, or else SJCL assumes low entropy
  var stanfordSeed = sjcl.codec.hex.toBits(hexString);
  sjclRandom.addEntropy(stanfordSeed, 10, 'csprng');
});

因此,我们在React Native中有一个同步的
randomBytes
方法,只要我们有机会在需要同步功能之前至少异步调用它一次。

您的解决方案确实回答了这个问题,但似乎有点复杂。特别是,为什么不只使用SJCL

在我的例子中,我最终使用了,它只是Android和iOS本机调用的一个薄薄的包装。然后我做了这个来初始化SJCL的RNG:

const { generateSecureRandom } = require('react-native-securerandom');
const sjcl = require('lib/vendor/sjcl');

const randomBytes = await generateSecureRandom(1024/8);

let temp = [];
for (let n in randomBytes) {
    if (!randomBytes.hasOwnProperty(n)) continue;
    temp.push(randomBytes[n].toString(16));
}

const hexSeed = sjcl.codec.hex.toBits(temp.join(''));
sjcl.random.addEntropy(hexSeed, 1024, 'generateSecureRandom');

我相信在2016年1月,随机事件并不存在。它的第一次提交是2017年10月:)您重新定义了
randomBytes
,这并不意味着使用它的决定(
crypto&&crypto.getRandomValues
)会改变。那么你如何解决这个问题呢?为了通过测试,我不愿意简单地定义
crypto.getRandomValues
,因为我不知道它还能影响什么。以下是我正在努力解决的问题: