簡體   English   中英

使用python的硬件rng

[英]using the hardware rng from python

是否有任何現成的庫,以便numpy程序可以使用intel硬件prng(rdrand)來填充隨機數的緩沖區?

如果失敗了,有人會指出我正確的方向,我可以適應或使用一些C代碼(我使用CPython和Cython與numpy,所以最小的包裝器就足夠了)。

我想要的隨機生成器是[0,1]之間的均勻隨機數。

此代碼將使用/ dev / urandom(Unix)或CryptGenRandom API(Windows)。 使用哪種RNG,硬件或軟件,取決於操作系統。

如果要准確控制使用的生成器,則必須通過其硬件驅動程序或庫進行查詢。 當您將隨機位作為字符串時,您使用np.fromstring進行類似於此代碼的操作。

通常,我們可以信任操作系統為其加密服務使用最佳熵源,包括隨機位生成器。 如果存在硬件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

以下是在Mac OS X上使用此方法生成的1,000,000個隨機偏差的分布。正如您所看到的,它在[0,1]上非常均勻:

在此輸入圖像描述

如果您需要非常強大的加密隨機偏差,可以使用/ dev / random而不是/ dev / urandom。 這僅適用於類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

請注意,與使用os.urandom作為熵源的版本不同,此函數可能會阻塞。

(Edit1:更新了標准化以等同於NumPy的標准化)

編輯2:評論表明問題的原因是速度,而不是加密強度。 硬件RNG的目的不是速度而是強度,因此它使問題無效。 然而,一個快速和良好的PRNG可以替代Mersenne Twister是George Marsaglia的乘法攜帶發生器。 這是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

請注意,Mersenne Twister和multiply-with-carry都沒有加密強度。

這里有一篇論文( http://iopscience.iop.org/article/10.3847/1538-4357/aa7ede/meta;jsessionid=A9DA9DDB925E6522D058F3CEEC7D0B21.ip-10-40-2-120 )和(非支付版本)這里( https://arxiv.org/abs/1707.02212 )描述了如何使用英特爾安全密鑰,這是一個在芯片上實現的加密安全隨機數發生器。 它可以通過RdRand和RdSeed指令訪問。

但是作者似乎說你應該用C / C ++而不是Python來實現它。 rdrand python模塊運行速度比Python默認隨機數生成器慢大約100倍,比Numpy慢一倍(文章5.2節)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM