crypto杂记(1)
记录一下寒假做的题目
Dicectf[commitment-issues]
from random import randrange
from Crypto.Util.number import getPrime, inverse, bytes_to_long, GCD
flag = b'dice{?????????????????????????}'
n = 5
def get_prime(n, b):
p = getPrime(b)
while GCD(p - 1, n) != 1:
p = getPrime(b)
return p
p = get_prime(n, 1024)
q = get_prime(n, 1024)
N = p*q
phi = (p - 1)*(q - 1)
e = 0xd4088c345ced64cbbf8444321ef2af8b
d = inverse(e, phi)
def sign(message):
m = bytes_to_long(message)
return pow(m, d, N)
def commit(s, key, n):
return (s + key) % N, pow(key, n, N)
def reveal(c1, c2, key, n):
assert pow(key, n, N) == c2
return (c1 - key) % N
r = randrange(1, N)
s = sign(flag)
c1, c2 = commit(s, r, n)
print(f'N = {hex(N)}')
print(f'c1 = {hex(c1)}')
print(f'c2 = {hex(c2)}')
利用RSA原理进行数字签名
由条件
\(s+r=c1 mod(N),r^5=c2 mod(N),s=m^d mod(N)\)
\(=>m=(c1-r)^e mod(n)\)
利用快速幂算法对右式约化,r最高次为4
用该式子得m的1~5次的表达式消掉r后得到m的5次方表达式
进行copper,注意的是此处copper对根的大小要求,利用已知的m的部分信息适当减小m
代码如下
N = 0xba8cb3257c0c83edf4f56f5b7e139d3d6ac8adf71618b5f16a02d61b63426c2c275ce631a0927b2725c6cc7bdbe30cd8a8494bc7c7f6601bcee5d005b86016e79919e22da4c431cec16be1ee72c056723fbbec1543c70bff8042630c5a9c23f390e2221bed075be6a6ac71ad89a3905f6c706b4fb6605c08f154ff8b8e28445a7be24cb184cb0f648db5c70dc3581419b165414395ae4282285c04d6a00a0ce8c06a678181c3a3c37b426824a5a5528ee532bdd90f1f28b7ec65e6658cb463e867eb5280bda80cbdb066cbdb4019a6a2305a03fd29825158ce32487651d9bfa675f2a6b31b7d05e7bd74d0f366cbfb0eb711a57e56e6db6d6f1969d52bf1b27b
c1 = 0x75240fcc256f1e2fc347f75bba11a271514dd6c4e58814e1cb20913195db3bd0440c2ca47a72efee41b0f9a2674f6f46a335fd7e54ba8cd1625daeaaaa45cc9550c566f6f302b7c4c3a4694c0f5bb05cd461b5ca9017f2eb0e5f60fb0c65e0a67f3a1674d74990fd594de692951d4eed32eac543f193b70777b14e86cf8fa1927fe27535e727613f9e4cd00acb8fab336894caa43ad40a99b222236afc219397620ca766cef2fe47d53b07e302410063eae3d0bf0a9d67793237281e0bfdd48255b58b2c1f8674a21754cf62fab0ba56557fa276241ce99140473483f3e5772fcb75b206b3e7dfb756005cec2c19a3cb7fa17a4d17f5edd10a8673607047a0d1
c2 = 0xdb8f645b98f71b93f248442cfc871f9410be7efee5cff548f2626d12a81ee58c1a65096a042db31a051904d7746a56147cc02958480f3b5d5234b738a1fb01dc8bf1dffad7f045cac803fa44f51cbf8abc74a17ee3d0b9ed59c844a23274345c16ba56d43f17d16d303bb1541ee1c15b9c984708a4a002d10188ccc5829940dd7f76107760550fac5c8ab532ff9f034f4fc6aab5ecc15d5512a84288d6fbe4b2d58ab6e326500c046580420d0a1b474deca052ebd93aaa2ef972aceba7e6fa75b3234463a68db78fff85c3a1673881dcb7452390a538dfa92e7ff61f57edf48662991b8dd251c0474b59c6f73d4a23fe9191ac8e52c8c409cf4902eeaa71714
e = 0xd4088c345ced64cbbf8444321ef2af8b
PR.<x>=PolynomialRing(Zmod(N))
f=c1-x
n=x^5-c2
def pow1(f,e,n):
h=1
while e:
if e%2:
e=e-1
h=h*f%n
else:
e=e//2
f=f^2%n
return h
g=pow1(f,e,n)
G=[]
for i in range(1,6):
G.append(list(g^i%n))
A=Matrix([G[0],G[1],G[2],G[3],G[4]])
v=vector(Zmod(N),[1,0,0,0,0])
s=v*A^(-1)
ff=s[0]*x+s[1]*x^2+s[2]*x^3+s[3]*x^4+s[4]*x^5-1
ff =ff(256*x+177412069566112213731253013760310652613044638443561381240821131913554034813).monic()
print(ff.small_roots(X=2^200))
Dicectf[rejected]
#!/usr/local/bin/python
import secrets
class LFSR:
def __init__(self, key, taps):
self._s = key
self._t = taps
def _sum(self, L):
s = 0
for x in L:
s ^= x
return s
def _clock(self):
b = self._s[0]
self._s = self._s[1:] + [self._sum(self._s[p] for p in self._t)]
return b
def bit(self):
return self._clock()
class RNG:
def __init__(self, lfsr, N, nbits):
self.lfsr = lfsr
self.N = N
self.nbits = nbits
if not (pow(2, 27) < N < pow(2, 31)):
raise ValueError("modulus is too big or small")
K = pow(2, nbits) // N
self.cutoff = K * N
def get_random_nbit_integer(self):
res = 0
for i in range(self.nbits):
res += self.lfsr.bit() << i
return res
def get_random_integer_modulo_N(self):
count = 1
while True:
x = self.get_random_nbit_integer()
if x < self.cutoff:
return x % self.N, count
count += 1
taps = [60, 58, 54, 52, 48, 47, 45, 43, 38, 36, 32, 28, 22, 21, 13, 9, 8, 5, 2, 0]
n = 64
with open("flag.txt", "r") as f:
flag = f.read()
if __name__ == "__main__":
print("Welcome to the unbiased random number factory!")
N = int(input("What modulus would you like to use? Choose between 2^27 and 2^31: "))
key = secrets.randbits(n)
key_bits = [(key >> i)&1 for i in range(n)]
lfsr = LFSR(key_bits, taps)
rng = RNG(lfsr, N, 32)
for _ in range(1024):
c = input("Enter your command (R,F): ")
if c.startswith("R"):
x,t = rng.get_random_integer_modulo_N()
print("creating this random number took {} attempts".format(t))
elif c.startswith("F"):
seed = int(input("what was my seed?"))
if seed == key:
print(flag)
exit(0)
else:
print("unsupported command")
一个LFSR的oracle
分析代码可知对于LFSR的连续32位如果大于cutoff会在cout处+1直到小于cutoff
最后让我们输入LFSR的原始状态获取flag,故我们希望通过上述的操作获取生成流中的部分bit的信息
一个想法就是使得cutoff=0b11···1(x个1)011···1,这样的话如果得知生成的32bits数据大于cutoff我们相当于知道生成数据的前面x+1的bit数据均为1
由于概率的问题我们使x尽可能小(尽管x取的很大的时候一次成功获取的已知数据更多,但是为了保证在1024次里收集到64个数据我们还是让x尽可能小)
from tqdm import tqdm
for i in tqdm(range(2**27,2**31)):
K = pow(2, 32) // i
cutoff = K * i
mask=0b11101111111111111111111111111111
if cutoff==mask:
print(i)
#366048349
最后解决离散的lfsr恢复问题即可,因为是离散的所以构造的矩阵不一定满秩,多跑几次即可
值得注意的是这个lfsr的写法真的好奇怪呀😢,调了我一下午,结果是代码看错了,输出是按照小端序输出的
代码如下:
from pwn import *
from sage.all import *
p=remote('mc.ax',31669)
mask='1010010011000100000001100000100010001010000101011000101000101000'
M=Matrix.zero(64)
v=vector(GF(2),64)
for i in range(63):
M[i,i+1]=1
for i in range(64):
M[63,i]=int(mask[i])
v[i]=int(mask[i])
M=Matrix(GF(2),M)
p.recvuntil(':')
p.sendline('366048349')
k=[]
n=0
for i in range(1024):
p.recvuntil(':')
p.sendline('R')
p.recvuntil('took ')
t=int(p.recv(1))
if t==2:
s1=n*32
for j in range(1,5):
k.append(s1-j-32)
if t==3:
s1=n*32
s2=(n+1)*32
for j in range(1,5):
k.append(s1-j-32)
k.append(s2-j-32)
if t==4:
s1=n*32
s2=(n+1)*32
s3=(n+2)*32
for j in range(1,5):
k.append(s1-j-32)
k.append(s2-j-32)
k.append(s3-j-32)
n+=t
print(k)
print(len(k))
if len(k)>64:
break
B=[]
for i in range(64):
vv=v*(M**k[i])
vv=list(vv)
B.append(vv)
B=Matrix(GF(2),B)
V=vector(GF(2),64)
for i in range(64):
V[i]=1
m=(B**(-1))*V
m=list(m)[::-1]
pay=''
for i in range(64):
pay+=str(m[i])
pay=int(pay,2)
p.recvuntil(':')
p.sendline('F')
p.sendline(str(pay))
p.interactive()
Dicectf[pow-pow]
#!/usr/local/bin/python
from hashlib import shake_128
# from Crypto.Util.number import getPrime
# p = getPrime(1024)
# q = getPrime(1024)
# n = p*q
n = 20074101780713298951367849314432888633773623313581383958340657712957528608477224442447399304097982275265964617977606201420081032385652568115725040380313222774171370125703969133604447919703501504195888334206768326954381888791131225892711285554500110819805341162853758749175453772245517325336595415720377917329666450107985559621304660076416581922028713790707525012913070125689846995284918584915707916379799155552809425539923382805068274756229445925422423454529793137902298882217687068140134176878260114155151600296131482555007946797335161587991634886136340126626884686247248183040026945030563390945544619566286476584591
T = 2**64
def is_valid(x):
return type(x) == int and 0 < x < n
def encode(x):
return x.to_bytes(256, 'big')
def H(g, h):
return int.from_bytes(shake_128(encode(g) + encode(h)).digest(16), 'big')
def prove(g):
h = g
for _ in range(T):
h = pow(h, 2, n)
m = H(g, h)
r = 1
pi = 1
for _ in range(T):
b, r = divmod(2*r, m)
pi = pow(pi, 2, n) * pow(g, b, n) % n
return h, pi
def verify(g, h, pi):
assert is_valid(g)
assert is_valid(h)
assert is_valid(pi)
assert g != 1 and g != n - 1
m = H(g, h)
r = pow(2, T, m)
assert h == pow(pi, m, n) * pow(g, r, n) % n
if __name__ == '__main__':
g = int(input('g: '))
h = int(input('h: '))
pi = int(input('pi: '))
verify(g, h, pi)
with open('flag.txt') as f:
print(f.read().strip())
相当漂亮的一个题目了,比赛的时候想到了一部分,然后就跑偏了,看wp复现一下
代码介绍的是一个VDF(可验证延迟函数),我们显然不能在正常的时间里面通过题目提供的prove()函数来获得数据
故我们需要采取另外的方式来欺骗服务器
很容易想到的是统一底数,这就能将原来的同余方程转换为幂次的同余方程
我们需要满足h=pimgr mod(n) ,我们取底数为2,指数分别为h0,p0,g0
=>\(2^{h_0}=2^{mp_0+g_0r} mod(n)\) => \(h_0=mp_0+g_0r\mod(φ(n))\)
最简单的想法就是使得h0=0同时mp0+g0r=0
注意到m是由h,g唯一确定所以在h0,g0取定后m就已经确定,所以我们希望通过调整p0的值使得等式成立
即p0=-\(\frac{g_0r}{m}\)
所以我们最后是希望能够在固定h=1的情况下找到m|g0的解
注意到shake128产生的数不超过128bits,如果能找到光滑的m同时g0取遍历的素数的乘积,那我们就能够解决问题
shake128的参数位置要注意一下,刚开始写反了跑出来一直通不过验证
代码如下:
from hashlib import shake_128
import gmpy2
from tqdm import tqdm
n=20074101780713298951367849314432888633773623313581383958340657712957528608477224442447399304097982275265964617977606201420081032385652568115725040380313222774171370125703969133604447919703501504195888334206768326954381888791131225892711285554500110819805341162853758749175453772245517325336595415720377917329666450107985559621304660076416581922028713790707525012913070125689846995284918584915707916379799155552809425539923382805068274756229445925422423454529793137902298882217687068140134176878260114155151600296131482555007946797335161587991634886136340126626884686247248183040026945030563390945544619566286476584591
def encode(x):
return x.to_bytes(256, 'big')
def H(g, h):
return int.from_bytes(shake_128(encode(g) + encode(h)).digest(16), 'big')
def getg0():
a=gmpy2.fac(100)
p=1
for i in tqdm(range(2**20)):
if gmpy2.is_prime(i):
p=p*i
return a*p
T=2**64
g0=getg0()
g=int(pow(2,g0,n))
while 1:
m=H(g,1)
if g0%m==0:
print(g)
r=pow(2,T,m)
p0=-g0*r//m
p=pow(2,p0,n)
print(p)
break
else:
g0=2*g0
g=pow(g,2,n)
show
描述:Lucas has just discovered a way to efficiently calculate f(x, k) = 2 * f(x - 1, k) + k * f(x - 2, k), f(0, k) = 0, f(1, k) = 1, and is excited to use it for cryptography! Can you crack his code?
with open("flag.txt", "r") as fin:
flag = fin.read().strip()
size = 7
flag = [flag[i:i + size] for i in range(0, len(flag), size)] # split text into groups of size
for i in range(len(flag)):
cur = 0
flag[i] = flag[i][::-1] # reverse flag[i]
for j in flag[i]:
cur <<= 8
cur += ord(j)
flag[i] = cur
def f(p, k, mod):
# returns f(11^(11^p), k) % mod as defined in the problem statement
pass
def generate():
# generates appropriate p, k, and mod
pass
with open("enc.txt", "w") as fout:
for i in flag:
p, k, mod = generate()
enc = f(p, k, mod) ^ i
fout.write(str(p) + " " + str(k) + " " + str(mod) + " " + str(enc) + "\n")
对卢卡斯数列取模运算,我们将二阶线性递推写成矩阵的形式
\(\left[\begin{matrix}a_n\\a_{n-1}\end{matrix}\right]=\left[\begin{matrix}2&k\\1&0\end{matrix}\right]\left[\begin{matrix}a_{n-1}\\a_{n-2}\end{matrix}\right]\)mod(N)
=>\(\left[\begin{matrix}a_n\\a_{n-1}\end{matrix}\right]=\left[\begin{matrix}2&k\\1&0\end{matrix}\right]^{n-1}\left[\begin{matrix}a_{1}\\a_{0}\end{matrix}\right]\)mod(N)
考虑模N意义下的矩阵乘法循环群,生成元为\(\left[\begin{matrix}2&k\\1&0\end{matrix}\right]\),随便试了一组发现循环群的阶是N-1
根据这个结论,化简f的计算过程
代码如下
c=[]
mmm=[]
for i in range(0,len(c),4):
p=c[i]
k=c[i+1]
n=c[i+2]
cc=c[i+3]
A=Matrix(GF(n),[[2,k],[1,0]])
B=Matrix(GF(n),[[1],[0]])
f, e = zip(*factor(n-1))
t=pow(11,p,euler_phi(n-1))
ff=pow(11,t,n-1)
m=str(list(A^(ff-1)*B)[0])[1:-1]
m=bin(int(m)^^cc)[2:].rjust(56,'0')
k=[]
for i in range(0,len(m),8):
k.append(int(m[i:i+8],2))
k=k[::-1]
mmm.extend(k)
print(bytes(mmm))
HWS[crypto_Elgamal]
from Crypto.Util.number import *
from key import FLAG
def keygen(size):
q = getPrime(80)
k = getPrime(944)
while True:
p = q * k + 1
if isPrime(p):
break
k += 1
g = 2
while True:
if pow(g, q, p) == 1:
break
g += 1
A = getRandomInteger(size) % q
B = getRandomInteger(size) % q
x = getRandomInteger(size) % q
h = pow(g, x, p)
return (g, h, A, B, p, q), (x)
def rand(A, B, q):
global rand_state
rand_state, ret = (A * rand_state + B) % q, rand_state
return ret
def encrypt(pubkey, m):
g, h, A, B, p, q = pubkey
assert 0 < m <= p
r = rand(A, B, q)
c1 = pow(g, r, p)
c2 = (m * pow(h, r, p)) % p
return (c1, c2)
rand_state = getPrime(1024)
pubkey, privkey = keygen(1024)
m = bytes_to_long(FLAG)
c1, c2 = encrypt(pubkey, m)
c1_, c2_ = encrypt(pubkey, m)
print(c1, c2)
print(c1_, c2_)
s0 = 543263588863771657634119
s1 = 628899245716105951093835
s2 = 78708024695487418261582
s3 = 598971435111109998816796
s4 = 789474285039501272453373
assert ( A * s0 + B ) % q == s1
assert ( A * s1 + B ) % q == s2
assert ( A * s2 + B ) % q == s3
assert ( A * s3 + B ) % q == s4
p = 65211247300401312530078141569304950676358489059623557848188896752173856845051471066071652073612337629832155846984721797768267868868902023383604553319793550396610085424563231688918357710337401138108050205457200940158475922063279384491022916790549837379548978141370347556053597178221402425212594060342213485311
g = 27642593390439430783453736408814717946185190497201679721975757020767271070510268596627490205095779429964809833535285315202625851326460572368018875381603399143376574281200028337681552876140857556460885848491160812604549770668188783258592940823128376128198726254875984002214053523752696104568469730021811399216
h = 54585833166051670245656045196940486576634589000609010947618047461787934106392112227019662788387352615714332234871251868259282522817042504587428441746855906297390193418159792477477443129333707197013251839952389651332058368911829464978546505729530760951698134101053626585254469108630886768357270544236516534904
c1 = 60724920570148295800083597588524297283595971970237964464679084640302395172192639331196385150232229004030419122038089044697951208850497923486467859070476427472465291810423905736825272208842988090394035980454248119048131354993356125895595138979611664707727518852984351599604226889848831071126576874892808080133
c2 = 48616294792900599931167965577794374684760165574922600262773518630884983374432147726140430372696876107933565006549344582099592376234783044818320678499613925823621554608542446585829308488452057340023780821973913517239972817669309837103043456714481646128392677624092659929248296869048674230341175765084122344264
c1_ = 42875731538109170678735196002365281622531058597803022779529275736483962610547258618168523955709341579773947887175626960699426438456382655370090748369934296474999389316334717699127421889816721511602392591677377678759026657582648354688447456509292302633971842316239774410380221303269351351929586256938787054867
c2_ = 64829024929257668640929285124747107162970460545535885047576569803424908055130477684809317765011143527867645692710091307694839524199204611328374569742391489915929451079830143261799375621377093290249652912850024319433129432676683899459510155157108727860920017105870104383111111395351496171846620163716404148070
利用Lcg解出A,B,q
由\(mg^{rx}=c_1mod(p),mg^{(Ar+B)x}=c_2mod(p),h=g^xmod(p)\)
=>\(c_1^Ag^{Bx}=c_2m^{A-1}mod(p)\) =>\(m^{A-1}=c_1^Ah^Bc_2^{-1}mod(p)\)
由于\(g^q=1mod(p)\) =>\(m^q=c_1^qmod(p)\)
gcd(q,A-1)=1 利用共模攻击解出m
import gmpy2
p = 65211247300401312530078141569304950676358489059623557848188896752173856845051471066071652073612337629832155846984721797768267868868902023383604553319793550396610085424563231688918357710337401138108050205457200940158475922063279384491022916790549837379548978141370347556053597178221402425212594060342213485311
g = 27642593390439430783453736408814717946185190497201679721975757020767271070510268596627490205095779429964809833535285315202625851326460572368018875381603399143376574281200028337681552876140857556460885848491160812604549770668188783258592940823128376128198726254875984002214053523752696104568469730021811399216
h = 54585833166051670245656045196940486576634589000609010947618047461787934106392112227019662788387352615714332234871251868259282522817042504587428441746855906297390193418159792477477443129333707197013251839952389651332058368911829464978546505729530760951698134101053626585254469108630886768357270544236516534904
c1 = 60724920570148295800083597588524297283595971970237964464679084640302395172192639331196385150232229004030419122038089044697951208850497923486467859070476427472465291810423905736825272208842988090394035980454248119048131354993356125895595138979611664707727518852984351599604226889848831071126576874892808080133
c2 = 48616294792900599931167965577794374684760165574922600262773518630884983374432147726140430372696876107933565006549344582099592376234783044818320678499613925823621554608542446585829308488452057340023780821973913517239972817669309837103043456714481646128392677624092659929248296869048674230341175765084122344264
c1_ = 42875731538109170678735196002365281622531058597803022779529275736483962610547258618168523955709341579773947887175626960699426438456382655370090748369934296474999389316334717699127421889816721511602392591677377678759026657582648354688447456509292302633971842316239774410380221303269351351929586256938787054867
c2_ = 64829024929257668640929285124747107162970460545535885047576569803424908055130477684809317765011143527867645692710091307694839524199204611328374569742391489915929451079830143261799375621377093290249652912850024319433129432676683899459510155157108727860920017105870104383111111395351496171846620163716404148070
s0 = 543263588863771657634119
s1 = 628899245716105951093835
s2 = 78708024695487418261582
s3 = 598971435111109998816796
s4 = 789474285039501272453373
t1=s0-s1
t2=s1-s2
t3=s2-s3
t4=s3-s4
p1=t1*t3-t2^2
p2=t2*t4-t3^2
q=gmpy2.gcd(p1,p2)
a=t2*gmpy2.invert(t1,q)%q
b=(s1-a*s0)%q
m1=pow(c2,a,p)*pow(h,b,p)*gmpy2.invert(c2_,p)%p
m2=pow(c2,q,p)
d,u,v=xgcd(a-1,q)
m=pow(m1,u,p)*pow(m2,v,p)%p
print(m)
Cyber Grabs[Unbr34k4bl3]
from Crypto.Util.number import *
from secret import *
assert (x>2 and x%2 == 0)
assert (isPrime(e1) and isPrime(e2))
def functor():
val1 , val2 = 0,0
for i in range(x+1):
val1 += pow(e1,i)
for j in range(3):
val2 += pow(e2,j)
assert (val1 == val2)
def keygen():
while True:
p,q = [getStrongPrime(1024) for _ in range(2)]
if p%4==3 and q%4==3:
break
r = 2
while True:
r = r*x
if r.bit_length()>1024 and isPrime(r-1):
r = r-1
break
return p,q,r
functor()
p,q,r = keygen()
n = p*q*r
print(f"p:{p}")
print(f"q:{q}")
ip = inverse(p,q)
iq = inverse(q,p)
c1 = pow(bytes_to_long(flag[0:len(flag)//2].encode('utf-8')),e1,n)
c2 = pow(bytes_to_long(flag[len(flag)//2:].encode('utf-8')),e2,n)
print(f"n:{n}",f"ip:{ip}",f"iq:{iq}",f"c1:{c1}",f"c2:{c2}",sep="\n")
一开始就给我整个数论问题,开始用整除关系没搞出来,后来利用不等式放缩解出来了
要解个不定方程p,q均为素数,2|x,1+p+p2=1+q+···+qx,求(p,q,x)
=>p(p+1)=\(\frac{q(q^x-1)}{q-1}\) =>p(p+1)(q-1)=q(qx-1)
∵x%2=0 令x=2t(t>1) =>p(p+1)(q-1)=q(qt+1)(qt-1)
∵p为素数 =>p|q or p|qt+1 or p|qt-1
等式两边大小估计可知p|qt+1 否则LHS<RHS
=>p≤qt+1 =>q(qt+1)(qt-1)≤(qt+1)(qt+2)(q-1)
=>q2t+1-q≤q2t+1+3qt+1+2q-q2t-3qt-2
=>q2t+3qt+2≤3qt+1+3q(※) 构造f(q,t)=q2t+3qt-3qt+1-3q+2
固定t求偏导 f'=2tq2t-1-3(t+1)qt+3tqt-1-3=qt(2tqt-1-3(t+1))+t+(3tqt-1-3)
在q≥2且t≥2的情况下f'>0
故f(q,t)≥f(2,t)=22t-3×2t+1+3×2t-4
关于t的函数单调增易证=>f(q,t)≥f(2,2)=0
结合(※) =>等号成立 故(p,q,x)=(5,2,4)
解决了这个问题后利用所给条件分解n然后就是RSA的正常解密了,涉及一个rabin
ps:这个地方在做题的时候完全不需要证明,直接在小范围爆破即可
代码如下
import gmpy2
r=10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087
n=267362205744654830055585746250317245125479735269853713372687604676608285629127977574310510441358104169652444917329986129098240750401425257601282268733834091593200445244725460613298199140690597119199763970064359847666802255456013592631532853951273286284878230893809080250386646832110506402289378691079462364884899662707502858007857457806853302449695351229004051902617728418480990341155900565542195318206284041182555579388392863474548687784403795738945489219689610881075059037192656116884269582257788959555951074322245033492165406470004019896763472332962300128378758934128374039937693688718317737657946435827745981009467876838127075176808098467305627394472135213533754815713468369763665632168616054982745256773112537152292099369137072982289095951236065885648588670059655452986720063260146952425798150221407866669449837430999779776718047668562687216933053536759554900663226163021145439386115076821161003965334731127329486856711654741683760749336235855319144478194501034662638054193682000283319917096796971
nr=n//r
ip=65491313526527942082900846848440586365393305192439699810712229312474732937502934334921061033822729150056656630858908294464249602368303871630644420585085642204592189073314730233318796675949142968346807766087775542461078648703191450221286915401606901781524237580646760734493950360267230729125514156671619347616
iq=97034409222811998555255396847918439343239825222504093225438959283117395075159811973044380473862026342866489725039905931430797650466599952795602909181290621103197493223080488468216279214006070950393096075839913101687588555346523517436421698916141195686143520143972735534402754157166545851899187305574703394138
c1=103687839591259628532585171241634220321003599759860095236990117623065664975385083122971507015385215246948744078816596026772744294701233346732383214113445480056584639282712898073542520168025667980980057512174927564196375256682206601425714094930670415979638437119896258396784978194294581076901000507291277729888015413204446158926865037965291316577726275211006619643531704449499845352147547986667837681877488120093302675775792115380914560935989896453159186176952126083066619414338359303033325593504442257083571002878083287293828310810483726711816109297046925744157605591270761804522735216774801135342322479770391505911100485259078064775709124730966391629468398187269096529671187877954443617005248499140455160589093379715757808387108825458007733207099871941497372539249357162437077379731766825184301649010270921003130776410066972952756983157217280397531412843118202051922048479332111760976091302376602674590153876045380552746826056547929265785960676415919260117136285580971488670143947003566230254837742519
c2=171159809874438596904787534111610260851529969068192878049771299710688449419966698428704180474774734112617652498954998301185232279153644173070897800123538474930545720934844727376637921072749901149514789723141795042182408704214998390482343965532559149095934231081729041402598776401575561653660624208366051273601230345754361771067242657825194926706328336322383296953817730346429591680463526267530372572332663327157636745578067246913529155120642276894180354494816411827468256127607558873938451944866168777913756913920336763454881108023708284527878322162463081091624350220308273550298342755582044860337692076513609120342318151660103532559583052954725303030103413034880155621982581677423267299780543045375467310718078800411397780269409147558121862038983169509828944551199620508493589091401498720419409158373805529997911655270528589050795214164221299581104149954423726171539700223299445034347915430838395255700425648686205603925507474877720680274914513203566997846945579395522000899007446797091893230195801607
s=gmpy2.isqrt((nr+1)**2-4*ip*iq*nr)
p=(nr+1-s)//(2*ip)
q=nr//p
phi=(p-1)*(q-1)*(r-1)
print(gmpy2.gcd(5,phi))
PR.<x>=PolynomialRing(Zmod(p))
f=x^2-c1
aes1=f.roots()
PR.<x>=PolynomialRing(Zmod(q))
f=x^2-c1
aes2=f.roots()
PR.<x>=PolynomialRing(Zmod(r))
f=x^2-c1
aes3=f.roots()
for i1 in aes1:
for i2 in aes2:
for i3 in aes3:
print(crt([int(i1[0]),int(i2[0]),int(i3[0])],[p,q,r]))
print('------------')
e2=5
d2=gmpy2.invert(e2,phi)
m=pow(c2,d2,n)
print(m)
Cyber Grabs[t0t13nt]
from sympy import totient
flag = REDACTED
def functor(n):
val = 0
for j in tqdm(range(1,n+1)):
for i in range(1,j+1):
val += j//i * totient(i)
return val
lest = []
for i in flag:
lest.append(functor(ord(i)*6969696969))
print(lest)
又是一道数学题
需要你化简\(\sum_{j=1}^n\sum_{i=1}^{j}[\frac{j}{i}]φ(i)\)
我们熟知关于欧拉函数的恒等式\(\sum_{d|n}φ(d)=n\)
故\(\sum_{i=1}^n\sum_{d|i}φ(d)=\frac{n(n+1)}{2}\)
从组合的意义上理解可知\(\sum_{i=1}^n\sum_{d|i}φ(d)=\sum_{i=1}^{n}[\frac{n}{i}]φ(i)\)
故\(\sum_{j=1}^n\sum_{i=1}^{j}[\frac{j}{i}]φ(i)=\sum_{j=1}^n\frac{j(j+1)}{2}=\frac{n(n+1)}{4}+\frac{n(n+1)(2n+1)}{12}\)
代码如下
f=open('output_1.txt','r')
def decrypt(n):
s=(n*(n+1)//2+n*(n+1)*(2*n+1)//6)//2
return s
a=6969696969
c=[54751499983812600001595164999947606, 99964672809872376546137976728298625, 53109066146380481534971079770844564, 58137259942365444979479997549034855, 83599752542227961885740894770768516, 61659800043905527133538302215438384, 83599752542227961885740894770768516, 51499811650564080459894297372806965, 53109066146380481534971079770844564, 85819100646121058196943447618203070, 105003982813844976161353898313196914, 8400749730877624158255771399988559, 6240424741484609266392009977454864, 73075186383278314052649120872243371, 7485157899144949411682111055590430, 48379486424936974614387887472243260, 59881263192906899425738121667861480, 90374940243693329303922258576171375, 75104938249367345681206971604866080, 54751499983812600001595164999947606, 9388117281207654321254731172830840, 6638633268326718341544242944266781, 6240424741484609266392009977454864, 75104938249367345681206971604866080, 32264483340980969722020637386275054, 48379486424936974614387887472243260, 75104938249367345681206971604866080, 7485157899144949411682111055590430, 92712108866793232034695893485547544, 7485157899144949411682111055590430, 83599752542227961885740894770768516, 48379486424936974614387887472243260, 54751499983812600001595164999947606, 7485157899144949411682111055590430, 15496388930720047282261773301643045, 8400749730877624158255771399988559, 58137259942365444979479997549034855, 48379486424936974614387887472243260, 88077383691706059347171006086863620, 6240424741484609266392009977454864, 48379486424936974614387887472243260, 7934151132541799341665122998944580, 73075186383278314052649120872243371, 7934151132541799341665122998944580, 102463675364526450047988025312160540, 7485157899144949411682111055590430, 48379486424936974614387887472243260, 73075186383278314052649120872243371, 7485157899144949411682111055590430, 110209866655316842092627871164477875]
m=[]
for i in c:
for j in range(128):
if i==decrypt(j*a):
m.append(j)
print(bytes(m))