- ベストアンサー
巨大な素数の効率的な作り方
C++の勉強がてらにRSAのプログラミングをやってみたのですが鍵生成の時間が一定しません。 試しに512bitの素数を50回作ってみると、平均79秒、標準偏差71秒、最長343秒、最短9秒でした。 ここまで標準偏差が大きいと当然50回の平均を取ったところで、一定の値は取りません。 現在はオイラーの公式n^2+n+41で素数を出していますが、もっと効率良く素数を出す方法はないのでしょうか?
- みんなの回答 (3)
- 専門家の回答
C++の勉強がてらにRSAのプログラミングをやってみたのですが鍵生成の時間が一定しません。 試しに512bitの素数を50回作ってみると、平均79秒、標準偏差71秒、最長343秒、最短9秒でした。 ここまで標準偏差が大きいと当然50回の平均を取ったところで、一定の値は取りません。 現在はオイラーの公式n^2+n+41で素数を出していますが、もっと効率良く素数を出す方法はないのでしょうか?
補足
回答ありがとございます。 実はNo.2の回答を頂いた後、色々と調べていたところ、モンゴメリ乗算という方法を見つけたのでそれのコーディングをしていたのですが、それがようやく今日できました。 x*y (mod a)という計算がaが常に一定で、繰り返し行われるとき効率良く計算できるという方法です。 これをa^b (mod c)の計算に組みこみ、さらにフェルマーの判定式の前に、10個ほどの小さな素数で割り切れるかどうか確認するようにしたところ、50回素数を生成した結果が平均7秒、標準偏差6秒、最長28秒、最短1秒になりました。 二秒程度で鍵ができあがるときもあれば、一分以上かかる場合もあるといったような状態ですが、一応使い物にはなるレベルにはなってきました。 > Miller-Rabin法を使うのが良いです。 最初はMiller-Rabin法でやっていたのですが、あまりにa^b (mod c)の計算速度が遅かったので簡略化のためフェルマーの小定理での判定法にしてしまっていました。 改めて調べて見ると、カーマイケル数の問題があるようなのでMiller-Rabin法に戻そうと思います。 > n^2+n+41で生成した数の中から素数を探すと、素数に偏りができてしまいます。 そこまで考えていたわけではありませんが、何となく使える素数が少なくなりそうと思い、現在は2n+1型の素数生成式しています。 オイラーの公式と比べて平均時間が5割以上、標準偏差が2割程度増えてしまいましたけど。 50回の平均の結果が標準偏差と同程度という状況を何とかしたかったんですけど、2n+1型で取ってくるしか無いのでしょうか? > int mrb[256]; //1が立っている最も下位のビット位置をあらかじめテーブルに入れておく 値を格納するのに使っているのがlong型なので、この方法ですと32bitのCPU・OSの場合2^32個の配列が必要になるので、ちょっと無理ではないかと。 ビット演算で1バイトずつ取り出すと、結局余計な計算が増えますし。 現在は、 if (x[i / 32] & 1 << i % 32) result = (result * temp) % c; といった感じで取り出しています。