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))
posted @ 2022-02-09 15:03  hash_hash  阅读(344)  评论(0编辑  收藏  举报