威尔逊定理

威尔逊定理

数论四大定理之一
威尔逊定理是以英格兰数学家爱德华·华林的学生约翰·威尔逊命名的,尽管这对师生未能给出证明。华林于1770年提出该定理,1773年由拉格朗日首次证明。威尔逊定理是判定一个自然数是否为素数的充分必要条件,它也是数论四大定理(威尔逊定理、欧拉定理、孙子定理、费马小定理)之一。

18世纪中叶,约翰·威尔逊发现了一个极为罕见的关系:取从1到某个质数所有连续正整数的乘积,例如从1乘到11,即11的阶乘11!,除去11这个数,得10!。无疑10!不能被11整除。

然而,如果给10!加上1的话,1×2×3×4×5×6×7×8×9×10+1=3628801,怎么也不会想到,3628801却能被11整除(3628801÷11=329891)。类似地,从1到质数7的阶乘7!中略去7,再加上1,得1×2×3×4×5×6+1=721,721也能被7整除(721÷7=103)。那么其他的质数是不是也有这样的规律呢?

威尔逊定理可以简述为:

当p为质数时,(p-1)!+1能被p整除。

威尔逊定理逆定理可以简述为:

若一个数 (p-1)!+1 能被 p 整除,那么 p 为质数。

在rsa中的应用

例题:[RoarCTF2019]babyRSA

题目:

import sympy
import random

def myGetPrime():
    A= getPrime(513)
    print(A)
    B=A-random.randint(13,15)
    print(B)
    return sympy.nextPrime((B!)%A)
p=myGetPrime()
#A1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467234407
#B1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467140596

q=myGetPrime()
#A2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858418927
#B2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858351026

r=myGetPrime()

n=p*q*r
#n=85492663786275292159831603391083876175149354309327673008716627650718160585639723100793347534649628330416631255660901307533909900431413447524262332232659153047067908693481947121069070451562822417357656432171870951184673132554213690123308042697361969986360375060954702920656364144154145812838558365334172935931441424096270206140691814662318562696925767991937369782627908408239087358033165410020690152067715711112732252038588432896758405898709010342467882264362733
c=pow(flag,e,n)
#e=0x1001
#c=75700883021669577739329316795450706204502635802310731477156998834710820770245219468703245302009998932067080383977560299708060476222089630209972629755965140317526034680452483360917378812244365884527186056341888615564335560765053550155758362271622330017433403027261127561225585912484777829588501213961110690451987625502701331485141639684356427316905122995759825241133872734362716041819819948645662803292418802204430874521342108413623635150475963121220095236776428
#so,what is the flag?

首先根据题意得:
p = sympy.nextPrime((B1!)%A1)
q = sympy.nextPrime((B2!)%A2)

又,B和A都是素数,根据威尔逊定理可得:
( A1 -1 )! ≡ -1 ( mod A1 )
( B1 -1 )! ≡ -1 ( mod B1 )
( A2 -1 )! ≡ -1 ( mod A2 )
( B2 -1 )! ≡ -1 ( mod B2 )
本题的主要部分就是(B!)%A,然后由于B很大B!不易求解,此时想到运用威尔逊定理,即(A-1)!=-1modA,那么这个式子就可以转化成B!*k=-1modA,其中k=(A-1)!/B!,等式两边同时乘上 k − 1 k^{-1} k1,即 B ! m o d    A = − k − 1 m o d    A B! \mod A=-k^{-1} \mod A B!modA=k1modA,这样就求出了(B!)%A,紧接着p和q就出来了。

也就是说威尔逊定理将原本求(B!)%A的难题,转变成了求(A-1)!/B!,而(A-1)!/B!可以理解为从B+1乘到A的乘法,当然这里A是大于B+1的,这点在题目中B等于A减去一个随机数的时候有提现到。

以下是运用威尔逊定理的脚本:

def wision(b, a):
    k = 1
    for i in range(b+1, a):
        k = (k*i) % a
    return ((-1)*gmpy2.invert(k, a))%a

通过威尔逊定理求出p,q,r,之后就是RSA密码的常规解密。

p = sympy.nextprime(wision(B1, A2))
q = sympy.nextprime(wision(B2, A2))
r = (n//p)//q
phi = (p-1)*(q-1)*(r-1)
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m))

但是不知道何种原因,没有得到flag
大佬的代码放一下👇

import sympy
import gmpy2

A1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467234407
B1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467140596
A2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858418927
B2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858351026
e=0x1001
c=75700883021669577739329316795450706204502635802310731477156998834710820770245219468703245302009998932067080383977560299708060476222089630209972629755965140317526034680452483360917378812244365884527186056341888615564335560765053550155758362271622330017433403027261127561225585912484777829588501213961110690451987625502701331485141639684356427316905122995759825241133872734362716041819819948645662803292418802204430874521342108413623635150475963121220095236776428
n=85492663786275292159831603391083876175149354309327673008716627650718160585639723100793347534649628330416631255660901307533909900431413447524262332232659153047067908693481947121069070451562822417357656432171870951184673132554213690123308042697361969986360375060954702920656364144154145812838558365334172935931441424096270206140691814662318562696925767991937369782627908408239087358033165410020690152067715711112732252038588432896758405898709010342467882264362733

def mydecrypt(A,B):
    ans=1
    temp=gmpy2.powmod(-1,1,A)
    #print(temp)
    for i in range(B+1,A):
        ans=(ans*gmpy2.invert(i,A))%A
    return (ans*temp)%A

p=sympy.nextprime(mydecrypt(A1,B1))
q=sympy.nextprime(mydecrypt(A2,B2))
r=n//p//q
phi=(p-1)*(q-1)*(r-1)
d=gmpy2.invert(e,phi)
flag=gmpy2.powmod(c,d,n)
import binascii
print(binascii.unhexlify(hex(flag)[2:]))

目前没看明白哪里的问题

另一道例题

# -*- coding:utf-8 -*-
#Author: Lazzaro
 
from Crypto.Util.number import getPrime,isPrime
from math import gamma
import random
 
def nextPrime(n):
    n += 2 if n & 1 else 1
    while not isPrime(n):
        n += 2
    return n
 
def getNewPrime():
    A = getPrime(512)
    B = nextPrime(A - random.randint(1e4,1e5))
    return nextPrime(gamma(B+2)%A)
    
p = getNewPrime()
q = getNewPrime()
r = getNewPrime()
n = p * q ** 2 * r ** 3
e = 0x10001
c = pow(flag,e,n)
 
 
#pA=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723982789
#pB=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723922147
#qA=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477881291
#qB=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477807457
#n=4451906216583258787166698210560165433649728830889954633721198623488802305844782492171757604711145165920462286487680020347239300947225371917344589502941576734875830871998499135120227347066586066943289430156378296665669974728569678779668142712266780949126509440672273927433367293606776081254094682033167575930701870261219046464773708974194213798032346187463443317770758989273370488582862531630356263732232300508706676725203199729764016766683870925164232508407363688370458877688991733322055785233669885166225464068579486683574954699370175267031949720967812902215635630884502987094547523361027411501285252862476410213277925430392164226297316310465146003494714018456407793759170649913180823814850170639706664167149612984905056804131124522209409607977589884632999710708045656852149371030046919242039957767777840304466948549383597755811307383659188216421501912831203089570725388153416013596114462069777713822433178099904907224119
#c=1996198968748552041728429851810599627895157160099076033250854211280074825148767841655949210593646824507865483166496070951130337321360509148527292165245205219296211294789087358959553387392928560150390604911087085313000622842025416521494799132969818997182731021267942464323979261593380113740152841984062184326431879167516288834455296913822921806893572566867611541664848820247889274979245086440402996661226884320574824077910315143756471444347386795428338020162169391827182914043434253974549636668126789355991920452920806351939782281969098470635517019120996509180703896707990501216102290302162705699788457579330150149320348175742131887213742989509004374645723471497302400169849858253644606818874098604333865973357374444445825761600866472906771935670261641342221394488068630591190697667016958881530367047928341661857241378511420562236766886349565409774340321441504290366223243635878057759623855735794209219474650425139791831374

注意,这里的gamma函数即伽马函数
在这里插入图片描述另外,关于欧拉函数,如果 m = p ∗ q m=p*q m=pq φ ( m ) = φ ( p ) ∗ φ ( q ) \varphi(m)=\varphi(p)*\varphi(q) φ(m)=φ(p)φ(q)
如果 m = p e m=p^e m=pe,其中p是素数,e是正整数, φ ( m ) = p e − p e − 1 \varphi(m)=p^e-p^{e-1} φ(m)=pepe1,特例e=2, φ ( m ) = p ∗ ( p − 1 ) \varphi(m)=p*(p-1) φ(m)=p(p1)

解题跟上面那道题一样的思路,代码如下:

import sympy
import gmpy2
from Crypto.Util.number import long_to_bytes

e = 0x10001
pA=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723982789
pB=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723922147
qA=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477881291
qB=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477807457
n=4451906216583258787166698210560165433649728830889954633721198623488802305844782492171757604711145165920462286487680020347239300947225371917344589502941576734875830871998499135120227347066586066943289430156378296665669974728569678779668142712266780949126509440672273927433367293606776081254094682033167575930701870261219046464773708974194213798032346187463443317770758989273370488582862531630356263732232300508706676725203199729764016766683870925164232508407363688370458877688991733322055785233669885166225464068579486683574954699370175267031949720967812902215635630884502987094547523361027411501285252862476410213277925430392164226297316310465146003494714018456407793759170649913180823814850170639706664167149612984905056804131124522209409607977589884632999710708045656852149371030046919242039957767777840304466948549383597755811307383659188216421501912831203089570725388153416013596114462069777713822433178099904907224119
c=1996198968748552041728429851810599627895157160099076033250854211280074825148767841655949210593646824507865483166496070951130337321360509148527292165245205219296211294789087358959553387392928560150390604911087085313000622842025416521494799132969818997182731021267942464323979261593380113740152841984062184326431879167516288834455296913822921806893572566867611541664848820247889274979245086440402996661226884320574824077910315143756471444347386795428338020162169391827182914043434253974549636668126789355991920452920806351939782281969098470635517019120996509180703896707990501216102290302162705699788457579330150149320348175742131887213742989509004374645723471497302400169849858253644606818874098604333865973357374444445825761600866472906771935670261641342221394488068630591190697667016958881530367047928341661857241378511420562236766886349565409774340321441504290366223243635878057759623855735794209219474650425139791831374

def wision(a,b):
    k = 1
    for i in range(b+1, a):
        k = (k*i) % a
    return ((-1)*gmpy2.invert(k, a))%a


p = sympy.nextprime(wision(pA, pB+1))
q = sympy.nextprime(wision(qA, qB+1))
r = gmpy2.iroot(n//(p*q**2), 3)[0]
phi = (p-1)*q*(q-1)*(r**3-r**2)
d = gmpy2.invert(e, phi)
m = gmpy2.powmod(c, d, n)

print(long_to_bytes(m))

这次没问题可以得到flag
但是还是不知道上面那道错哪了

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值