スキップしてメイン コンテンツに移動

Intel DRNG (rdrand)を使ってみる in C/Rust

Intel Digital Random Number Generator / rdrand

シミュレーションを行ったり暗号化を行うときに、乱数生成器を用います。コンピュータは決定論的に動作するので、プログラム中で真にランダムな乱数を得ることは難しいです。そこで、暗号論的疑似乱数生成器が用いられます。

LinuxやmacOSでは、/dev/randomなどがよく使われる暗号論的疑似乱数生成器です。これらは物理的なソースをエントロピー源として利用します。一般的な実装では、HDDやメモリ、マウス、キーボード等の、よく変動する予測が難しい情報を利用して乱数を生成するようです。

しかしこうしたエントロピー源から得られる値は、本当に一様分布で統計的に予測ができないかと言われるとそうとも言い切れません。そこで近年のIntel x86_64チップには、デジタル乱数生成器(Intel Digital Random Number Generator: DRNG)が搭載されており、シリコンの熱雑音を用いて乱数を得ることができます。これを用いて乱数を得るrdrand命令が用意されています。

Intel DRNGの構成

コード

rdrand レジスタ名で適当なレジスタにランダムな値を格納してくれます。setcでちゃんと生成されたどうか、結果のステータスも受け取ることができます。

これをC及びRustから呼び出すコードを書いてみました。

動かしてみると、ランダムな数字が出力されるのがわかるかと思います。

おわりに

たのしかったです(小並感)。初めてRustでインラインアセンブリを書く経験をしたので、勉強になりました。

小ネタ

Intelが誠実なHW実装をしているかは信じるしかないみたいなところがあるので、Linuxの/dev/randomではrdrandをそのまま使うようなことはしていないそうです。

参考

コメント

このブログの人気の投稿

ERC-165: Standard Interface Detection まとめ

先日EthereumのERC-165を読んでいたので, 備忘録として日本語でまとめを記しておきます. ERC-165: Standard Interface Detection このERCでは, スマートコントラクトがどのようなInterfaceを実装しているのかを公開・検出する方法を定義しています. これによって, 目の前のスマコンがERC-20準拠なのかとか, あのInterfaceを実装しているのかとかを調べることができるという嬉しいポイントがあります. Interfaceとは? これこれ. プログラミング言語によってはInterfaceの概念がないものもあったりして馴染みのない方ももしかしたらいるかもしれません. このコントラクトは, こういうメソッドを持つよ! というお約束を書くアレです. 標準化した内容 以下の4つを標準化しました. Interfaceの識別方法 コントラクトが実装しているInterfaceを公開する方法 コントラクトがERC-165を実装しているかを検出する方法 コントラクトが, 任意のInterfaceを実装しているかを検出する方法 1. Interfaceの識別方法 Interface識別子というものを導入します. Interface識別子というのは, 全てのFunction Selectorのxorを取ることで計算されます. Function Selector自体は bytes4(keccak256("関数名(引数の型)")) で計算されます. Function Selectorってなんやねんという方は, こちらの記事を読むとスッキリすると思います. Solidity Assembly入門 ~ Function Selector ~ - アルゴリズムとかオーダーとか なのでざっくり言うと, 目の前のコントラクトがERC-20に準拠しているか知りたかったら, ERC-20が備えているべきInterfaceの識別子を計算し, それをコントラクトに渡してお前はこのInterface持っとるかと聞けばいいわけですね. 2. コントラクトが実装しているInterfaceを公開する方法 目の前のコントラクトに, 「(少なくとも)このInterfaceをサポートしてますか?」と聞いたら, はい or いいえのbool

Ethereum 署名の流れ

Ethereumでトランザクションに署名をしたり, その検証をしたり, 署名から公開鍵(EOAアドレス)を導出する方法を整理しておきます. 署名でできること 以下ができます. 秘密鍵の所有者が, トランザクションの実行を許可したことを署名によって確認する 1自体(トランザクションの実行を許可したこと)を否定できないことを保証する 秘密鍵の所有者でないと, 有効な署名は作れないので, 当然ですね. 署名されて以来, トランザクションが改ざんされていないことを証明する トランザクションの内容が書き換わると, トランザクションのハッシュ値も変わるので, 署名が無効になります. 署名から, トランザクションを作成したアカウントの特定(EOAアドレス=公開鍵を導出する) トランザクションにはfromアドレスが記載されていないので, 署名から送信元アドレスを計算する必要があります. 署名のデータ 署名には, $(r, s, v)$という3つのデータが入っています. このうち, $v$は チェーン識別子 です. 署名の作成 $m$がトランザクション(nonce, gasPrice, gasLimit, to, value, data, vを適切に設定し, rとsにはゼロを入れたもの)を, RLPでエンコードしたものとします. $k$は, 秘密鍵とします. 署名は, $(r, s) = F_{sig}(m, k) $ という感じで生成します. 署名をやってくれる$F_{sig}$の中身はどうなっとるんじゃいという話ですが, Ethereumで採用されている署名アルゴリズムはECDSA(楕円曲線デジタル署名アルゴリズム)です. 一応その手順を以下に記しておきます. 楕円曲線暗号よくわかっとらんので, 間違ってたりとかしたら教えてください. 一時的な秘密鍵として, 乱数$q$を生成する. $q$に対応する一時的な公開鍵$Q$を, 秘密鍵$q$から生成する. 署名作成のときに一時的に使う公開鍵を, 楕円曲線生成元$G$から生成します. $r$は, 一時公開鍵$Q$のx座標になる まあ楕円曲線ってこんな感じのやつで, 一時公開鍵$Q$は楕円曲線上の点だったと思いますので, そのx座標を$r$とするわけですね. $s = q^{-1}(keccak256(m) + r \cdot k) (\

【論文輪読】CoopEdge: A Decentralized Blockchain-based Platform for Cooperative Edge Computing

研究会の輪読で, 協調エッジコンピューティングについての論文CoopEdgeを読んでまとめたので, スライドを供養しておきます. CoopEdge: A Decentralized Blockchain-based Platform for Cooperative Edge Computingを読む from Hiroki Takemura