简体   繁体   English

使用python的硬件rng

[英]using the hardware rng from python

Are there any ready made libraries so that the intel hardware prng (rdrand) can be used by numpy programs to fill buffers of random numbers? 是否有任何现成的库,以便numpy程序可以使用intel硬件prng(rdrand)来填充随机数的缓冲区?

Failing this can someone point me in the right direction for some C code that I could adapt or use (I use CPython and Cython with numpy so the bare minimum wrapper shd be enough). 如果失败了,有人会指出我正确的方向,我可以适应或使用一些C代码(我使用CPython和Cython与numpy,所以最小的包装器就足够了)。

The random generators I want are uniform random numbers between [0,1). 我想要的随机生成器是[0,1]之间的均匀随机数。

This code will use /dev/urandom (Unix) or CryptGenRandom APIs (Windows). 此代码将使用/ dev / urandom(Unix)或CryptGenRandom API(Windows)。 Which RNG is used, hardware or software, is dependent on the operating system. 使用哪种RNG,硬件或软件,取决于操作系统。

If you want to control exactly which generator is used, you must query it through its hardware driver or library. 如果要准确控制使用的生成器,则必须通过其硬件驱动程序或库进行查询。 When you have the random bits as a string, you proceeed similarly to this code, using np.fromstring. 当您将随机位作为字符串时,您使用np.fromstring进行类似于此代码的操作。

Normally we can trust the operating system to use the best entropy sources for its cryptographic services, including the random bit generator. 通常,我们可以信任操作系统为其加密服务使用最佳熵源,包括随机位生成器。 If there is a hardware RNG it is likely to be used, usually combination with other entropy sources. 如果存在硬件RNG,则可能会使用它,通常与其他熵源组合使用。

import os
import numpy as np

def cryptorand(n):
    a = np.fromstring(os.urandom(n*4), dtype=np.uint32) >> 5
    b = np.fromstring(os.urandom(n*4), dtype=np.uint32) >> 6
    return (a * 67108864.0 + b) / 9007199254740992.0

Here is the distribution of 1,000,000 random deviates generated with this method on Mac OS X. As you can see it is quite uniform on [0,1): 以下是在Mac OS X上使用此方法生成的1,000,000个随机偏差的分布。正如您所看到的,它在[0,1]上非常均匀:

在此输入图像描述

If you need really strong cryptographic random deviates, you can use /dev/random instead of /dev/urandom. 如果您需要非常强大的加密随机偏差,可以使用/ dev / random而不是/ dev / urandom。 This applies only to Unix-like systems, not Windows: 这仅适用于类Unix系统,而不适用于Windows:

import numpy as np

def cryptorand(n):
    with open('/dev/random','rb') as rnd:
        a = np.fromstring(rnd.read(n*4), dtype=np.uint32) >> 5
        b = np.fromstring(rnd.read(n*4), dtype=np.uint32) >> 6
        return (a * 67108864.0 + b) / 9007199254740992.0

Note that this function might block, unlike the version that uses os.urandom as entropy source. 请注意,与使用os.urandom作为熵源的版本不同,此函数可能会阻塞。

(Edit1: Updated normalization to equate that of NumPy) (Edit1:更新了标准化以等同于NumPy的标准化)

Edit 2: The comments indicates the reason for the question was speed, not cryptographic strength. 编辑2:评论表明问题的原因是速度,而不是加密强度。 The purpose of hardware RNG is not speed but strength, so it makes the question invalid. 硬件RNG的目的不是速度而是强度,因此它使问题无效。 However, a fast and good PRNG which can be an alternative to the Mersenne Twister is George Marsaglia's multiply-with-carry generator. 然而,一个快速和良好的PRNG可以替代Mersenne Twister是George Marsaglia的乘法携带发生器。 Here is a simple implementation in Cython: 这是Cython中的一个简单实现:

import numpy as np
cimport numpy as cnp

cdef cnp.uint32_t gw = 152315241 # any number except 0 or 0x464fffff
cdef cnp.uint32_t gz = 273283728 # any number except 0 or 0x9068ffff

def rand(cnp.intp_t n):
    """Generate n random numbers using George Marsaglia's 
    multiply-with-carry method."""
    global gw, gz
    cdef cnp.uint32_t w, z, a, b
    cdef cnp.intp_t i
    cdef cnp.ndarray x = cnp.PyArray_SimpleNew(1, &n, cnp.NPY_FLOAT64)
    cdef cnp.float64_t *r = <cnp.float64_t*> cnp.PyArray_DATA(x)
    w,z = gw,gz
    for i in range(n): 
        z = 36969 * (z & 65535) + (z >> 16)
        w = 18000 * (w & 65535) + (w >> 16)
        a = (z << 16) + w
        z = 36969 * (z & 65535) + (z >> 16)
        w = 18000 * (w & 65535) + (w >> 16)
        b = (z << 16) + w
        r[i] = (a * 67108864.0 + b) / 9007199254740992.0
    gw,gz = w,z
    return x

Beware that neither Mersenne Twister nor multiply-with-carry have cryptographic strength. 请注意,Mersenne Twister和multiply-with-carry都没有加密强度。

There is a paper available here ( http://iopscience.iop.org/article/10.3847/1538-4357/aa7ede/meta;jsessionid=A9DA9DDB925E6522D058F3CEEC7D0B21.ip-10-40-2-120 ) and (non-paywalled version) here ( https://arxiv.org/abs/1707.02212 ) that describes how to use Intel Secure Key, which is a cryptographically secure random number generator implemented on-chip. 这里有一篇论文( http://iopscience.iop.org/article/10.3847/1538-4357/aa7ede/meta;jsessionid=A9DA9DDB925E6522D058F3CEEC7D0B21.ip-10-40-2-120 )和(非支付版本)这里( https://arxiv.org/abs/1707.02212 )描述了如何使用英特尔安全密钥,这是一个在芯片上实现的加密安全随机数发生器。 It can be accessed via RdRand and RdSeed instructions. 它可以通过RdRand和RdSeed指令访问。

But the author seems to say you should go for implementing it in C/C++ instead of Python. 但是作者似乎说你应该用C / C ++而不是Python来实现它。 The rdrand python module runs about 100x slower than the Python default random number generator, and about 1000x slower than the one in Numpy (paper section 5.2). rdrand python模块运行速度比Python默认随机数生成器慢大约100倍,比Numpy慢一倍(文章5.2节)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM