1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

QRNGは“最強の乱数”なのか? ―暗号実務で本当に使える設計を考える―

1
Posted at

はじめに:「量子=最強」は半分正しい

「量子乱数生成器(QRNG)は予測不能で究極のランダム性を持つ」——物理学的にはこれは正解です。量子ビットが「0と1の重ね合わせ状態」から観測によって一方に確定する際のランダム性は、理論上いかなるアルゴリズムによっても事前予測が不可能です。

しかし、情報セキュリティの実装として「生の量子乱数をそのまま暗号鍵に使う」設計は、深刻な落とし穴を抱えています。

本記事では、IBM Quantum 実機(ibm_fez)を使った実測データを基に、QRNG の強みと限界を論理的に整理し、実務で採用すべき Hybrid(混合型)設計の必然性を解説します。

核心メッセージ
量子の「予測不能性」と暗号アルゴリズムの「数学的安全性保証」は、対立するものではなく補完し合うものです。その役割分担を正しく設計することが、量子時代のセキュリティ実装の最重要課題です。

1. 3つの乱数生成方式:内部構造と「決定性」

乱数生成の信頼性は、エントロピー(不規則性の源泉)の「起源」と、それを加工する「アルゴリズム」の組み合わせで決まります。

1.1 PRNG(疑似乱数):数式による拡張

  • メカニズム:完全に決定論的な数式に基づく
  • 実測 p 値8.72×10⁻²(理想値 0.5 から大きく外れる)
  • 致命的弱点:同じ Seed からは同じ列が再現される。Seed が漏洩した瞬間に全列が予測可能になる

1.2 TRNG(物理乱数):OS によるノイズ収集

  • メカニズム:CPU の熱雑音・割り込み等の物理現象をエントロピー源とする
  • 実測 p 値2.99×10⁻¹(安定しており、現行の標準的安全基盤)
  • 代表実装os.urandom()

1.3 QRNG(量子乱数):量子測定による確率崩壊

  • メカニズム:量子ビットが「0 と 1 の重ね合わせ」から「どちらか一方」へ確定する際の真のランダム性を利用
  • 実測 p 値4.13×10⁻¹(理論は最強だが、後述する物理的制約あり)

2. QRNG 単体運用の論理的限界

なぜ、生の量子乱数をそのまま暗号鍵として使ってはいけないのか。実機検証で明らかになった2つの決定的な課題があります。

課題 A:物理的バイアスと統計的品質の不安定性

実機 ibm_fez の raw データ検証では、p 値(0.4131)は良好でしたが、隣接相関(+0.0012)や最大偏差率(64.864%)には測定器固有の「癖」が残ります

暗号鍵には「全てのビットが完全に独立かつ等確率」であることが求められますが、NISQ(Noisy Intermediate-Scale Quantum)デバイスは熱的ノイズ・制御誤差・デコヒーレンスにより、0/1の出現確率に微細な偏りが混入します。

NISQ デバイスの現実
現在の量子コンピュータはノイズの影響を強く受けます。このバイアスは毎回異なり、ホワイトニング処理なしには予測・補正が困難です。

課題 B:リアルタイム性と可用性の欠如

今回の実測では、IBM Quantum 実機での乱数生成に 平均 67.3 秒を要しました。

使用バックエンド: ibm_fez
ジョブID: d6v255qtnsts73eso4vg → https://quantum.ibm.com/jobs
完了まで待機します…
実機生成完了(67.3秒)
先頭32バイト (hex): 7d0823b5b4b327c914e5c1eaee1f78ddc541bcc3a98fff90341e1042f5d328f2

オンデマンドな鍵生成が要求される現代システムにおいて、このレイテンシは致命的です。また、クラウド実機がメンテナンスに入れば乱数供給そのものが停止します。

3. 解決策としての「Hybrid 方式」:役割分担の設計

課題 A(品質のムラ)と課題 B(速度の欠如)を同時に解決するために、**「量子エントロピーを、暗号学的に安全な疑似乱数生成器(CSPRNG)の Seed として利用する」**設計が必要です。これが「Hybrid 方式」です。
Hybrid 方式は、エントロピー源と乱数生成器を分離する暗号設計原則(SP 800-90 系列)に基づいています。

Hybrid 処理パイプライン

image.png

  • STEP 1:量子エントロピーの採取(IBM Quantum 実機)

    • |+⟩ × N qubit --[H gate]--> 測定 --> raw ビット列
      ※ バイアス・ノイズ含む。25,000 バイト分を 1 ジョブでまとめて取得
  • STEP 2:SHA-512 によるランダムネス抽出(randomness extractor)

    • raw データ --[sha512_whiten(domain, counter, raw)]--> 精製エントロピー(64 byte)
      ※ ドメイン分離で用途ごとに出力を独立化。カウンターモードで任意長に対応
  • STEP 3:OS エントロピーとの混合

    • os.urandom(64) + qrng_white --[SHA-512(連結)]--> 混合 Seed(64 byte)
      ※ 連結 → SHA-512 で混合(XOR より偏り・長さ差に堅牢)
      ※ 量子:予測不能性の付与 / OS:供給安定性・フォールバックの保証
  • STEP 4:HMAC_DRBG への注入(NIST SP 800-90A 準拠)

    • 混合 Seed --[HMAC_DRBG.instantiate()]--> CSPRNG 内部状態
      ※ 前方・後方秘匿性を保証。出力から内部状態を逆算不可能
  • OUTPUT:高速・高品質・安定供給

    • HMAC_DRBG.generate(N) --> 実用乱数バイト列(μ 秒オーダー)
Python 実装例
import os
import binascii
import hashlib
import hmac


# ---------------------------
# STEP 2: SHA-512 によるランダムネス抽出(randomness extractor)
# ---------------------------
def sha512_whiten(raw: bytes, out_len: int, domain: bytes = b"QRNG-WHITEN-v1") -> bytes:
    """
    raw(物理バイアスを含む入力)から out_len バイトの疑似一様な列を抽出する。
    - ドメイン分離で用途ごとに出力を独立させる
    - カウンターモードで out_len > 64 バイトにも対応
    """
    out = bytearray()
    counter = 0
    while len(out) < out_len:
        h = hashlib.sha512()
        h.update(domain)
        h.update(counter.to_bytes(8, "big"))
        h.update(raw)
        out.extend(h.digest())
        counter += 1
    return bytes(out[:out_len])


# ---------------------------
# STEP 4: HMAC_DRBG(NIST SP 800-90A 準拠・自前実装)
# ---------------------------
class HMACDRBG_SHA512:
    """
    NIST SP 800-90A の HMAC_DRBG をそのまま実装。
    外部ライブラリ不要・前方/後方秘匿性を保証。
    """
    def __init__(self, entropy: bytes, nonce: bytes = b"", personalization: bytes = b""):
        self.K = b"\x00" * 64
        self.V = b"\x01" * 64
        seed_material = entropy + nonce + personalization
        self._update(seed_material)

    def _hmac(self, key: bytes, data: bytes) -> bytes:
        return hmac.new(key, data, hashlib.sha512).digest()

    def _update(self, provided_data: bytes = b""):
        self.K = self._hmac(self.K, self.V + b"\x00" + provided_data)
        self.V = self._hmac(self.K, self.V)
        if provided_data:
            self.K = self._hmac(self.K, self.V + b"\x01" + provided_data)
            self.V = self._hmac(self.K, self.V)

    def reseed(self, entropy: bytes, additional_input: bytes = b""):
        self._update(entropy + additional_input)

    def generate(self, n_bytes: int, additional_input: bytes = b"") -> bytes:
        if additional_input:
            self._update(additional_input)
        out = bytearray()
        while len(out) < n_bytes:
            self.V = self._hmac(self.K, self.V)
            out.extend(self.V)
        self._update(additional_input)
        return bytes(out[:n_bytes])


# ---------------------------
# STEP 3 + 4: Hybrid RNG の組み立て
# ---------------------------
def make_hybrid_rng(qrng_raw: bytes, verbose: bool = True) -> HMACDRBG_SHA512:
    """
    ハイブリッド乱数生成器の初期化:
      QRNG raw → sha512_whiten → os.urandom と連結 → SHA-512 → HMAC_DRBG へ注入
    片方(量子 or OS)が弱くても、もう片方が強ければ全体の強度が保たれる。
    """
    # OS 由来エントロピー(フォールバック兼・安定供給側)
    os_entropy = os.urandom(64)

    # STEP 2: SHA-512 によるランダムネス抽出(randomness extractor)
    qrng_white = sha512_whiten(qrng_raw, 64, domain=b"IBM-QRNG-RAW->SHA512")

    # STEP 3: 連結 → SHA-512 で混合(XOR より偏り・長さ差に堅牢)
    seed_entropy = hashlib.sha512(os_entropy + qrng_white).digest()  # 64 bytes

    # nonce で再起動時の重複を回避
    nonce = os.urandom(32)

    drbg = HMACDRBG_SHA512(
        entropy=seed_entropy,
        nonce=nonce,
        personalization=b"HYBRID-DRBG-v1"
    )

    if verbose:
        print(f"[hybrid_rng] os_entropy[:8] = {binascii.hexlify(os_entropy[:8]).decode()}")
        print(f"[hybrid_rng] qrng_white[:8] = {binascii.hexlify(qrng_white[:8]).decode()}")

    return drbg


# 使用例
# qrng_raw  = qrng_key_real(64)          # IBM Quantum 実機から取得
# rng       = make_hybrid_rng(qrng_raw)
# key_bytes = rng.generate(32)           # μ 秒オーダーで出力

4. 実行結果:全方式の完全ログ

本記事の統計評価は簡易的なものであり、主に「明らかな偏りの有無」を確認することを目的としています。
厳密な乱数品質評価には NIST SP 800-22、Dieharder、TestU01 などのテストスイートが必要です。
なお、これらの統計テストは暗号的安全性を保証するものではなく、安全性は DRBG の設計に依存します。

PRNG (seed固定) 平均統計 (5回成功)
  p値平均             : 8.7238e-02
  エントロピー不足平均 : 0.041972 bit
  隣接相関平均         : -0.023316
  最大偏差率平均       : 68.960 %

TRNG (os.urandom) 平均統計 (5回成功)
  p値平均             : 2.9889e-01
  エントロピー不足平均 : 0.039456 bit
  隣接相関平均         : -0.002554
  最大偏差率平均       : 61.792 %

Qiskit (IBM実機 Sampler・測定ビット列) 平均統計 (5回成功)
  p値平均             : 6.2437e-01
  エントロピー不足平均 : 0.035907 bit
  隣接相関平均         : 0.000060
  最大偏差率平均       : 66.912 %

QRNG (IBM実機 raw) 平均統計 (5回成功)
  p値平均             : 4.1317e-01
  エントロピー不足平均 : 0.039183 bit
  隣接相関平均         : 0.001232
  最大偏差率平均       : 64.864 %

QRNG raw→SHA-512 (ホワイトニング後) 平均統計 (5回成功)
  p値平均             : 2.6282e-01
  エントロピー不足平均 : 0.039540 bit
  隣接相関平均         : -0.005335
  最大偏差率平均       : 71.008 %


Hybrid(CSPRNG) (QRNG注入+OS混合) 平均統計 (5回成功)
  p値平均             : 5.4725e-01
  エントロピー不足平均 : 0.036508 bit
  隣接相関平均         : 0.003766
  最大偏差率平均       : 72.032 %

5. 統計分析:Hybrid が安定した指標を示した理由

全方式の横断比較

方式 p 値平均 エントロピー不足 隣接相関 供給速度
PRNG(seed固定) 8.72×10⁻² ❌ 0.041972 bit -0.023316 μ秒
TRNG (os.urandom) 2.99×10⁻¹ 0.039456 bit -0.002554 μ秒
QRNG raw(実機) 4.13×10⁻¹ 0.039183 bit +0.001232 〜67秒 ❌
QRNG raw → SHA-512 2.63×10⁻¹ 0.039540 bit -0.005335 〜67秒 ❌
Hybrid (CSPRNG) 5.47×10⁻¹ 0.036508 bit +0.003766 μ秒
Qiskit Sampler 実機 6.24×10⁻¹ 0.035907 bit +0.000060 ✅ 〜67秒 ❌

参考値
p 値は有意水準(例:0.05)で棄却されないことが重要です。
エントロピー不足および隣接相関は 0 に近いほど望ましい指標です。

p 値が 0.5472 になった理由

カイ二乗検定における p 値は、「一様分布からの逸脱を検出できるか」を示す指標です。本結果は「有意な偏りが検出されなかった」ことを示しますが、これ自体が一様ランダム性や暗号的安全性を証明するものではありません。

Hybrid が安定した統計値を示した背景には、以下の 3 要素があります。ただし、これらは統計的性質に関する説明であり、暗号的安全性そのものは DRBG の設計に依存します。

  1. SHA-512 の雪崩効果で量子バイアスが情報論的に均一化される
  2. HMAC_DRBG は前方秘匿性および後方秘匿性を提供し、内部状態から過去および将来の出力を推測できないように設計されています。
  3. OS エントロピーとの混合は、単なる品質向上ではなく、異なるエントロピー源を組み合わせることで単一点障害を回避する設計として重要です。

量子エントロピーは予測不能性を持つ入力源であり、DRBG はそれを安全に拡張する役割を持ちます。最終的な安全性は DRBG の構造(前方・後方秘匿性)によって保証されます。

Qiskit Sampler 単体の注目すべき結果

隣接相関 +0.000060(全方式中最もゼロに近い=ビット間独立性が最高)、エントロピー不足も 0.035907 bit と最少値を記録しました。これは量子力学の理論的予測を裏付ける実測値であり、QRNG の真のランダム性が統計的に確認された重要な結果です。

ただし 67.3 秒のレイテンシが実務適用のボトルネックである点も同時に確認されました。

6. 結論:実務者が採用すべき「三層の守り」

量子乱数を実務システムに組み込む際は、以下の三層アーキテクチャを推奨します。

量子は「究極の不規則性」を生み、暗号アルゴリズムは「数学的な安全性」を保証し、OS は「運用の安定性」を支えます。

この役割分担こそが、現在の IT インフラにおいて QRNG を実用化するための唯一無二の正攻法と言えるかもしれません。

検証環境

  • Backend:IBM Quantum ibm_fez
  • 言語・バージョン:Python 3.11
  • ライブラリ:Qiskit 1.x, PyCryptodome 3.x
  • 統計検定:カイ二乗検定(5,000 バイト × 5 回)
  • エントロピー不足:Shannon エントロピー理論値(8.0 bit)との差分
  • 隣接相関:連続バイト間のピアソン相関係数
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?