質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

4回答

4507閲覧

C言語のrand関数は、同じ値が返されることが保証されていますか?

dkyukinaga

総合スコア19

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2016/05/07 13:34

お世話になります。私の拙い文章に目を通していただければ幸いに存じます。

以下のようなプログラムを走らせると、同じシードを設定した場合、シードを設定してからの呼び出し回数に応じて、rand関数は同じ値を返すようであることがわかります。この挙動を利用すれば、暗号化(例えば暗号化したいデータに対して1バイトずつrandの結果を加算していき、復号化の時は暗号化の時と同じシードを設定して、1バイトずつrandの結果を除算していくなど)なんかも実現できそうです。しかし、そこで疑問に思ったのですが、この同じシードが設定されれば同じ値を返すという挙動は仕様書なんかで保証されているのでしょうか?保証されてないのに、「どうやらそういう挙動らしい」で暗号化なんかを実装するのはやはり危険でしょうか?

C

1#include <stdio.h> 2#include <stdlib.h> 3 4void showRand() 5{ 6 srand(0u); 7 for (int i = 0; i < 10; ++i) { 8 printf("%d ", rand()); 9 } 10 printf("\n"); 11} 12 13int main() 14{ 15 showRand(); 16 showRand(); 17 showRand(); 18 system("pause"); 19}

実行結果

38 7719 21238 2437 8855 11797 8365 32285 10450 30612

38 7719 21238 2437 8855 11797 8365 32285 10450 30612
38 7719 21238 2437 8855 11797 8365 32285 10450 30612
続行するには何かキーを押してください . . .

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

こんにちは。

n1570(C言語の規格書に近いもの)によると下記のように記載されてます。

If srand is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated.

同じシードを与えたら、同じ擬似乱数のシーケンスを繰り返すとは記載されてますが、それだけです。
リビルドした時さえ特に言及されてないので、リビルド前とリビルド後で同じシードに対して異なるシーケンスを返却しても規格には合致していると解釈した方が良いと思います。
実際には、リビルドだけなら同じシーケンスが返却すれるとは思いますが、異なるコンパイラ間で保証されるとはとても思えませんし、バージョンアップで変更されても文句は言えないように思います。

そのような使い方であれば、ご自身で乱数を実装すれば簡単な暗号化には使えるように思います。

投稿2016/05/07 14:08

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dkyukinaga

2016/05/07 14:44 編集

リビルドはともかく、コンパイラのバージョンアップで結果が変わってしまうということはあり得るかもしれませんね。復号できなくなってしまうと厄介なので、rand()を使っての(簡単な)暗号化は少し考えものです。 ご回答、誠にありがとうございました。 raccyさんもYsManaさんもcarbonさんも、ご回答誠にありがとうございました。
dkyukinaga

2016/05/07 15:38

追記: > ご自身で乱数を実装すれば 初めは、そんな無茶な・・・と思って、流してしまっていましたが、調べてみると疑似乱数を実装するだけなら拍子抜けするほど簡単なんですね(アルゴリズムを自分で作り出すことは僕には出来そうもないですが) http://d.hatena.ne.jp/pashango_p/20090717/1247848900 万が一、バージョンアップ等でrand()の中身が変わると嫌なので、自分で実装した疑似乱数を使ってみることにします。
guest

0

srandで同じseedを設定すれば、randが同じ乱数列を返すことは保証されています。
ただし、randには移植性がないのでコンパイラが変わると結果が変わることはあり得ます。

乱数列とxorを取るなどした暗号化は可能でしょう。
ただし、暗号に使うことを考慮していない疑似乱数を使った暗号化は
非常に脆弱なものになるということは意識しておいてください。
(使うなら実験や遊びまでにしておきましょう。)

投稿2016/05/07 14:11

YsMana

総合スコア257

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

rand()関数の実装は環境依存です。全く同じOS(バージョン含む)、全く同じコンパイラ(バージョン含む)、全く同じコンパイルオプション、全く同じアーキテクチャ(32bitや64bitとか)、全く同じ標準ライブラリ(glibcとかの)であれば、同じ環境になっているため、同じシードであれば同じ結果になります。逆にいうと、OSやコンパイラ等が違っていれば異なる場合があります。実際にMacのclangでコンパイルした場合とLinuxのgccでは違うようです。なので、どのような環境であっても同じであるという前提をしてはいけません。

C標準のrand()ではなくメルセンヌ・ツイスタ等の外部ライブラリを使用した場合はそのライブラリが環境依存では無いと同じ結果になります。また、C++ではmt19937など環境依存では無い乱数もあります。

次に、rand()の乱数をそのまま暗号化の処理には使用してはいけません。ほとんどのrand()の実装では次の値が容易に予想可能であり、規則性もあるため、ある程度の暗号文から簡単に予測できてしまい、誰でも容易に復号できてしまう可能性が高いです。AESなどの暗号化処理は、こういった予測が数学的に極めて困難であるという特性をもつ処理を含んでおり、そのような特性が無い物を暗号化に用いると脆弱なシステムになってしまいます。

安全な暗号を作るには極めて高度な計算科学及び数学的知識が必要であり、知識無く新しい暗号化の仕組みを作るのは極めて危険です。思いつきで作った物を実際に使うことは推奨できかねます。

投稿2016/05/07 14:11

編集2016/05/07 14:12
raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dkyukinaga

2016/05/07 14:35

思い付きの暗号化への警鐘ありがとうございます。やはり暗号化というと、極めて高度な計算科学及び数学的知識の世界になってしまうわけですね(汗) 逆アセンブルが少しでも面倒になるくらいの簡単な暗号化と割り切って実装しようと思います^^; ご回答、誠にありがとうございました!
guest

0

randので出てくるような乱数を擬似乱数をと言いますがsrandで同一の値を入れれば全く同じ結果が得られます。なので、確かに暗号化に利用できなくはないのですが、randの場合はかなり簡単に次の値が予測できるので暗号には向かないようです。
ですが、randを使った(randでも可能な)新しい暗号化手法を考えれば、かなり実用的な暗号化方式になるので、面白いかもしれないですね。

投稿2016/05/07 14:15

carbon

総合スコア31

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問