Miller-Rabin算法 素性测试

素性测试

素性测试就是给定一个正整数,然后判断其是否有真因数(除了1和它本身之外的其他正整数)

确定性测试

确定性测试是能够肯定该数的素性,

从2开始到 N \sqrt{N} N 用每个数遍历去和N比划比划,要是能被N整除开则表明N不是素数

优点是确定性

缺点是当N很大的时候时间复杂度大

概率性测试

挑选任意几个数去和N比划比划,如果N能够整除则N一定不是素数.否则N可能是素数

缺点:只能够从概率上保证整数的素性,一个整数通过几次素性测试,只能表明其是一个素数的概率比较大,但是不能断定其就是一个素数

优点:但是如果试验次数够多的话可以极大似然地认为该数就是一个素数.并且时间复杂度要比遍历低得多

比如Fermat素性测试和Miller-Rabin素性测试

Fermat素性测试

费马小定理:

p p p是一个素数,对于任意整数a,都有 a p − 1 ≡ 1   ( m o d    p ) a^{p-1}\equiv 1\ (\mod p) ap11 (modp)

用快速幂计算 a p − 1 m o d    p a^{p-1}\mod p ap1modp

#include <iostream>
#include <algorithm>
using namespace std;

int quick_pow(const int &base, const int &index, const int &p) {
	if (index == 0)
		return 1;
	else if (index == 1)
		return base % p;
	else if (index % 2) {
		int temp = base * base % p;
		return quick_pow(temp, index >> 1, p) * base % p;
	} else {
		int temp = base * base % p;
		return quick_pow(temp, index >> 1, p);
	}
}
const int p = 31;

int main() {
	for (int i = 2; i < p; ++i) {
		cout << quick_pow(i, p - 1, p) << "  ";
	}
	return 0;
}

选定 p = 31 p=31 p=31做实验

运行结果

1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1

均满足费马小定理

选定 N = 30 N=30 N=30做实验

2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29

费马小定理逆定理不成立

即如果对于任选的 a a a,都有 a p − 1 ≡ 1 ( m o d    N ) a^{p-1}\equiv 1(\mod N) ap11(modN),不能说明N是一个素数

伪素数

比如 N = 341 , a = 2 N=341,a=2 N=341,a=2
2 340 ≡ 1 ( m o d    341 ) 2^{340}\equiv 1(\mod 341) 23401(mod341)
但是 N = 341 = 11 × 31 N=341=11\times 31 N=341=11×31不是素数,因此N被称为"伪素数"

这里只是取了一个 a = 2 a=2 a=2,如果取一个 a = 3 a=3 a=3则有 3 340 ≡ 5 ( m o d    341 ) 3^{340} \equiv 5(\mod 341) 33405(mod341),立刻判定341不是素数

于是对于这种情况我们只需要多取几次a去试就可以判定 N N N是不是素数

还是 N = 341 N=341 N=341用刚才的程序计算

image-20220413141109928

卡迈尔克数

但是,就是有这么一类数,你使劲取 a a a,只要是 a a a N N N互素,它都装的跟个孙子一样,都满足 a N − 1 ≡ 1 ( m o d    N ) a^{N-1}\equiv 1(\mod N) aN11(modN),但是N就不是素数

他们叫"卡迈克尔数", 561 = 3 ∗ 11 ∗ 17 561=3*11*17 561=31117就是一个

用下列这些数字去测试561都会得到 a 560 ≡ 1 ( m o d    561 ) a^{560}\equiv 1(\mod 561) a5601(mod561),这些数字都满足 g c d ( a , 561 ) = 1 gcd(a,561)=1 gcd(a,561)=1

2  4  5  7  8  10  13  14  16  19  20  23  25  26  28  29  31  32  35  37  38  40  41  43  46  47  49  50  52  53  56  58  59  61  62  64  65  67  70  71  73  74  76  79  80  82  83  86  89  91  92  94  95  97  98  100  101  103  104  106  107  109  112  113  115  116  118  122  124  125  127  128  130  131  133  134  137  139  140  142  145  146  148  149  151  152  155  157  158  160  161  163  164  166  167  169  172  173  175  178  179  181  182  184  185  188  190  191  193  194  196  197  199  200  202  203  205  206  208  211  212  214  215  217  218  223  224  226  227  229  230  232  233  235  236  239  241  244  245  247  248  250  251  254  256  257  259  260  262  263  265  266  268  269  271  274  277  278  280  281  283  284  287  290  292  293  295  296  298  299  301  302  304  305  307  310  311  313  314  316  317  320  322  325  326  328  329  331  332  334  335  337  338  343  344  346  347  349  350  353  355  356  358  359  361  362  364  365  367  368  370  371  373  376  377  379  380  382  383  386  388  389  392  394  395  397  398  400  401  403  404  406  409  410  412  413  415  416  419  421  422  424  427  428  430  431  433  434  436  437  439  443  445  446  448  449  452  454  455  457  458  460  461  463  464  466  467  469  470  472  475  478  479  481  482  485  487  488  490  491  494  496  497  499  500  502  503  505  508  509  511  512  514  515  518  520  521  523  524  526  529  530  532  533  535  536  538  541  542  545  547  548  551  553  554  556  557  559  560

共319个

也就是说每次任选一个 a ∈ [ 2 , 560 ] a\in[2,560] a[2,560],去测试561的素性,失误概率为 319 559 = 0.570661896243292 \frac{319}{559}=0.570661896243292 559319=0.570661896243292

假设试验k次,那么全都失败的概率是 0.5 7 k 0.57^k 0.57k,成功概率为 1 − 0.5 7 k 1-0.57^k 10.57k

如果使成功概率在 90 90% 90以上,即令 1 − 0.5 7 k ≥ 0.9 1-0.57^k\ge 0.9 10.57k0.9解得到 4.09 4.09 4.09

即尝试4次之后就可以有比较高的把握,决定这个数是素数还是合数了

Miller-Rabin素性测试

费马小定理"逆定理"起死回生

虽然费马小定理的逆定理不成立,但是,如果素性测试次数多了,也能够以很高的概率认为一个数是否是素数

即虽然逆定理不成立但是仍然有一定的利用价值

感觉类似于SSA无法判定全等,但是能够在一定程度上确定三角形的形状

image-20220413143242846

我们现在认为,如果任取 a a a,在我们选取的这几次a中,都满足 a N − 1 ≡ 1 ( m o d    N ) a^{N-1}\equiv 1(\mod N) aN11(modN),则概率认为N是素数

而这样做也是有道理的,刚才卡迈尔克数561在进行4次素性测试之后被测试出是合数的概率已经达到了 90 90% 90

现在问题是,如何科学的选取 a a a

需要用到二次探测定理

二次探测定理

如果 p p p是一个奇素数,则 x 2 ≡ 1 ( m o d    p ) x^2\equiv 1(\mod p) x21(modp)的解为 x ≡ 1 ( m o d    p ) x\equiv 1(\mod p) x1(modp)或者 x ≡ p − 1 ( m o d    p ) x\equiv p-1(\mod p) xp1(modp)

证明:

x 2 ≡ 1 ( m o d    p ) x^2\equiv 1(\mod p) x21(modp)得到 x 2 − 1 ≡ 0 ( m o d    p ) x^2-1\equiv 0(\mod p) x210(modp),即 ( x + 1 ) ( x − 1 ) ≡ 0 ( m o d    p ) (x+1)(x-1)\equiv 0(\mod p) (x+1)(x1)0(modp)

p ∣ ( x + 1 ) ( x − 1 ) p|(x+1)(x-1) p(x+1)(x1),即 ( x + 1 ) ( x − 1 ) = k p , k ∈ Z , k ≠ 0 (x+1)(x-1)=kp,k\in Z,k≠0 (x+1)(x1)=kp,kZ,k=0

p p p是一个素数因此两个乘数之一必然包含 p p p这个因子,

x + 1 x+1 x+1包含p因子时得到 p ∣ ( x + 1 ) p|(x+1) p(x+1),即 x + 1 ≡ 0 ( m o d    p ) x+1\equiv 0(\mod p) x+10(modp),即 x ≡ − 1 ( m o d    p ) x\equiv -1(\mod p) x1(modp),即 x ≡ p − 1 ( m o d    p ) x\equiv p-1(\mod p) xp1(modp)

x − 1 x-1 x1包含p因子时得到 p ∣ ( x − 1 ) p|(x-1) p(x1),即 x − 1 ≡ 0 ( m o d    p ) x-1\equiv 0(\mod p) x10(modp),即 x ≡ 1 ( m o d    p ) x\equiv 1(\mod p) x1(modp)

考虑什么是"奇素数",很庆幸的是除了2之外其他的偶数都是合数,那么奇素数就是除了2之外的任何素数

那么这个定理的适用范围就很广了

二次探测定理+费马小定理"逆定理"

1.假设 N N N是一个待测试的整数(N>2),我们期望他是一个素数,

基于上述期望,素数N一定是奇数,那么 N − 1 N-1 N1是一个偶数

2.考虑一个偶数可以分解成一伙子2和一个奇数的乘积

比如 48 = 16 ∗ 3 = 2 4 ∗ 3 48=16*3=2^4*3 48=163=243,比如 30 = 2 ∗ 15 30=2*15 30=215

则一个偶数可以写为 e v e n = a × 2 b even=a\times 2^b even=a×2b,其中a是一个奇数

N − 1 N-1 N1也是偶数,当然也可以写成 N − 1 = a × 2 b N-1=a\times 2^b N1=a×2b

3.任取一个 x x x,去和N比划比划即通过 x N − 1 ≡ 1 ( m o d    N ) x^{N-1}\equiv 1(\mod N) xN11(modN)去验证N是否是一个素数

x N − 1 − 1 m o d    N x^{N-1} -1\mod{N} xN11modN通过快速幂计算判断结果是否为0

N − 1 = a × 2 b N-1=a\times 2^b N1=a×2b带入上式
x a × 2 b − 1 m o d    N = ( ( x a ) 2 b − 1 ) 2 − 1 m o d    N = ( ( x a ) 2 b − 1 + 1 ) ( ( x a ) 2 b − 1 − 1 ) m o d    N = ( ( x a ) 2 b − 1 + 1 ) ( ( x a ) 2 b − 2 + 1 ) ( ( x a ) 2 b − 2 − 1 ) m o d    N = . . . = ( ( x a ) 2 b − 1 + 1 ) ( ( x a ) 2 b − 2 + 1 ) . . . ( x a + 1 ) ( x a − 1 ) m o d    N \begin{aligned} &x^{a\times 2^b}-1\mod N\\ &=((x^a)^{2^{b-1}})^2-1\mod N\\ &=((x^a)^{2^{b-1}}+1)((x^a)^{2^{b-1}}-1)\mod N\\ &=((x^a)^{2^{b-1}}+1)((x^a)^{2^{b-2}}+1)((x^a)^{2^{b-2}}-1)\mod N\\ &=...\\ &=((x^a)^{2^{b-1}}+1)((x^a)^{2^{b-2}}+1)...(x^a+1)(x^a-1)\mod N \end{aligned} xa×2b1modN=((xa)2b1)21modN=((xa)2b1+1)((xa)2b11)modN=((xa)2b1+1)((xa)2b2+1)((xa)2b21)modN=...=((xa)2b1+1)((xa)2b2+1)...(xa+1)(xa1)modN
如果最后的因数分解式中有一项为0则认为通过了该次素性测试

4.由二次探测定理有
x a m o d    N = 1 x a m o d    N = N − 1 ( x a ) 2 m o d    N = N − 1 . . . ( x a ) 2 b − 1 m o d    N = N − 1 \begin{aligned} x^a \mod N&=1\\ x^a\mod N&=N-1\\ (x^a)^2\mod N&=N-1\\ ...\\ (x^a)^{2^{b-1}}\mod N&=N-1 \end{aligned} xamodNxamodN(xa)2modN...(xa)2b1modN=1=N1=N1=N1
这其中有一个式子成立即可

如果这些式子都没有成立则可以啃腚N不是素数

即满足费马小定理"逆定理"的不一定是素数,但是不满足费马小定理"逆定理"的一定不是素数

算法实现

int gcd(const int &a, const int &b) {
	if (b == 0)
		return a;
	return gcd(b, a % b);
}


int quick_pow(const int &base, const int &index, const int &p) {
	if (index == 0)
		return 1;
	else if (index == 1)
		return base % p;
	else if (index % 2) {
		int temp = base * base % p;
		return quick_pow(temp, index >> 1, p) * base % p;
	} else {
		int temp = base * base % p;
		return quick_pow(temp, index >> 1, p);
	}
}

int miller_rabin(const int &n) {
	if (n < 3 || n % 2 == 0)
		return  2;
	int a = n - 1;
	int b = 0;
	while (a % 2 == 0) {
		++b;
		a /= 2;
	}
	//到此n-1=a*2^b
	const int trial_times = 10;

	int x;
	int base;
	for (int i = 0; i < trial_times; ++i) {
		x = rand() % (n - 2) + 2; //限制x∈[2,n-1]
		int base = quick_pow(x, a, n); //base=x^a
		if (base == 1)
			continue;//如果x=1(mod n)则直接通过本次素性测试
		int j;
		for (int j = 0; j < b; ++j) {
			if (base == n - 1)
				break;//base=n-1(mod n)通过本次素性测试
			base = (long long)base * base % n;
		}
		if (j >= b)
			return 0;//本次所有所有机会都没有把握住,未通过素性测试
	}
	return 1;//通过所有trial_times次素性测试,概率认为n是素数
}

BUUCTF-Alice和Bob

分解质因数98554799767

得到因子101999去做试验

image-20220413150624361

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Miller-Rabin素性测试算法是一种用于判断一个数是否为质数的算法。该算法基于费马小定理,使用随机数进行迭代运算,可以高效地判断一个数是否为质数。 具体来说,该算法将要判断的数记作n,随机选取一个小于n的正整数a,将a与n进行求模运算得到b。如果b等于0或者b等于n-1,则继续选择下一个a。否则,将b平方并对n取模,得到c。如果c等于1或者c等于n-1,则继续选择下一个a。否则,不断平方c并对n取模,直到c等于1或者迭代次数达到了一定阈值。如果c等于1,则n可能是一个合数;如果迭代过程中出现了c等于n-1的情况,则n很可能是一个质数。 为了提高判断的准确性,Miller-Rabin算法会进行多次随机迭代,每次选取不同的随机数a。随机迭代次数越多,判断结果的准确性越高,但计算时间也越长。 总之,Miller-Rabin素性测试算法是一种高效、准确的判断一个数是否为质数的算法,被广泛应用于密码学、计算机科学等领域。 ### 回答2: Miller-Rabin素性测试算法是一种用于判断一个数是否为素数的快速算法。该算法基于费马小定理,利用随机数的特性来判断一个数是否为素数。该算法的优势在于速度快且准确率高,同时能够应对大整数的素性测试。 该算法的具体步骤如下: 1. 首先确定待测试的数n,如果n为偶数,则直接判断n是否等于2,如果是则n为素数,因为2是最小的质数。 2. 若n为奇数,则写成n-1=2^r * d的形式,其中r为非负整数,d为奇数。 3. 接着随机选取一个整数a,且1 < a < n-1。计算a^d mod n,如果结果等于1或n-1,则可以认为n有很大的可能是素数,结束测试。 4. 若结果不等于1或n-1,则重复计算a^(2^j*d) mod n,直到出现下面两种情况之一:结果为1,或者出现了j=0,1,...,r-1时,结果为n-1。 5. 如果满足上述两种情况之一,则认为n有很大的可能是素数,结束测试。否则,重新随机选取一个a,重复上述操作进行测试。 需要说明的是,该算法的准确率可以通过多次测试进行提高。一般来说,重复进行10~20次检验,即可认为检验结果是正确的。 总之,Miller-Rabin素性测试算法是一种简单高效的素数测试算法,可以广泛应用于需要高精度计算的场合。它在加密、密码学等领域中,有着重要的应用价值。 ### 回答3: Miller-Rabin素性测试算法是一种用于判断一个数是否为素数的算法,名字来源于两位发明者:Gary L. Miller和Michael O. Rabin。与其它素数检测算法不同,Miller-Rabin素性测试算法有极高的概率能够正确地识别素数,其准确率可以达到误判的可能性小于$\frac{1}{4}$。 Miller-Rabin素性测试算法的基本原理是利用了费马小定理和欧拉判别法,即对于一个素数$p$和$a<p$,有$a^{p-1} \equiv 1 \pmod{p}$,而对于合数$n=pq$,其中$p,q$为大于1的素数,则在模n下,$a^{n-1} \equiv 1 \pmod{n}$,并且除了一些“小概率事件”外,$a^{(n-1)/2} \equiv \pm 1 \pmod{n}$。 Miller-Rabin 素性测试算法的流程如下: 1.将$n-1$分解成$2^sd$的形式,其中$d$是奇数。 2.对于给定的$a<n$,利用费马小定理,计算$a^d \pmod{n}$。 3.如果$a^d \equiv 1 \pmod{n}$,则认为$n$可能是一个素数,算法结束。 4.对于$0\leq r \leq s-1$,如果$a^{2^rd} \equiv -1 \pmod{n}$,则认为$n$可能是一个素数,算法结束。 5.如果$a^{2^sd} \not \equiv 1 \pmod{n}$或$a^{2^{r}d} \not \equiv -1 \pmod{n}$(其中$0\leq r \leq s-1$),则认为$n$不是素数,算法结束。 通过多次进行以上的步骤,可以提高算法的准确率。 Miller-Rabin素性测试算法是一种在计算机领域经常使用的算法,其特点是计算量较小、正确率较高、可扩展性好。在计算机安全领域,该算法被广泛地应用于RSA算法中,用于加密和解密数据。虽然该算法在某些情况下会出现一定的偏差,但是通过多次计算,可以达到一个非常高的准确率。因此,在实际应用中,Miller-Rabin素性测试算法是一个非常实用的工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灰球球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值