検証可能ランダム関数(VRF)
PoSのリーダー選出やくじ引きを、誰にも操作されず後から誰でも監査できるようにする鍵がVRFです。予測不能な乱数と、その正しさを証明できる仕組みを原理から押さえられます。
- 1.VRFは秘密鍵の保持者だけが計算でき、入力ごとに出力が一意に決まる擬似乱数関数。出力と一緒に証明を添え、公開鍵さえあれば「その乱数は正しく引かれた」ことを第三者が検証できる。
- 2.満たす性質は一意性・擬似ランダム性・証明可能性の3つ。ECVRFは入力をハッシュで曲線上の点に写し、秘密鍵倍した点から出力を作る。実体はNIZK付きの決定的署名で、鍵所有者でも出力を選び直せない。
- 3.PoSのリーダー選出や暗号くじ(sortition)で、当選者を事前に予測できず後から公開監査できる。commit-reveal(RANDAO等)は最後の1人が結果を偏らせるlast-revealer攻撃に弱く、VRFやVDFと組んで補強される。
分散台帳で「公平な乱数」が難しい理由
分散台帳(distributed ledger)では、次にブロックを提案するのは誰か、どのバリデータが委員会に選ばれるか、といった判断に乱数が要ります。ところがパブリックチェーンには信頼できる乱数の発生源がありません。誰かが乱数を握れば、自分が有利になる値を選んだり(操作)、当選者を先読みして狙い撃ちしたり(予測)できてしまいます。合意の安全性(/blockchain/consensus-pow-pos/)を守るには、乱数そのものが操作耐性と予測不能性を備えていなければなりません。
同時に、ブロックチェーンでは「正しく引いた」ことを誰もが後から検証できる必要があります。当選者が「自分は正当に選ばれた」と主張しても、他ノードがそれを鵜呑みにはできません。乱数の秘密性(予測させない)と検証可能性(後から監査できる)は一見矛盾します。この緊張を1つの道具で解くのが**検証可能ランダム関数(Verifiable Random Function, VRF)**です。Micali・Rabin・Vadhan(1999)が定式化しました。
VRFは、秘密鍵 sk を持つ者だけが計算できる擬似乱数関数と考えると分かりやすいです。入力 x に対し、出力 y(乱数値)と証明 pi を返します。y は入力ごとに一意に定まり第三者には予測不能ですが、対応する公開鍵 pk と pi があれば「y は x から正しく導かれた」ことを誰でも検証できます。HMAC(/security/)のような鍵付きハッシュに、出力の正しさを他人へ示す証明を足したもの、と捉えると本質に近いです。
VRFの3つの性質
VRFは3つの性質を同時に満たします。この組み合わせが操作耐性の土台です。
| 性質 | 内容 | 防ぐ攻撃 |
|---|---|---|
| 一意性 (uniqueness) | 同じ pk と x に対し、検証を通る出力 y はただ1つ。鍵所有者でも別の y を選び直せない | 有利な値を選ぶ grinding/出力すり替え |
| 擬似ランダム性 (pseudorandomness) | 証明 pi を見るまで、y は真の乱数と区別できず予測不能 | 当選者の先読み・狙い撃ち |
| 証明可能性 (provability) | pk と pi があれば、y が正しく計算されたことを第三者が検証できる | 「正当に選ばれた」の詐称 |
要点は一意性です。ハッシュ関数なら誰でも同じ出力を再現できますが、それでは秘密鍵の保持者だけが引ける乱数になりません。逆に、鍵所有者が入力ごとに出力を自由に選べては、自分に都合のよい値を作れてしまいます。VRFは「秘密鍵ごと・入力ごとに出力が決定的に一意」で、しかも鍵所有者自身にも選択の余地がない点が鍵です。この一意性のおかげで、後述のリーダー選出において当選者は事前に運命づけられ、恣意的な操作が入り込めません。
VRFの操作は3つのアルゴリズムで表せます。
KeyGen() -> (sk, pk) # 秘密鍵と公開鍵の対を生成
Prove(sk, x) -> (y, pi) # 入力 x から出力 y と証明 pi を計算
Verify(pk, x, y, pi) -> true / false # y が x から正しく導かれたか検証
Prove は秘密鍵 sk を持つ者しか実行できません。一方 Verify は公開情報だけで動くので、ネットワーク上の誰もが当選の正しさを独立に確かめられます。この非対称性が、秘密性と検証可能性の両立を成り立たせています。
ECVRFの内部:署名を乱数源に変える
実用的なVRFは楕円曲線上で構成されます(ECVRF、IRTF が RFC 9381 として標準化)。骨格は決定的な楕円曲線署名に近く、署名・鍵管理で扱うECDSA/EdDSAと同じ数学の上に立ちます。生成点 G、位数 n、秘密鍵 x(1 以上 n 未満)、公開鍵 Y = xG を前提に、入力メッセージ alpha を次のように処理します。
Prove(x, alpha):
H = hash_to_curve(alpha) # 入力を曲線上の点へ写す(出力を選べない核心)
Gamma = x * H # 秘密鍵倍した点。これが乱数の種
# 「Gamma = x*H かつ Y = x*G の x が同一」であることの
# 非対話ゼロ知識証明(NIZK, Fiat-Shamir変換)
k = 決定的に導いた乱数
c = Hash(H, Gamma, k*G, k*H) # チャレンジ
s = k + c*x (mod n) # レスポンス
pi = (Gamma, c, s) # 証明
y = Hash(Gamma) # 最終的な乱数出力(一意)
return (y, pi)
Verify(Y, alpha, y, pi=(Gamma, c, s)):
H = hash_to_curve(alpha)
U = s*G - c*Y # = k*G を復元
V = s*H - c*Gamma # = k*H を復元
c' = Hash(H, Gamma, U, V) # Prove と同じ入力で再計算
有効 <=> c' == c かつ y == Hash(Gamma)
一意性が成り立つ理由は Gamma = x*H にあります。公開鍵 Y = xG が固定である以上、離散対数問題が難しい前提の下では、検証を通る Gamma は入力 alpha(ひいては H)ごとにただ1点に定まります。鍵所有者が別の Gamma を選んでも、Y と整合するゼロ知識証明を作れません。ここが「鍵所有者ですら出力を選び直せない」という操作耐性の源泉です。
入力 alpha を素直に整数化して使うと、攻撃者が出力の構造を予測できる余地が残ります。ECVRFは alpha を曲線上の点 H へハッシュしてから秘密鍵倍します。H はランダムオラクル的に振る舞うため、秘密鍵 x を知らない限り x*H は予測不能な点になり、その先の Hash(Gamma) も真の乱数と見分けがつきません。この写像が甘い(一様でない・別の入力へ衝突する)と擬似ランダム性も一意性も崩れるため、hash_to_curve の正しい実装が安全性の要になります。
PoSのリーダー選出と暗号くじ(sortition)
VRFの代表的な用途が、Proof of Stake(/blockchain/consensus-pow-pos/)でのブロック提案者や委員会の選出です。素朴に「ステーク量に比例して当選確率を割り当てる」だけなら公開情報でできますが、それでは次の当選者が全員に事前に分かってしまい、標的DoSや検閲の的になります。VRFを使うと、各バリデータが自分の鍵で秘密裏にくじを引き、当たったときだけ証明付きで名乗り出られます。
暗号くじ(cryptographic sortition)の骨子は次の通りです。共通のシード(前ラウンドの乱数など)とラウンド番号を入力にして、各自がVRFを評価します。
seed = 直近の確定した乱数(全員が同じ値を参照)
(y, pi) = VRF.Prove(sk_i, seed || round || role)
# 出力 y を [0,1) に正規化し、自分のステーク比率に応じた閾値と比較
当選 <=> normalize(y) < 自分のステーク配分に基づく閾値
if 当選:
ブロック(や投票)に (y, pi) を添えて放送
受け取った側は VRF.Verify(pk_i, seed||round||role, y, pi) で当選の正しさを検証し、複数の当選者がいれば y の値で優先順位(最小の y を提案者にする等)を決めます。Algorand はこの方式で提案者と投票委員会を毎ラウンド秘密に選び、当選者は自分が話す直前まで匿名でいられます。**Cardano(Ouroboros Praos)**もスロットリーダー選出にVRFを用います。
sortitionの巧妙さは、当選判定を各自がローカルに、他者と通信せず行える点です。全員でくじを回す必要がないため通信量が抑えられ、かつ結果が出るまで当選者が誰にも分かりません。標的攻撃者は「誰を攻撃すべきか」を当選者が発言するまで知り得ず、発言した頃には既に役割を果たした後です。これが確定的な当選表(誰でも先読み可能)に対するVRF方式の決定的な優位です。
正当な提案が確定へ進む過程はファイナリティとフォーク選択の規則に従い、当選者が担うのはあくまで「提案する権利」です。二重提案などの違反は、トークンとインセンティブ設計で扱うスラッシングで経済的に罰せられます。
操作耐性:ブロックハッシュ乱数との違い
「ブロックハッシュを乱数に使えばよい」という素朴案がなぜ危ういかを見ると、VRFの操作耐性が際立ちます。ブロック提案者は、自分が作るブロックの中身(トランザクションの取捨・並べ替え・ノンス)を少しずつ変えれば、結果のハッシュを何通りも試せます。当選や配当が自分に有利になるハッシュを選んで採用する——これがgrinding攻撃です。乱数の生成者が結果を試行錯誤で選べる限り、その乱数は操作されうると考えるべきです。
VRFはこの穴を一意性でふさぎます。入力(シード)を固定すれば、各バリデータの出力は鍵ごとにただ1つに決まり、試し引きの余地がありません。出力を変えたければ入力を変えるしかありませんが、シードは過去の確定値なので単独では動かせません。「引き直し」を原理的に封じている点が、ハッシュ流用との本質的な差です。
VRFは個々のくじの引き直しは防ぎますが、次シードの生成に自分の出力が混ざる設計では、悪意ある提案者が「自分に不利なら提案を放棄する(棄権)」ことで、次ラウンドの乱数分布を微妙に偏らせられます。これは値を選ぶ操作ではなく、参加・不参加という2択で結果を間引くバイアス注入で、last-revealer攻撃と同種の残存リスクです。完全なバイアス耐性には、時間で強制する遅延(VDF)や、多数参加者の寄与の集約を併用します。
commit-reveal(RANDAO)方式との比較
VRF以前から使われる乱数生成がcommit-revealです。各参加者がまず秘密値 r_i のハッシュ commit_i = Hash(r_i) を提出(commit)し、全員のcommitが出そろってから r_i を公開(reveal)、公開された値のXORやハッシュを最終乱数とします。commit段階で値を隠すので、他人の値を見てから自分の値を合わせる操作は防げます。EthereumのRANDAOがこの系統です。
| 観点 | commit-reveal(RANDAO等) | VRF |
|---|---|---|
| 乱数の作り手 | 多数の参加者の共同(分散型) | 各鍵保持者が単独で評価 |
| 検証 | 公開値がcommitと一致するか照合 | 公開鍵と証明で出力の正しさを検証 |
| 予測不能性 | 全員がrevealするまで不明 | 証明を見るまで不明(単独で完結) |
| 主なリスク | last-revealer攻撃(最後の1人が棄権/選択) | 参加取捨によるバイアス(限定的) |
| 通信 | commitとrevealの2ラウンドが必要 | 各自ローカル評価で低通信 |
commit-revealの弱点はlast-revealer攻撃です。最後にrevealする者は、他全員の値を見た上で最終乱数を計算でき、結果が気に入らなければ自分のrevealを**わざと出さない(棄権する)ことで乱数を1つ捨てられます。棄権にペナルティがあっても、当選利得がそれを上回れば偏らせる誘因が残ります。RANDAOは各エポックで多数のバリデータの寄与を積み重ねてこの影響を薄めますが、最後の数ブロックの提案者によるわずかなバイアス(一定ビットの操作余地)**は原理的に残ります。
現実の設計は排他的でなく組み合わせです。Ethereumはビーコンチェーンでcommit-reveal型のRANDAOを乱数の骨格に据えつつ、各提案者の寄与にBLS署名ベースのVRF的な決定性を持たせ、将来的にはVDF(Verifiable Delay Function)で「revealを見てから間に合わないほどの計算遅延」を課し、last-revealerのバイアスを封じる方向が議論されてきました。VRFは「単独で予測不能かつ検証可能」を、VDFは「結果確定に不可避な時間を要する」を担い、両者でgrindingと棄権の双方を抑えます。
・VRFの3性質=一意性(pk・xごとに出力は1つ、鍵所有者も選べない)/擬似ランダム性(証明を見るまで予測不能)/証明可能性(pkとpiで第三者が検証可能)。
・一意性がgrinding(引き直し)を封じる操作耐性の核。ブロックハッシュ乱数は提案者が試行選択できるため危険。
・用途=PoSのリーダー選出・暗号くじ(sortition)。Algorand・Cardano Praosが代表。当選者を先読みさせず標的攻撃を防ぐ。
・**commit-reveal(RANDAO)**はlast-revealer攻撃(最後の1人の棄権)に弱い。VRF・VDFと併用して補強する、はセットで問われやすい。
まとめ
- VRFは秘密鍵の保持者だけが計算でき、入力ごとに出力が一意に決まる擬似乱数関数。出力に証明を添え、公開鍵で第三者が正しさを検証できる。
- 満たす性質は一意性・擬似ランダム性・証明可能性の3つ。ECVRFは入力を
hash_to_curveで曲線上の点に写し、秘密鍵倍した点から出力を作る。実体はNIZK付きの決定的署名。 - 一意性が操作耐性の核心で、鍵所有者ですら出力を選び直せない。ブロックハッシュ流用のような**grinding(引き直し)**を原理的に封じる。
- PoSの**リーダー選出・暗号くじ(sortition)**で、当選者を事前に予測させず後から公開監査できる。Algorand・Cardano Praosが代表例。
- commit-reveal(RANDAO)は分散生成だがlast-revealer攻撃に弱い。実際のチェーンはVRFやVDFと組み合わせ、grindingと棄権の双方を抑える。
ブロックチェーン Article
検証可能ランダム関数(VRF)を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
ブロックチェーン
比較で見る軸
難易度: advanced / カテゴリ: ブロックチェーン / タグ数: 6
導入後に効く点
満たす性質は一意性・擬似ランダム性・証明可能性の3つ。ECVRFは入力をハッシュで曲線上の点に写し、秘密鍵倍した点から出力を作る。実体はNIZK付きの決定的署名で、鍵所有者でも出力を選び直せない。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- ブロックチェーン
- タグ数
- 6
判断チェックリスト
- 自社の用途が「ブロックチェーン / 分散台帳」に近いか確認する。
- 強みである「VRFは秘密鍵の保持者だけが計算でき、入力ごとに出力が一意に決まる擬似乱数関数。出力と一緒に証明を添え、公開鍵さえあれば「その乱数は正しく引かれた」ことを第三者が検証できる。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。