定理

费马小定理

费马小定理是数论中的一个重要定理,在1636年提出.

在学之前先了解一下

剩余类:,亦称同余类,是一种数学的用语,为数论的基本概念之一.设模为n,则根据余数可将所有的整数分为n类,把所有与整数a模n同余的整数构成的集合叫做模n的一个剩余类,记作[a]。并把a叫作剩余类[a]的一个代表元。

完全剩余系:从每个剩余系中各取一个数,得到一个由n个数组成的集合,叫做模n的一个完全剩余系。完全剩余系常用于数论中存在性证明。

同余式:a和b被m除时有相同的余数。 同余式的性质

如果p是一个质数,而整数a不是p的倍数,则

a^(p-1)≡1 mod (p)

两边同乘 a,得:

a^p≡a mod (p)

当然这是a<p的情况

推导

引理1

若a,b,c为任意三个整数,m为正整数,且(m,c)=1,则

a*c≡b*c mod (m)

a≡b mod (m)

证明

a*b=b*c mod (m)可得:

ac-bc≡0 mod (m)可得:

c*(a-b) ≡ 0 mod (m)

**因为(m,c)=1即m,c互质,**c可以约去,

a-b ≡ 0 mod (m)可得:

a≡b mod (m)

引理2

设m是以一个整数且m>1,b是以一个整数且(m,b)=1 如果a[1],a[2],a[3],a[4],…a[m]是模m的一个完全剩余系,则b·a[1],b·a[2],b·a[3],b·a[4],…b·a[m]也构成模m的一个完全剩余系。

所以b·a[1],b·a[2],b·a[3],b·a[4],…b·a[m]构成模m的一个完全剩余系。

构造素数p的完全剩余系1ac8b2711d737ab313e9b851d87d45b4因为,由引理2可得66bac3cd2d5978c59755e415e76459e1也是p的一个完全剩余系。

由完全剩余系的性质,

(p-1)! ≡ (p-1)! * a^(p-1) mod (p)

易知((p-1!),p)=1,同余式两边可约去(p-1)!,得到:

/这里不懂的话,可以去看看同余式/

a**(p-1) ≡ 1 mod (p)

这样就证明了费马小定理。

另外

两边同乘a:

a^p ≡ a mod (p)

这个公式就可以用到RSA解密算法

定理意义

费马小定理是初等数论四大定理(威尔逊定理欧拉定理(数论中的欧拉定理),中国剩余定理(又称孙子定理),费马小定理)之一,在初等数论中有着非常广泛和重要的应用。实际上,它是欧拉定理的一个特殊情况(即883b26489df019421e297d75c8d31d0a

费马大定理

当整数n>2时,关于x,y,z的方程a175f34504994108a7d3f6895a0d8507没有正整数解。

虽然我这个暂时没用到,但是看了定理的证明经历,真的有一种,我站在巨人的肩膀上的感觉

欧拉定理

在数论中,欧拉定理(也称费马-欧拉定理或欧拉φ函数定理)是一个关于同余的性质。

设a,m∈N+, 且gcd(a,m)=1, 则我们有:有aΦ(n) = 1(mod n).

即对于任何互质的正整数a和n,有aΦ(n) = 1(mod n)

φ(n) 为欧拉函数。欧拉定理得名于瑞士数学家莱昂哈德·欧拉。

欧拉定理实际上是费马小定理的推广。

威尔逊定理

在初等数论中,威尔逊定理给出了判定一个自然数是否为质数的充分必要条件。即:当且仅当p为质数时:

(p-1)! ≡ -1 mod (p)

但是由于阶乘是呈爆炸增长的,其结论对于实际操作意义不大.

  • 推论

    (p-2)! ≡ 1 mod (p)

证明

充分性

如果p不是素数,

p=4时:

​ 显然(p-1)! ≡ 6 ≡ 2 mod (p)

p>4时,

​ 若p不是完全平方数则存在两个不等的因数a,b使得ab=p,则(p-1)! ≡ nab ≡ 0 mod (p)

​ 若p是完全 平方数即p=k^2,因为p>4,所以k>2,(k,2k)<p,(p-1)! ≡ n(k*2k) ≡ 2n*k^2 ≡ 0 mod (p)

必要性

若p是素数,取集合A={1,2,3,…,p-1};则A构成模p乘法的简化剩余系,即任意i∈A,存在j∈A,使得:

(i*j) ≡ 1 mod (p)那么A中的元素是不是恰好两两配对呢? 不一定,但只需考虑这种情况

x^2 ≡ 1 mod (p)

解得:

x ≡ 1 mod (p) 或 x ≡ p-1 mod (p)

其余两两配对;故而

(p-1)! ≡ 1*(p-1) ≡ -1 mod (p)

中国剩余定理(孙子定理/GRT)

定义

用现代数学的语言来说明的话,中国剩余定理给出了以下的一元线性同余方程组:

说明

假设整数m1,m2,…,mn其中任两数互质,则对任意的整数:a1,a2,…,an,方程组**(S)**有解,并且通解可以用如下方式构造得到:

  1. 设$M=m_1×m_2×\dots×m_n=\prod\limits_{i=1}^{n} m_i$是整数m1,m2, … ,mn的乘积,并设$m_1,m_2,…,m_n$是除了mi以外的n- 1个整数的乘积。
  2. 设 $t_i=M_i^{-1}$ 为 $M_i$为$m_i$ 模 $m_i$的数论倒数:$t_iM_i \equiv 1 \pmod {m_i},\forall i \in {1,2,…,n}$
  3. 方程组**(S)** 的通解形式为$x=a_1t_1M_1+a_2t_2M_2+\dots+a_nt_nM_n+kM=kM+\sum\limits_{i=1}^{n}a_it_iM_i,\quad k\in \mathbb{Z}$在模$M$的意义下,方程组**(S)** 只有一个解:3f6f9189362ab5f594e57053426006c1

模不两两互质的同余式组可化为模两两互质的同余式组,再用孙子定理直接求解

在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二(除以3余2),五五数之剩三(除以5余3),七七数之剩二(除以7余2),问物几何?”这个问题称为“孙子问题”,该问题的一般解法国际上称为“中国剩余定理”。

1
2
3
4
5
6
7
8
9
10
11
12
#sage
def chinese_remainder(modulus, remainders):
Sum = 0
prod = reduce(lambda a, b: a*b, modulus)
for m_i, r_i in zip(modulus, remainders):
p = prod // m_i
Sum += r_i * (inverse_mod(p,m_i)*p)
return Sum % prod
chinese_remainder([3,5,7],[2,3,2]) #23
/**
Lazzaro @ https://lazzzaro.github.io
*/

扩展中国剩余定理(扩展CRT / ExCRT)

中国剩余定理是用来解同余方程组的,它要求 m1,m2,…,mn其中两两互质。

模不两两互质的同余式组可化为模两两互质的同余式组,再用中国剩余定理直接求解。

形式

给定 n 组非负整数 mi,ai求解关于 x 的方程组的最小非负整数解。

image-20230329001337646

解法

扩展中国剩余定理的方法和中国剩余定理关系不大,我们贪心处理前 i−1 项,然后合并当前方程。

将每个方程拆成若干个方程image-20230329001818573,其中image-20230329001842283为$m_i$的分解式

对每个质数 p ,合并对应的$a+b=1所有方程,从而转化为模数两两互质的情形。若合并过程中出现矛盾,则原方程组无解。

RSA考察点

整数RSA加解密原理

20190325144254-37b9f868-4ec9-1

基于多项式上的RSA加密

多项式RSA倒推

在RSA的基础原理上将多项式带入整数进行分析.

20190325144328-4c620dfa-4ec9-1

采用sage语言解题

我们可以利用sage中的factor()函数分解多项式N得到两个不可约多项式p,q,

1
2
3
4
5
6
7
p = 40031
P = PolynomialRing(Zmod(p), name = 'x')
x = P.gen()
n=24096*x^93 + 38785*x^92 + 17489*x^91 + 9067*x^90 + 1034*x^89 + 6534*x^88 + 35818*x^87 + 22046*x^86 + 12887*x^85 + 445*x^84 + 26322*x^83 + 37045*x^82 + 4486*x^81 + 3503*x^80 + 1184*x^79 + 38471*x^78 + 8012*x^77 + 36561*x^76 + 19429*x^75 + 35227*x^74 + 10813*x^73 + 26341*x^72 + 29474*x^71 + 2059*x^70 + 16068*x^69 + 31597*x^68 + 14685*x^67 + 9266*x^66 + 31019*x^65 + 6171*x^64 + 385*x^63 + 28986*x^62 + 9912*x^61 + 10632*x^60 + 33741*x^59 + 12634*x^58 + 21179*x^57 + 35548*x^56 + 17894*x^55 + 7152*x^54 + 9440*x^53 + 4004*x^52 + 2600*x^51 + 12281*x^50 + 22*x^49 + 17314*x^48 + 32694*x^47 + 7693*x^46 + 6567*x^45 + 19897*x^44 + 27329*x^43 + 8799*x^42 + 36348*x^41 + 33963*x^40 + 23730*x^39 + 27685*x^38 + 29037*x^37 + 14622*x^36 + 29608*x^35 + 39588*x^34 + 23294*x^33 + 757*x^32 + 20140*x^31 + 19511*x^30 + 1469*x^29 + 3898*x^28 + 6630*x^27 + 19610*x^26 + 11631*x^25 + 7188*x^24 + 11683*x^23 + 35611*x^22 + 37286*x^21 + 32139*x^20 + 20296*x^19 + 36426*x^18 + 25340*x^17 + 36204*x^16 + 37787*x^15 + 31256*x^14 + 505*x^13 + 27508*x^12 + 20885*x^11 + 32037*x^10 + 31236*x^9 + 7929*x^8 + 27195*x^7 + 28980*x^6 + 11863*x^5 + 16025*x^4 + 16389*x^3 + 570*x^2 + 36547*x + 10451
c=3552*x^92 + 6082*x^91 + 25295*x^90 + 35988*x^89 + 26052*x^88 + 16987*x^87 + 12854*x^86 + 25117*x^85 + 25800*x^84 + 30297*x^83 + 5589*x^82 + 23233*x^81 + 14449*x^80 + 4712*x^79 + 35719*x^78 + 1696*x^77 + 35653*x^76 + 13995*x^75 + 13715*x^74 + 4578*x^73 + 37366*x^72 + 25260*x^71 + 28865*x^70 + 36120*x^69 + 7047*x^68 + 10497*x^67 + 19160*x^66 + 17939*x^65 + 14850*x^64 + 6705*x^63 + 17805*x^62 + 30083*x^61 + 2400*x^60 + 10685*x^59 + 15272*x^58 + 2225*x^57 + 13194*x^56 + 14251*x^55 + 31016*x^54 + 10189*x^53 + 35040*x^52 + 7042*x^51 + 29206*x^50 + 39363*x^49 + 32608*x^48 + 38614*x^47 + 5528*x^46 + 20119*x^45 + 13439*x^44 + 25468*x^43 + 30056*x^42 + 19720*x^41 + 21808*x^40 + 3712*x^39 + 25243*x^38 + 10606*x^37 + 16247*x^36 + 36106*x^35 + 17287*x^34 + 36276*x^33 + 1407*x^32 + 28839*x^31 + 8459*x^30 + 38863*x^29 + 435*x^28 + 913*x^27 + 36619*x^26 + 15572*x^25 + 9363*x^24 + 36837*x^23 + 17925*x^22 + 38567*x^21 + 38709*x^20 + 13582*x^19 + 35038*x^18 + 31121*x^17 + 8933*x^16 + 1666*x^15 + 21940*x^14 + 25585*x^13 + 840*x^12 + 21938*x^11 + 20143*x^10 + 28507*x^9 + 5947*x^8 + 20289*x^7 + 32196*x^6 + 924*x^5 + 370*x^4 + 14849*x^3 + 10780*x^2 + 14035*x + 15327
e=65537
q1, q2 = n.factor()

计算phi以及d

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
p = 40031
P = PolynomialRing(Zmod(p), name = 'x')
x = P.gen()
n=24096*x^93 + 38785*x^92 + 17489*x^91 + 9067*x^90 + 1034*x^89 + 6534*x^88 + 35818*x^87 + 22046*x^86 + 12887*x^85 + 445*x^84 + 26322*x^83 + 37045*x^82 + 4486*x^81 + 3503*x^80 + 1184*x^79 + 38471*x^78 + 8012*x^77 + 36561*x^76 + 19429*x^75 + 35227*x^74 + 10813*x^73 + 26341*x^72 + 29474*x^71 + 2059*x^70 + 16068*x^69 + 31597*x^68 + 14685*x^67 + 9266*x^66 + 31019*x^65 + 6171*x^64 + 385*x^63 + 28986*x^62 + 9912*x^61 + 10632*x^60 + 33741*x^59 + 12634*x^58 + 21179*x^57 + 35548*x^56 + 17894*x^55 + 7152*x^54 + 9440*x^53 + 4004*x^52 + 2600*x^51 + 12281*x^50 + 22*x^49 + 17314*x^48 + 32694*x^47 + 7693*x^46 + 6567*x^45 + 19897*x^44 + 27329*x^43 + 8799*x^42 + 36348*x^41 + 33963*x^40 + 23730*x^39 + 27685*x^38 + 29037*x^37 + 14622*x^36 + 29608*x^35 + 39588*x^34 + 23294*x^33 + 757*x^32 + 20140*x^31 + 19511*x^30 + 1469*x^29 + 3898*x^28 + 6630*x^27 + 19610*x^26 + 11631*x^25 + 7188*x^24 + 11683*x^23 + 35611*x^22 + 37286*x^21 + 32139*x^20 + 20296*x^19 + 36426*x^18 + 25340*x^17 + 36204*x^16 + 37787*x^15 + 31256*x^14 + 505*x^13 + 27508*x^12 + 20885*x^11 + 32037*x^10 + 31236*x^9 + 7929*x^8 + 27195*x^7 + 28980*x^6 + 11863*x^5 + 16025*x^4 + 16389*x^3 + 570*x^2 + 36547*x + 10451
c=3552*x^92 + 6082*x^91 + 25295*x^90 + 35988*x^89 + 26052*x^88 + 16987*x^87 + 12854*x^86 + 25117*x^85 + 25800*x^84 + 30297*x^83 + 5589*x^82 + 23233*x^81 + 14449*x^80 + 4712*x^79 + 35719*x^78 + 1696*x^77 + 35653*x^76 + 13995*x^75 + 13715*x^74 + 4578*x^73 + 37366*x^72 + 25260*x^71 + 28865*x^70 + 36120*x^69 + 7047*x^68 + 10497*x^67 + 19160*x^66 + 17939*x^65 + 14850*x^64 + 6705*x^63 + 17805*x^62 + 30083*x^61 + 2400*x^60 + 10685*x^59 + 15272*x^58 + 2225*x^57 + 13194*x^56 + 14251*x^55 + 31016*x^54 + 10189*x^53 + 35040*x^52 + 7042*x^51 + 29206*x^50 + 39363*x^49 + 32608*x^48 + 38614*x^47 + 5528*x^46 + 20119*x^45 + 13439*x^44 + 25468*x^43 + 30056*x^42 + 19720*x^41 + 21808*x^40 + 3712*x^39 + 25243*x^38 + 10606*x^37 + 16247*x^36 + 36106*x^35 + 17287*x^34 + 36276*x^33 + 1407*x^32 + 28839*x^31 + 8459*x^30 + 38863*x^29 + 435*x^28 + 913*x^27 + 36619*x^26 + 15572*x^25 + 9363*x^24 + 36837*x^23 + 17925*x^22 + 38567*x^21 + 38709*x^20 + 13582*x^19 + 35038*x^18 + 31121*x^17 + 8933*x^16 + 1666*x^15 + 21940*x^14 + 25585*x^13 + 840*x^12 + 21938*x^11 + 20143*x^10 + 28507*x^9 + 5947*x^8 + 20289*x^7 + 32196*x^6 + 924*x^5 + 370*x^4 + 14849*x^3 + 10780*x^2 + 14035*x + 15327
e=65537
q, p = n.factor()
print(q)
#(x^40 + 13029*x^39 + 14563*x^38 + 9857*x^37 + 14196*x^36 + 37419*x^35 + 12162*x^34 + 18402*x^33 + 27295*x^32 + 4309*x^31 + 13725*x^30 + 12263*x^29 + 1764*x^28 + 27335*x^27 + 7162*x^26 + 12761*x^25 + 11062*x^24 + 8930*x^23 + 29986*x^22 + 29466*x^21 + 25299*x^20 + 26166*x^19 + 15768*x^18 + 27804*x^17 + 6948*x^16 + 13664*x^15 + 9575*x^14 + 21999*x^13 + 9201*x^12 + 12524*x^11 + 8077*x^10 + 37470*x^9 + 10724*x^8 + 24204*x^7 + 10083*x^6 + 25894*x^5 + 1816*x^4 + 39488*x^3 + 69*x^2 + 26125*x + 1193, 1)
print(p)
q, p = q[0], p[0]#可以看出这一步只是将多项式从元组中ti
print(q)
#x^40 + 13029*x^39 + 14563*x^38 + 9857*x^37 + 14196*x^36 + 37419*x^35 + 12162*x^34 + 18402*x^33 + 27295*x^32 + 4309*x^31 + 13725*x^30 + 12263*x^29 + 1764*x^28 + 27335*x^27 + 7162*x^26 + 12761*x^25 + 11062*x^24 + 8930*x^23 + 29986*x^22 + 29466*x^21 + 25299*x^20 + 26166*x^19 + 15768*x^18 + 27804*x^17 + 6948*x^16 + 13664*x^15 + 9575*x^14 + 21999*x^13 + 9201*x^12 + 12524*x^11 + 8077*x^10 + 37470*x^9 + 10724*x^8 + 24204*x^7 + 10083*x^6 + 25894*x^5 + 1816*x^4 + 39488*x^3 + 69*x^2 + 26125*x + 1193
print(p)
phi = (p**q.degree() - 1) * (p**p.degree() - 1)
assert gcd(e, phi) == 1
d = inverse_mod(e, phi)
m = pow(c,d,n)
flag = bytes(m.coefficients())
print("Flag: ", flag.decode())
#NKCTF{We_HaV3_n0th1ng_But_dr3amS}

光滑数

p-1光滑

pollard’s p-1分解算法

如果一个整数的所有素因子都不大与B,我们称这个数为B-Smooth数

设 p-1 是B-Smooth的,可设 $p-1=p_1p_2 \cdots p_n(\forall 1 \leq i \leq n,p_i \leq B)$

若p_1,p_2, \cdots ,p_n两两不同,则$p_1p_2 \cdots p_n \mid B! \Rightarrow (p-1) \mid B! \Rightarrow B!=k(p-1)$

因此 $a^{B!} \equiv a^{k(p-1)} \equiv 1 \pmod p$,假设$N=pq$,计算$\gcd(a^{B!}-1,N)$,只要结果大于 0 小于 $N$,那么结果就为 $p$。

1
2
3
4
5
6
7
8
9
10
11
12
13
from gmpy2 import *
a = 2
k = 2
N =
while True:
a = powmod(a, k, N)
res = gcd(a-1, N)
if res != 1 and res != N:
q = N // res
print("p =",res)
print("q =",q)
break
k += 1

p+1光滑

William’s p+1分解算法。在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def mlucas(v, a, n):
""" Helper function for williams_pp1(). Multiplies along a Lucas sequence modulo n. """
v1, v2 = v, (v**2 - 2) % n
for bit in bin(a)[3:]:
v1, v2 = ((v1**2 - 2) % n, (v1*v2 - v) % n) if bit == "0" else ((v1*v2 - v) % n, (v2**2 - 2) % n)
return v1

for v in count(1):
for p in primegen():
e = ilog(isqrt(n), p)
if e == 0:
break
for _ in xrange(e):
v = mlucas(v, p, n)
g = gcd(v-2, n)
if 1 < g < n:
return g # g|n
if g == n:
break

Coppersmith定理指出在一个 e 阶的 mod(n) 多项式 f(x) 中,如果有一个根小于 n1e,就可以运用一个 O(logn) 的算法求出这些根。

格密码

线性独立空间上有集合 v_1,\cdots,v_n \in \mathbb{R}^n,格(Lattices)就是这些向量的线性组合,用公式表示为:

L={a_1v_1+a_2v_2+\cdots+a_nv_n \mid a_1,a_2,\cdots,a_n \in \mathbb{Z}}。

格 L 的维数等于格中向量的个数。

假定 v_1,v_2,\cdots,v_n 是格 L 的基,w_1,w_2,\cdots,w_n \in L,则必然存在整系数 a_{ij} 使得:

\begin{cases} w_1=a_{11}v_1+a_{12}v_2+\cdots+a_{1n}v_n \ w_2=a_{21}v_1+a_{22}v_2+\cdots+a_{2n}v_n \ \vdots \ w_n=a_{n1}v_1+a_{n2}v_2+\cdots+a_{nn}v_n \end{cases}

这样,格的问题就是矩阵运算了。