C言語 Unix /dev/urandomから乱数を読み込む方法
スポンサーリンク
このドキュメントの内容は、以下の通りです。
- はじめに
- Unix環境における乱数の取得
- /dev/random
- /dev/urandom
- kern.random.sys.seeded
- urandom と random のどちらを利用すべきか?
- Linuxでの/dev/urandomと/dev/random
- FreeBSDでの/dev/urandomと/dev/random
- C言語のサンプルコード
- コンパイル
- 実行例
- Linuxのシステムコール getrandom
はじめに
乱数という言葉は聞いたことがあるでしょうか?乱数とは、ランダムな数ということです。このランダムな数は、いろいろなところで用いられています。たとえば、ロールプレイングゲームの中で、敵が現れるかどうかは、乱数によって決めることができます。ロールプレイングゲームの中で、敵と戦うときに、攻撃が当たるかどうかも乱数で決めることができますね。キャラクタごとのいろんなパラメータを加味して、計算されるので、乱数だけで決まらないとは思いますが。
みなさんが利用しているインターネットでは、安全性を実現するために、暗号技術を利用しており、暗号技術では、乱数が利用されています。
いろいろなシーンで乱数は必要になります。ソフトウェアを開発するときに、乱数を必要とするケースもあるでしょう。
プログラミング言語ごとに、乱数を得るための関数・メソッド・モジュールなどが用意されています。ゲームならそこまで気にする必要はないかもしれませんが、もし暗号化のために乱数を使うのであれば、 暗号学的に安全な乱数を得る手段を使う必要があり、暗号や乱数の専門家でない限り、自身で実装すべきではないでしょう。
Unix環境における乱数の取得
Unix環境におけるC言語で、乱数を取得するには、rand()関数を利用すると簡単に乱数が得られますが、今回は、/dev/urandomから乱数を取得します。urandomは、 FreeBSD や Linux などの Unix に存在します。
/dev/urandomのほかに/dev/randomもあります。
/dev/random
エントロピーを集めて、プールしておき、乱数を生成します。十分なデータがない場合、乱数が生成できません。 エントロピーのプールが空の場合は、ブロックされます。
/dev/urandom
エントロピーがより高くなるのを待つためのブロックが行われません。十分なエントロピーがない場合は、ドライバで使っているアルゴリズムによって乱数が生成されますが、/dev/randomに比べ、脆弱になります。
kern.random.sys.seeded
FreeBSDの場合、kern.random.sys.seededが0のときに、十分なエントロピーがないとブロックされます。1のときは、ノンブロッキングです。
urandom と random のどちらを利用すべきか?
Linux においては、 /dev/urandom よりも /dev/random のほうが安全だと言われています。しかし、前述したとおり、 /dev/random は、ブロックするという特徴があることから、 /dev/urandom が好ましいケースもあります。
Linuxでの/dev/urandomと/dev/random
Linux の1つである Ubuntu の /dev/random と /dev/urandom を ls コマンドで確認しました。以下のように独立したものとなっています。
$ ls -l /dev/*random crw-rw-rw- 1 root 1, 8 5月 31 12:10 /dev/random crw-rw-rw- 1 root 1, 9 5月 31 12:10 /dev/urandom
FreeBSDでの/dev/urandomと/dev/random
FreeBSDでは、 /dev/urandom と /dev/random があります。
以下は、FreeBSD で ls コマンドを用いて確認をした結果です。
$ ls -ls /dev/*random 0 crw-rw-rw- 1 root wheel 0x20 6月 2 2018 /dev/random 0 lrwxr-xr-x 1 root wheel 6 6月 12 2018 /dev/urandom@ -> random
FreeBSD の /dev/urandom は、 /dev/random のシンボリックリンクになっています。
C言語のサンプルコード
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#define DEV_RANDOM "/dev/urandom"
#define BUF 256
int
get_random (char * const buf, const int buflen, const int len)
{
if (len > buflen)
{
warnx ("buffer size is small (%d / %d)", buflen, len);
return (-1);
}
int fd = open(DEV_RANDOM, O_RDONLY);
if (fd == -1)
{
warn ("can not open %s", DEV_RANDOM);
return (-1);
}
int r = read (fd, buf, len);
if (r < 0) {
warn ("can not read");
return (-1);
}
if (r != len)
{
warnx ("can not read(%d != %d)", r, len);
return (-1);
}
(void) close (fd);
return (0);
}
void
dump_hex(const char *p, const int len)
{
int i = 0;
for (i = 0; i < len; ++i)
{
unsigned char c = p[i];
printf ("i=%d , %02x\n", i, c);
}
printf ("len = %d\n", len);
}
int
main (int argc, char *argv[])
{
char buf[BUF];
int buflen = sizeof(buf);
int len = 4;
if (get_random(buf, buflen, len) == 0) {
dump_hex(buf, len);
}
(void) printf ("\n");
exit (EXIT_SUCCESS);
}
コンパイル
コンパイル方法は以下の通りです。
cc urandom.c
実行例
% ./a.out i=0 , a5 i=1 , 57 i=2 , ae i=3 , 91 len = 4 % ./a.out i=0 , be i=1 , 48 i=2 , 01 i=3 , e7 len = 4
Linuxのシステムコール getrandom
Linux カーネル 3.17 で gerandom システムコールが追加されました。 getrandom は、 /dev/random か /dev/urandom からデータを読み出す機能を提供します。getrandom の 第三引数のフラグで、ブロッキングモードや非ブロッキングモードが指定できます。
getrandom システムコールを利用するメリットは、open システムコールや close を呼ぶ必要もなくなるので、コードが短くなることだと思います。
#include <sys/random.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> //write
int
main(int argc, char *argv[])
{
ssize_t size;
unsigned char buf[8];
size_t buf_size = sizeof(buf);
int flag = GRND_NONBLOCK;
size = getrandom(buf, buf_size, flag);
if(-1 == size) {
perror ("getrandom");
exit (1);
}
write(1, buf, size);
return 0;
}
コンパイル方法は以下の通りです。
cc getrandom1.c
バッファの中は、そのまま printf してもわからないので、base64 してから表示します。乱数であるため、毎回実行結果は変わります。
$ ./a.out | base64 wEh6oQu18oI=
スポンサーリンク
スポンサーリンク
いつもシェア、ありがとうございます!
もっと情報を探しませんか?
関連記事
最近の記事
- パナソニック ジェットウォッシャードルツ EW-DJ61-Wのホースの修理
- LinuxセキュリティモジュールIntegrity Policy Enforcement
- アマゾンのEcho Show 5を買ったのでレビューします
- アマゾンのサイバーマンデーはAlexa Echo Show 5が安い
- Android スマートフォン OnePlus 7T と OnePlus 7の違い
- Android スマートフォン OnePlus 7 をAndroid10にアップデートしてみた
- クレジットカードのバーチャルカードの比較のまとめ
- 活動量計 Xiaomi Mi Band 4を買ってみたのでレビュー
- Android スマートフォン OnePlus 7 のレビュー
- AliExpressでスマートフォンを買い物してみた
- パソコンのホコリ対策 レンジフードフィルターと養生テープ
- 80PLUS GOLDのPC電源ユニットAntec NeoEco 750 Goldのレビュー
- イギリスの付加価値税 VAT は払い戻しを受けられる
- イギリスのロンドンでスーツケースなど荷物を預けられる場所は
- イギリスのロンドンで地下鉄やバスに乗るならオイスターカードを使おう
- イギリスのヒースロー空港からロンドン市内への行き方
- 航空便でほかの航空会社に乗り継ぎがある場合のオンラインチェックイン
- SFC会員がANA便ではなくベトナム航空のコードシェアを試して解ったこと
- ベトナムの入国審査でeチケットの掲示が必要だった話
- シアトルの交通ICカードはオルカカード(Orca)です
人気のページ
- Windows7 IME 辞書ツールで単語の登録に失敗しました
- C言語 popen()でコマンドを実行して出力を読み込む
- Windows7で休止状態にする方法
- CentOS MySQLの起動、停止、再起動
- loggerコマンドでsyslogにエラーを出力する方法
- パソコンパーツの買取をしてくれる店のまとめ
- Java Mapの使い方 get(),put(),remove(),size(),clear()
- 楽天のRポイントカードを作ってみた
- iPhone 5 から iPhone 6 に乗り換えたのでレビュー
- netstatコマンドのステータスの意味
スポンサーリンク
過去ログ
2020 : 01 02 03 04 05 06 07 08 09 10 11 122019 : 01 02 03 04 05 06 07 08 09 10 11 12
2018 : 01 02 03 04 05 06 07 08 09 10 11 12
2017 : 01 02 03 04 05 06 07 08 09 10 11 12
2016 : 01 02 03 04 05 06 07 08 09 10 11 12
2015 : 01 02 03 04 05 06 07 08 09 10 11 12
2014 : 01 02 03 04 05 06 07 08 09 10 11 12
2013 : 01 02 03 04 05 06 07 08 09 10 11 12
2012 : 01 02 03 04 05 06 07 08 09 10 11 12
2011 : 01 02 03 04 05 06 07 08 09 10 11 12
2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12
2005 : 01 02 03 04 05 06 07 08 09 10 11 12
2004 : 01 02 03 04 05 06 07 08 09 10 11 12
2003 : 01 02 03 04 05 06 07 08 09 10 11 12