ソロベイ–シュトラッセン素数判定法

ソロベイ–シュトラッセン素数判定法（英: Solovay–Strassen primality test）は、Robert M. Solovay（英語版）とフォルカー・シュトラッセンによって開発された、与えられた数が合成数か擬素数か判定する確率的テストである。現在ではBaillie–PSW primality test（英語版）やミラー-ラビン素数判定法にとって代わられているが、RSA暗号の実用性を示したアルゴリズムとして歴史的には重要である。 レオンハルト・オイラーは任意の素数pと整数aに対して、 a ( p − 1 ) / 2 ≡ ( a p ) ( mod p ) {\displaystyle a^{(p-1)/2}\equiv \left({\frac {a}{p}}\right){\pmod {p}}} ( ( a p ) {\displaystyle \left({\tfrac {a}{p}}\right)} はルジャンドル指標)であることを証明した。ヤコビ指標（英語版）はルジャンドル指標を一般の奇数nに対する ( a n ) {\displaystyle \left({\tfrac {a}{n}}\right)} に一般化したものである。ヤコビ指標は平方剰余の相互法則のヤコビによる一般化を用いればO((log n)2)時間で計算できる。 奇数nが与えられたとき、合同式 a ( n − 1 ) / 2 ≡ ( a n ) ( mod n ) {\displaystyle a^{(n-1)/2}\equiv \left({\frac {a}{n}}\right){\pmod {n}}} がnと互いに素な様々な底aに対して成立するかどうかを考えることができる。nが素数なら、この合同式はすべてのaに対して真である。そのため、ランダムにaを取ってこの合同式をチェックすれば、成り立たないaが存在した時にnが素数でないことが言える(ただし素因数分解は分からない)。この場合の底aをnのEuler witnessと呼ぶ。このaはnが合成数であることの証拠である。もしnが合成数で上の合同式が成立するならば、そのときの底aをnのEuler liarと呼ぶ。 任意の奇数の合成数nに対して、全ての底のうち少なくとも半分の底 a ∈ ( Z / n Z ) ∗ {\displaystyle a\in (\mathbb {Z} /n\mathbb {Z} )^{*}} がEuler witnessである。これは、証拠の数がずっと少なくなり得るフェルマーテストとは対照的である。そのため、フェルマーテストにおけるカーマイケル数の存在とは対照的に、証拠がたくさん存在しないような(奇数の)合成数nは存在しない。 n = 221が素数かどうかを判定したいとする。(n−1)/2=110である。 ランダムにaを取る(ここではa = 47 < n)。このとき、 a(n−1)/2 mod n  =  47110 mod 221  =  −1 mod 221 ( a n ) {\displaystyle ({\tfrac {a}{n}})} mod n  =  ( 47 221 ) {\displaystyle ({\tfrac {47}{221}})} mod 221  =  −1 mod 221. これにより、221が素数であるか、47が221のEuler liarであることが分かる。もう一つ別のa(ここではa = 2)で試す。 a(n−1)/2 mod n  =  2110 mod 221  =  30 mod 221 ( a n ) {\displaystyle ({\tfrac {a}{n}})} mod n  =  ( 2 221 ) {\displaystyle ({\tfrac {2}{221}})} mod 221  =  −1 mod 221. 2は221が合成数であることを示すEuler witnessであるため、47は実はEuler liarであった。なおこの方法では221の約数(13と17)については何も分からないことに注意されたい。 このアルゴリズムは以下の疑似コードで書ける: 入力: n : 素数かどうかチェックする数; k: テストの正確性を決めるパラメータ 出力: nが合成数の場合はcomposite、そうでなければprobably prime 以下を k 回繰り返す: [2,n − 1]の範囲からaをランダムに選ぶ x ← ( a n ) {\displaystyle \left({\tfrac {a}{n}}\right)} if x = 0 or a ( n − 1 ) / 2 ≢ x ( mod n ) {\displaystyle a^{(n-1)/2}\not \equiv x{\pmod {n}}} then return composite return probably prime 冪剰余の高速なアルゴリズムを使えば、このアルゴリズムの実行時間はO(k·log3 n)である(kは異なるaでテストをする回数)。 このアルゴリズムは誤った答えを返すことがある。入力nが実際に素数であれば、出力は常に正しく「probably prime」である。しかし、入力nが合成数である場合にも、出力が「probably prime」である場合がある。そのような整数nは擬素数と呼ばれる。 nが奇数の合成数である場合、gcd(a,n) = 1であるようなaのうち少なくとも半分はEuler witnessである。これは以下のように証明できる。{a1, a2, ..., am}をEuler liarの集合とし、aをEuler witnessとする。各i = 1,2,...,mに対して次が成り立つ: ( a ⋅ a i ) ( n − 1 ) / 2 = a ( n − 1 ) / 2 ⋅ a i ( n − 1 ) / 2 = a ( n − 1 ) / 2 ⋅ ( a i n ) ≢ ( a n ) ( a i n ) ( mod n ) {\displaystyle (a\cdot a_{i})^{(n-1)/2}=a^{(n-1)/2}\cdot a_{i}^{(n-1)/2}=a^{(n-1)/2}\cdot \left({\frac {a_{i}}{n}}\right)\not \equiv \left({\frac {a}{n}}\right)\left({\frac {a_{i}}{n}}\right){\pmod {n}}} ( a n ) ( a i n ) = ( a ⋅ a i n ) {\displaystyle \left({\frac {a}{n}}\right)\left({\frac {a_{i}}{n}}\right)=\left({\frac {a\cdot a_{i}}{n}}\right)} なので、 ( a ⋅ a i ) ( n − 1 ) / 2 ≢ ( a ⋅ a i n ) ( mod n ) . {\displaystyle (a\cdot a_{i})^{(n-1)/2}\not \equiv \left({\frac {a\cdot a_{i}}{n}}\right){\pmod {n}}.} が成り立つ。 これにより、各Euler liar aiに対して、a·aiがEuler witnessになる。そのため、Euler witnessの個数はEuler liarの個数以上である。それゆえ、nが合成数ならば、gcd(a,n) = 1となるaのうち少なくとも半分はEuler witnessである。 このため、失敗の確率は最大で2−kである(ミラー-ラビン素数判定法の失敗の確率(最大4−k)と比較されたい)。 暗号の目的で使用する場合、沢山のaでテストするほど、つまり十分大きなkを選べば、テストはより正確になる。そのためこのアルゴリズムが失敗する可能性はとても低いので、実用的な暗号への応用においてはこの方法で得られた(擬似)乱数が使われる。しかし、素数を得ることが重要であるような応用においては、ECPP（英語版）やPocklingtonのような素数性を「証明」するテストを使用すべきである。 ^ オイラーの規準 ^ PlanetMath ^ Pocklington test on Mathworld Solovay, Robert M.; Strassen, Volker (1977). “A fast Monte-Carlo test for primality”. SIAM Journal on Computing 6 (1): 84–85. doi:10.1137/0206006  See also Solovay, Robert M.; Strassen, Volker (1978). “Erratum: A fast Monte-Carlo test for primality”. SIAM Journal on Computing 7 (1): 118. doi:10.1137/0207009  Dietzfelbinger, Martin. “Primality Testing in Polynomial Time, From Randomized Algorithms to "PRIMES Is in P"”. Lecture Notes in Computer Science. 3000. ISBN 3-540-40344-2  Solovay-Strassen Implementation of the Solovay–Strassen primality test in Maple 表示 編集