中国剩余定理(m不互素情况Python实现)

博客: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}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

风好衣轻

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

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

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

打赏作者

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

抵扣说明:

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

余额充值