大素数的生成
强拟素数
设n为正奇数,\(b\in Z,b>1,s\in Z^+\),且\(2^s|(n-1)\),令\(t=\frac{n-1}{2^s}\),则\(b^{n-1}-1=(b^{2^0t}-1)(b^{2^0t}+1)(b^{2^1t}+1)+\cdots+(b^{2^{s-1}t}+1)\),因此若n为素数,则\(b^{n-1}-1\equiv 1\mod n\)且\(Z_n\)无零因子,所以\(b^{n-1}-1\)至少有一个等于零的因式,即
\(b^{2^0t}\equiv 1,b^{2^0t}\equiv -1,b^{2^1t}\equiv -1,...,b^{2^{s-1}t}\equiv -1\mod n\)
中必有一个成立。
定义:设\(n\gt 1\)为奇合数,\(b\in Z,(b,n)=1\),令\(n=2^st+1\),其中t为奇数,若\(b^t\equiv 1\mod n\)或存在\(r\in Z,0\le r\lt s\),使得\(b^{2^rt}\equiv -1\mod n\),则称n为对于基b的强拟素数
定理1:存在无穷多个对于基2的强拟素数
定理2:设n是奇合数,\(b\in Z,1\le b\lt n\),那么n是对于基b的强拟素数的概率不超过\(\frac{1}{4}\)
Miller-Rabin素性检验
由上面的结论可知,可以通过增加检验的轮数使生成的素数为强拟素数的概率降低
素性检测的每一轮步骤如下
第一步:将待检测的奇数n写成\(n-1=t\cdot 2^k\)的形式,其中t为奇数
第二步:随机选取一个整数b(b>2),计算\(b_1=b^t\mod n\),如果\(b_1=\pm 1\),则检验通过直接开始下一轮检验
第三步:否则,计算\(b_{i+1}=b_i^2\mod n(n\ge 1)\),如果\(b_{i+1}=-1\),则检验通过直接开始下一轮检验;否则就继续检验下一个因式,如果所有因式都检验不通过,那么这个素数就可以判定为合数
下面是用于生成任意长度的大素数的java代码:
package BigPrimeInteger;
import java.math.BigInteger;
import java.io.*;
public class BigPrimeInteger {
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String read = null;
try {
read = br.readLine();
}catch(IOException e) {
e.printStackTrace();
}
int l = Integer.parseInt(read); //the length(bits) of Big Prime Integer
BigInteger n=generating(l);
for(;!vrify(n);n=generating(l));
System.out.println("The Big Prime Integer is "+n);
}
public static Boolean vrify(BigInteger n) {
BigInteger t = n.subtract(BigInteger.valueOf(1));
int s = 0;
for(;(t.mod(BigInteger.valueOf(2))).compareTo(BigInteger.valueOf(0))==0;t=t.divide(BigInteger.valueOf(2)),s++);
for(int i = 0;i < 16;i++) { //Vrify in 16 turns
int flag = 0;
BigInteger b = BigInteger.valueOf((int)(Math.random()*1000+2)); //get a random r simply
BigInteger r = modPower(b,t,n); //r = b**t mod n
for(int j = 0;j < s ;j++) {
if(r.compareTo(n.subtract(BigInteger.valueOf(1))) == 0) { //r = n-1
flag = 1;
break;
}else if(j==0 && r.compareTo(BigInteger.valueOf(1))==0) { //j = 0 && r = 1
flag = 1;
break;
}
r = (r.multiply(r)).mod(n); //r = r ** 2
}
if(flag == 0) {
//System.out.println("vrifying failed!");
return false;
}
}
return true;
}
public static BigInteger generating(int l){
StringBuilder value = new StringBuilder();
for(int i=0;i<l;i++) {
if(i==0) { //first bit must be 1
value.append((char)49);
}else if(i==l-1) { //last bit should be 1 to get an odd number
value.append((char)49);
}else {
int v = (int)(Math.random()*2+48);
value.append((char)v);
}
}
String Value = value.toString();
BigInteger Bin = new BigInteger(Value);
//Invert Binary to decimal
BigInteger Dec = BigInteger.valueOf(0);
BigInteger Power = BigInteger.valueOf(1);
for(;Bin.compareTo(BigInteger.valueOf(0)) > 0;Power=Power.multiply(BigInteger.valueOf(2)),Bin=Bin.divide(BigInteger.valueOf(10))) {
BigInteger lsb = Bin.mod(BigInteger.valueOf(10));
Dec = Dec.add(lsb.multiply(Power));
}
//System.out.println("the number is:"+Dec);
return Dec;
}
//Computing r = b^n mod m
public static BigInteger modPower(BigInteger b,BigInteger n,BigInteger m) {
BigInteger r = new BigInteger("1");
String binary = n.toString(2);
for (int i = binary.length() - 1 ; i >= 0 ; i--){
if (binary.charAt(i) == '1'){
r = (r.multiply(b)).mod(m);
b = (b.multiply(b)).mod(m);
}else {
b=(b.multiply(b)).mod(m);
}
}
return r;
}
}