ラズパイが出力する乱数のエントロピー(どのくらいバラバラかを表す値)を推定してみました。
- 3つの乱数生成方法について確認
- 2つのOSバージョンで確認
- 1MB出力にかかる時間も確認
確認した乱数3種
- /dev/hwrng
- ラズパイに搭載されているハードウェア乱数生成器の出力
- /dev/random
- 疑似乱数生成機能(高品質)による出力
- /dev/urandom
- 疑似乱数生成機能(高速)による出力
確認したOSバージョン
/dev/randomの動作が Linuxカーネルのバージョン5.6以降は変わっているとのことなので、以下の2つのOSで確認しました。
- Raspbian 10 Buster (Linux kernel 4.19)
- Raspberry Pi OS 12 Bookworm (Linux kernel 6.6)
結果
OSバージョン | hwrng | random | urandom |
---|---|---|---|
Raspbian 10 Buster Linux kernel 4.19 |
15.0s (6.638) |
37.1s (7.218) |
2.6s (7.163) |
Raspberry Pi OS 12 Bookworm Linux kernel 6.6 |
14.9s (7.334) |
2.0s (7.207) |
2.0s (7.241) |
- 各セルの上段は1MB出力の所要時間、下段は出力データの8bit当たりのエントロピー(8に近い方がバラバラ)
- Bookwormでのrandomの実行時は、CRNGは準備済となった後でブロックは発生していないと思われる
- /dev/hwrngの出力がOSのエントロピープールに使われているかどうかは不明(特に設定はしていない)
分かったこと
- いずれも優秀
- /dev/randomは、確かに動きが変わっている
確認方法
処理時間の確認方法
administrator@raspberrypi:~ $ sudo dd if=/dev/hwrng of=/dev/null bs=1 count=1000000
1000000+0 records in
1000000+0 records out
1000000 bytes (1.0 MB, 977 KiB) copied, 14.689 s, 68.1 kB/s
administrator@raspberrypi:~ $ sudo dd if=/dev/random of=/dev/null bs=1 count=1000000
1000000+0 records in
1000000+0 records out
1000000 bytes (1.0 MB, 977 KiB) copied, 1.9735 s, 507 kB/s
administrator@raspberrypi:~ $ sudo dd if=/dev/urandom of=/dev/null bs=1 count=1000000
1000000+0 records in
1000000+0 records out
1000000 bytes (1.0 MB, 977 KiB) copied, 1.93535 s, 517 kB/s
administrator@raspberrypi:~ $
エントロピーの確認方法
NIST SP800-90B に記述されているエントロピー推定方法をPythonで実行できるようにしたパッケージsp800_90b
を利用しました。
1. ラズパイにDockerをインストール
Docker公式の Install using the convenience scriptのぺージで紹介されている以下コマンドでDockerをインストール
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
また、sudoなしでDockerコマンド実行できるようにするため、以下ページを参考にしてDockerグループにユーザを追加
2. 必要なパッケージをインストールしたDockerコンテナを起動
以下のDockerfileを作成
FROM python:3
RUN apt update && apt install -y \
libbz2-dev \
libdivsufsort-dev \
build-essential \
&& rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir sp800-90b
WORKDIR /mnt
CMD ["bash"]
Dockerfileからイメージをビルドする
docker image build -t my-sp800_90b:latest -f Dockerfile .
コンテナを起動
docker run --rm -it -v {ホストのデータ格納場所}:/mnt my-sp800_90b
3. pythonコンソールで読み込んだファイルのエントロピーを出力
>>> import sp800_90b
>>> f = open('/mnt/data_by_hwrng.bin','rb')
>>> r = f.read()
>>> rd = sp800_90b.Data(r)
>>> rd.h_initial()
7.333765872584084
>>> f = open('/mnt/data_by_random.bin','rb')
>>> r = f.read()
>>> rd = sp800_90b.Data(r)
>>> rd.h_initial()
7.2074744569771845
>>> f = open('/mnt/data_by_urandom.bin','rb')
>>> r = f.read()
>>> rd = sp800_90b.Data(r)
>>> rd.h_initial()
7.240992233664618
>>>
以上です。