费马与欧拉定理

1.费马小定理

知识点:

定义:若p为素数,且gcd(a,p)=1,则a^(p-1) ≡ 1 (mod p)

另一种形式:对于任意一个整数a,a^p ≡ a (mod p)

例题复现:

Ⅰ.题目附件:

#[祥云杯2022 little little fermat]
#费马小定理
#a^(p-1)≡1(mod p)或a^p ≡a (mod p)
from Crypto.Util.number import *
from random import *
from flag import FLAG

BITS = 1024
flag = bytes_to_long(FLAG)

p = getPrime(BITS)
q = getPrime(BITS)
n = p*q
#得到一个1到n之间的随机整数
g = randint(1,n)
a1 = randint(1,n)
a2 = randint(1,n)

k1 = pow(g,a1*(p-1),n)
k2 = pow(g,a2*(q-1),n)

print("n = %s"%n)
print("k1 = %s"%k1)
print("k2 = %s"%k2)

b1 = randint(1,n)
b2 = randint(1,n)

c1 = (pow(k1,b1,n)*flag)%n
c2 = (pow(k1,b2,n)*flag)%n
#断言语句提示 flag是小于n的
assert flag < n

print("c1 = %d"%c1)
print("c2 = %d"%c2)

'''
n = 9858036118742475059433629759400140149605427966433887001108914046633590983713890376353399251885596714047941627222518567515364827340623251995233155278723954926352575221234142199002389819918370754455018819109203109519495493316781422680537687252828642561153832774006286448224016306003631037545643746379044035822029246823483754854602215035869280453855199171915302879406862793807947285344105991067005185493038370882005106069286893165426035453262949739088328689761676541415552066845538243916687080015277379248062286846119847500455125785281216888979581104100416760176854106890525904804003871967844912776926419778292365918733
k1 = 4961356980843219227031667558158760111429474781353239042846946454889308337426649950562701556812878479419482114480334396560017050901408543482904510839046375272618911899662922000275482705215097956326853000314956770940510205507508883917322367747195211326932972446951696070952604655668087834669239815290687449340666091764203568518066586476150861542456340936303824392273004883320273039066213750777751436497551151274574369325153858390731248298056433816285354182588883715211738843801326831297181947562239993323202961410530072969013398669658073337273085171642258091164822631807295793886169033827781164115751086585872189121242
k2 = 8943660577405892997099415246000964332413663135286363632645590478753346989578467429954062835807609942851365774880023144520942029315601785638267996044694835031239940919206726351387647791985293576677117144309222345482756402074345845506698221273703274410853004407629888264128027446878663894377503365831077629911487977796118893231354280680598325548327444053575447407791091256260091884824630356121390983373431984667887019137026219503921285289004358685317477667095203722657823621429988685962573778350234701781053232256494914398637744373081735647622790113318562356606831868682912936768762749860591989864642992367932846710665
c1 = 4115578106197062017294044310891024039554438131787269391154862526142866937938155870549829472424386226484625850457327387070755337288822640509004443484397234720914851433620556887385729540499953724033259937785600491548446806766462413179765702810698096381537513314758346885921106310631278002150697458246447235914052771405341899822588463120295331632180131956205362147784798497203957828308109092025630961803808101730731656980785388965672073473370194469269645377465298620585379296063436880502566076330461976785816470877632107769103280243111778113065038163250625042092690628478547757779278811188187028242267396799577953511519
c2 = 1069417390392712224013484466911946251479515132512683148923109806683426116132220974153759944203026795479272077929265429391851629949467649257513543604050970026412281764244254971122378729482985044535740328359563865949603944075625096242664299209143911115287867129678168308056632406522013494918385694044348658310785409548526884085469813804712945302487796400392901241763662852123731910949146709219711388725430757562836225353975933990961286601256351973981732004724397292031523206145692402321288085912884435326461626793886145952474077975796841103796283781865005879515976167187625178845457630564285181509041968859289264784559
'''

分析:

首先观察和flag有关的语句

c1 = (pow(k1,b1,n)*flag)%n

发现和k1有关,我们再观察和前面和k1有关的代码

k1 = pow(g,a1*(p-1),n)

即k1=g^(a1*(p-1)) %n = (ga1)(p-1) %n,看到p-1,联想到费马小定理(a^(p-1) ≡ 1 (mod p)),但是模数应该为p,我们继续转换

k1=(ga1)(p-1)+k*n

k1 % p=((ga1)(p-1)) % p+(k*n)%p

k1 % p=((ga1)(p-1)) % p ( 因为n=p ** q,所以(k* * n)% p=0)

由费马小定理((ga1)(p-1)) % p=1 % p

即k1 % p=1 % p

k1=1+k * p

k1 - 1= k * p

又因为n=p * q

所以p = gcd(k1-1,n)

我们再看和flag 相关的

c1 = (pow(k1,b1,n) * flag)%n

c1=((k1^b1) +k * n)*flag+k * n

两边同时模p

c1 % p=(((k1^b1) +k * n) * flag)%p+(k * n)%p

c1 % p=(((k1^b1) +k * n) * flag)%p (因为(k * n)% p=0)

c1 % p=(((k1^b1) +k * n)%p) * (flag%p)

c1 % p=((k1^b1) %p) * (flag%p)

c1 % p=(((k1%p)^b1) %p) * (flag%p)

从上面的推理我们知道k1 % p=1 % p

所以c1 % p=flag % p

又因为有断言

assert flag < n

所以flag小于p(这里有点不太理解,断言是flag<n,那么flag % n=flag是必然的,但是这个推导出来是 flag % p,怎么就推出了flag % p=flag,这里p和n也不等价呀),则flag % p=flag

flag =c1 % p

解密代码:

import gmpy2
import libnum

n = 9858036118742475059433629759400140149605427966433887001108914046633590983713890376353399251885596714047941627222518567515364827340623251995233155278723954926352575221234142199002389819918370754455018819109203109519495493316781422680537687252828642561153832774006286448224016306003631037545643746379044035822029246823483754854602215035869280453855199171915302879406862793807947285344105991067005185493038370882005106069286893165426035453262949739088328689761676541415552066845538243916687080015277379248062286846119847500455125785281216888979581104100416760176854106890525904804003871967844912776926419778292365918733
k1 = 4961356980843219227031667558158760111429474781353239042846946454889308337426649950562701556812878479419482114480334396560017050901408543482904510839046375272618911899662922000275482705215097956326853000314956770940510205507508883917322367747195211326932972446951696070952604655668087834669239815290687449340666091764203568518066586476150861542456340936303824392273004883320273039066213750777751436497551151274574369325153858390731248298056433816285354182588883715211738843801326831297181947562239993323202961410530072969013398669658073337273085171642258091164822631807295793886169033827781164115751086585872189121242
k2 = 8943660577405892997099415246000964332413663135286363632645590478753346989578467429954062835807609942851365774880023144520942029315601785638267996044694835031239940919206726351387647791985293576677117144309222345482756402074345845506698221273703274410853004407629888264128027446878663894377503365831077629911487977796118893231354280680598325548327444053575447407791091256260091884824630356121390983373431984667887019137026219503921285289004358685317477667095203722657823621429988685962573778350234701781053232256494914398637744373081735647622790113318562356606831868682912936768762749860591989864642992367932846710665
c1 = 4115578106197062017294044310891024039554438131787269391154862526142866937938155870549829472424386226484625850457327387070755337288822640509004443484397234720914851433620556887385729540499953724033259937785600491548446806766462413179765702810698096381537513314758346885921106310631278002150697458246447235914052771405341899822588463120295331632180131956205362147784798497203957828308109092025630961803808101730731656980785388965672073473370194469269645377465298620585379296063436880502566076330461976785816470877632107769103280243111778113065038163250625042092690628478547757779278811188187028242267396799577953511519
c2 = 1069417390392712224013484466911946251479515132512683148923109806683426116132220974153759944203026795479272077929265429391851629949467649257513543604050970026412281764244254971122378729482985044535740328359563865949603944075625096242664299209143911115287867129678168308056632406522013494918385694044348658310785409548526884085469813804712945302487796400392901241763662852123731910949146709219711388725430757562836225353975933990961286601256351973981732004724397292031523206145692402321288085912884435326461626793886145952474077975796841103796283781865005879515976167187625178845457630564285181509041968859289264784559

p = gmpy2.gcd(k1 - 1, n)
flag = (int)(c1 % p)
print(libnum.n2s(flag))

2.欧拉定理

知识点:

欧拉定理:若gcd(a,m)=1,则a^φ(m) =1 mod m

相关知识:

欧拉函数:即φ(n),表示的是小于等于 n 和 n 互质的数的个数。

性质:

  • 欧拉函数是积性函数,即若gcd(m,n)=1,则φ(mn)=φ(m) * φ(n)

    特别的,若n为奇数,则φ(2n)=φ(n)

  • 若n=pk,其中p为质数,则φ(n)=pk-p^(k-1)

扩展欧拉定理:

扩展

例题复现:

欧拉定理的主要应用是RSA加密,所以就找了道RSA的题,但是和欧拉定理关联不是很紧密

已知:

dp ≡ d mod (p-1)

e = 65537
n = 248254007851526241177721526698901802985832766176221609612258877371620580060433101538328030305219918697643619814200930679612109885533801335348445023751670478437073055544724280684733298051599167660303645183146161497485358633681492129668802402065797789905550489547645118787266601929429724133167768465309665906113
dp = 905074498052346904643025132879518330691925174573054004621877253318682675055421970943552016695528560364834446303196939207056642927148093290374440210503657
c = 140423670976252696807533673586209400575664282100684119784203527124521188996403826597436883766041879067494280957410201958935737360380801845453829293997433414188838725751796261702622028587211560353362847191060306578510511380965162133472698713063592621028959167072781482562673683090590521214218071160287665180751

原文链接:https://blog.csdn.net/weixin_43790779/article/details/108539518

分析:

e * d =1 mod (p-1)*(q-1)

dp ≡ d mod (p-1)

则e * dp = e * d mod (p-1)

e * d=k1 * (p-1) * (q-1) + 1 = k2 * (p-1) + e * dp

e * dp =(p-1) * (k1*(p-1)-k2)+1

又因为dp ≡ d mod (p-1), 那么dp一定小于(p-1)

则dp也小于p,那么e>(k1(q-1)-k2)

解密代码:

import gmpy2
import binascii
e = 65537
n = 248254007851526241177721526698901802985832766176221609612258877371620580060433101538328030305219918697643619814200930679612109885533801335348445023751670478437073055544724280684733298051599167660303645183146161497485358633681492129668802402065797789905550489547645118787266601929429724133167768465309665906113
dp = 905074498052346904643025132879518330691925174573054004621877253318682675055421970943552016695528560364834446303196939207056642927148093290374440210503657
c = 140423670976252696807533673586209400575664282100684119784203527124521188996403826597436883766041879067494280957410201958935737360380801845453829293997433414188838725751796261702622028587211560353362847191060306578510511380965162133472698713063592621028959167072781482562673683090590521214218071160287665180751

for i in range(1,e):
    if (e*dp-1)%i == 0 and n%((e*dp-1)//i+1)==0:
        q = n//((e*dp-1)//i+1)
        phi = (q-1)*((e*dp-1)//i)
        d = gmpy2.invert(e,phi)
        m = gmpy2.powmod(c,d,n)

print(binascii.unhexlify(hex(m)[2:]))


忙着复习,没学太多

posted @ 2025-07-23 14:18  xiehou~  阅读(28)  评论(0)    收藏  举报