10

/dev/random のランダム性をテストする Python スクリプトを作成しようとしていますが、数値を取得できません。私のコードは次のようになります

with open("/dev/random", 'rb') as file:
     print f.read(10)

/dev/random から 10 バイトを出力すると思われますが、数字の代わりに奇妙な文字 (非標準の文字と数字なし) を出力します。私が間違っていることは何か分かりますか?

4

4 に答える 4

16

Python にはこのための組み込み関数があります (他の OS でも適切なメソッドを使用します)...

import os
print os.urandom(10)
# '\xf1\x11xJOl\xab\xcc\xf0\xfd'

http://docs.python.org/2/library/os.html#os.urandomのドキュメントから

この関数は、OS 固有の乱数ソースから乱数バイトを返します。返されるデータは、暗号化アプリケーションにとって十分に予測不可能である必要がありますが、その正確な品質は OS の実装によって異なります。UNIX ライクなシステムでは、これは /dev/urandom を照会し、Windows では CryptGenRandom を使用します。乱数ソースが見つからない場合、NotImplementedError が発生します。

これらのバイトを数値にしたい場合は、次のように変換することで実行できます。

>>> rand = os.urandom(10)
>>> int(binascii.hexlify(rand), 16)
1138412584848598544216317L

または Python 2 を使用:

>>> int(rand.encode('hex'), 16)
1138412584848598544216317L

とはわずかに異なるため/dev/random、違いが重要な場合は、/dev/urandom既存の.read()op を使用して変換を行うことができます。int

于 2013-02-06T02:57:53.830 に答える
9

10 バイトを取得しています。Python はそれらを自動的に数値に変換しません。

バイトを 4 の倍数で取得し、それらを 32 ビットの符号なし整数に変換し、必要に応じてスケーリングすることをお勧めします。

EDIT:古いコードはアイデアを示していましたが、機能にうまく分割されていませんでした。これは基本的な考え方は同じですが、便利に関数にパッケージ化されています。

import os
import struct

_random_source = open("/dev/random", "rb")

def random_bytes(len):
    return _random_source.read(len)

def unpack_uint32(bytes):
    tup = struct.unpack("I", bytes)
    return tup[0]

UINT32_MAX = 0xffffffff
def randint(low, high):
    """
    Return a random integer in the range [low, high], including
    both endpoints.
    """
    n = (high - low) + 1
    assert n >= 1
    scale_factor = n / float(UINT32_MAX + 1)
    random_uint32 = unpack_uint32(random_bytes(4))
    result = int(scale_factor * random_uint32) + low
    return result

def randint_gen(low, high, count):
    """
    Generator that yields random integers in the range [low, high],
    including both endpoints.
    """
    n = (high - low) + 1
    assert n >= 1
    scale_factor = n / float(UINT32_MAX + 1)
    for _ in range(count):
        random_uint32 = unpack_uint32(random_bytes(4))
        result = int(scale_factor * random_uint32) + low
        yield result

if __name__ == "__main__":
    # roll 3 dice individually with randint()
    result = [randint(1, 6) for _ in range(3)]
    print(result)

    # roll 3 dice more efficiently with randint_gen()
    print(list(randint_gen(1, 6, 3)))
于 2013-02-06T03:12:20.970 に答える
1

ランダムな文字を出力しているので、ord()関数を使用してそれらを int に変換するだけです。何かのようなもの:

with open("/dev/random", 'rb') as file: print [ord(x) for x in file.read(10)]

これにより、0 から 255 までの 10 個のランダムな int のリストが出力されます (取得した: [117, 211, 225, 24, 134, 145, 51, 234, 153, 89])。

于 2013-02-06T03:11:45.977 に答える