博客:https://blog.slight-wind.com/
中国剩余定理(Python)
做题的时候在网上找了半天 m 不互素时的 Python 代码,可惜没有找到,还是自己整吧…
m 两两互素时
简单的模板:
from Crypto.Util.number import long_to_bytes
from functools import reduce
from gmpy2 import gcd,invert
Num=3 #一次同余式的个数
m = [ , , ]
a = [ , , ]
M=reduce(lambda x,y: x*y, m)
Mi=[M//i for i in m]
t=[invert(Mi[i], m[i]) for i in range(Num)]
x=0
for i in range(Num):
x+=a[i]*t[i]*Mi[i]
print(long_to_bytes(x%M))
原理和相关证明很容易找到,就不赘述了。
m 之间不互素时
这种情况是有最小解x满足条件,很多博客也讲的很详细,比如 这一篇 ,但是没找到 Python 写的…
与 m 互素时一样,m 不互素时显然也会有无限个解 X = k * M + x ,但是 m 之间不互素时,在模 M 的意义下也可能会有多个解。
x 为最小解,m1 , m2 , … , mn 的最小公倍数为 L ,X < M ,易知 X = x + k * L ,枚举 k 就可以了。
这是我写的 V&N 公开赛的一道密码题的 exp:
import hashlib
from functools import reduce
from gmpy2 import gcd
from Crypto.Util.number import *
Num=8
m = [284461942441737992421992210219060544764, 218436209063777179204189567410606431578, 288673438109933649911276214358963643204, 239232622368515797881077917549177081575, 206264514127207567149705234795160750411, 338915547568169045185589241329271490503, 246545359356590592172327146579550739141, 219686182542160835171493232381209438048]
a = [273520784183505348818648859874365852523, 128223029008039086716133583343107528289, 5111091025406771271167772696866083419,33462335595116820423587878784664448439, 145377705960376589843356778052388633917, 128158421725856807614557926615949143594,230664008267846531848877293149791626711, 94549019966480959688919233343793910003]
gbs=reduce(lambda x,y: x*y//gcd(x,y), m)#最小公倍数
p = reduce(lambda x,y: x*y, m)
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def china(num):
m1,a1,lcm=m[0],a[0],m[0]
for i in range(1,num):
m2=m[i]
a2=a[i]
c=a2-a1
g,k1,k2=egcd(m1,m2)
lcm=lcm*m[i]//gcd(lcm,m[i])
if c%g :
print('No Answer!')
return 0
x0=c//g*k1
t=m2//g
x0=(x0%t+t)%t
a1+=m1*x0
m1=m2//g*m1
return a1
ans=china(Num)
i=0
x=ans+i*gbs
while x<p:
flag = "flag{" + hashlib.sha256(str(x).encode()).hexdigest() + "}"
if ("4b93deeb" in flag):print(flag)
i+=1
x=ans+i*gbs
最终输出:flag{fa71921acdc2a756897d6b0c7ee41a7397386de2e7cde5b6adb525414b93deeb}