WEEK 4

NKCTF_Crypto

一.eZ_Math

题目:

from Crypto.Util.number import *
from secret import flag

m1, m2 = bytes_to_long(flag[:len(flag)//2]), bytes_to_long(flag[len(flag)//2:])
p, q, r, s = [getStrongPrime(512) for _ in range(4)]
e = 0x10001

n = p * q * r * s
x = pow(q + r, p, n)
y = pow(p * q + r, p, n)
z = pow(s + 1, m1, s ** 3)
c = pow(m2, e * (s - 1), n)

print(f'{n = }')
print(f'{x = }')
print(f'{y = }')
print(f'{z = }')
print(f'{c = }')

在这里插入图片描述

from Crypto.Util.number import *
import gmpy2

n = 16063619267258988011034805988633616492558472337115259037200126862563048933118401979462064790962157697989038876156970157178132518189429914950166878537819575544418107719419007799951815657212334175336430766777427972314839713871744747439745897638084891777417411340564312381163685003204182743581513722530953822420925665928135283753941119399766754107671729392716849464530701015719632309411962242638805053491529098780122555818774774959577492378249768503656934696409965037843388835948033129997732058133842695370074265039977902884020467413323500218577769082193651281154702147769044514475692164145099161948955990463002411473013
x = 3021730035236300354492366560252387204933590210661279960796549263827016146230329262559940840168033978439210301546282150367717272453598367244078695402717500358042032604007007155898199149948267938948641512214616076878271433754986480186150178487625316601499002827958344941689933374158456614113935145081427421623647242719093642478556263121508238995676370877385638074444859047640771188280945186355013165130171802867101829647797879344213688981448535289683363612035513789240264618036062440178755665951650666056478493289870170026121826588708849844053588998886259091357236645819074078054595561158630194224419831088510266212458
y = 8995787142441643101775260550632842535051686960331455373408888374295557050896156890779515089927839904014859222004906681231525326673182671984194300730575609496770604394218160422560576866112460837985407931067753009696969997384839637927957848613356269534870170452152926447601781637641134982178028922559652443398183848786034348994249923007092159192374765197460466878587635412657807328348343062302127490267456095927890461140420639805398464266081441243108883599713672104446500850203779995739675784794478089863001309614674686652597236324659979849324914804032046113978246674538411441434320732570934185579553749616238819583998
z = 1283646988194723153191718393109711130382429329041718186548715246082834666179475883560020086589684603980734305610989683434078096863563033623169666389076830792095374856743015929373461198718962686411467443788047511292138922700655772772117855226419561159782734009961921473456332468653898105909729309377890721920937410781006337057478451806364879679045839945032594716202888196404203782734864187890231653321470085251
c = 4988583141177813116287729619098477713529507701428689219486720439476625736884177254107631282807612305211904876847916760967188201601494592359879509876201418493870112712105543214178376471651715703062382025712952561985261461883133695993952914519494709871429166239968478488380137336776740647671348901626710334330855078254188539448122493675463406596681080368929986034772169421577420193671300532508625180845417164660544286332963072804192276425664877337357353975758574262657585309762422727680851018467657523970318042829660721433987195369353660020476598195375492128671951807024027929490113371463210453342974983253996717176870
e = 0x10001

q = GCD(y-x,n)
p = GCD(y-x+q,n)//q
r = (x-q)%p
s = n//(p*q*r)
m1 = (z%s**2-1)//s
m1 = long_to_bytes(m1)
phi = (p-1)*(q-1)*(r-1)
d = inverse(e*(s-1)//4,phi)
m2 = pow(c,d,p*q*r)
m2 = gmpy2.iroot(m2,4)
m2 = long_to_bytes(m2[0])
print(m1+m2)

总结:做完这道题之后才意识到数论对于密码的作用,所以决定本周的其他题目也做的数学性强一点

CNSS2023夏令营

一.cyclic group

题目:

from Crypto.Util.number import *
from secret import flag  ## secret is a local file, flag is unknown to you

p = getPrime(1024)
m = bytes_to_long(flag)
e = getPrime(512)
c = 1
for i in range(e):
    c *= m   
    c %= p

print('p =', p)
print('e =', e)
print('c =', c)

'''
p = 134994058501022133829793113756450648798182080773931273262418798773562440624857106163310596590759607340807163876539520282102901165977612358002331391089851066812663281502398201018663717659213732276911585751665516661301930410244101046617666467321456930120075263141242119953757880295718825254018040413826880843763
e = 12927587515508549311645504126259938927362775210786958053823827936884288861306268493761629822045846148118653977616493302703588300283111036739875491883808759
c = 46583597391505868783218970830156160405763802889228578452060606957717500160663392513770581781157233604314178955789908254475724009921579917780127649365498088467948777432657442293331639740286781008682662602974865442032279819833194544535317410041738966384493317240586005380761492762248899523164168679218802048162
'''

提示:

可以找到我藏在循环群中的flag吗?

根据题目中的代码以及提示

c = 1
for i in range(e):
    c *= m   
    c %= p

可以得知:c = pow(m,e,p),因为正常的形式为:c = pow(m,e,n),由于题目也没有给出 n ,则我们试想把 p 换成 n,phi 就是(p-1)

通过大胆尝试,最后获得flag

from Crypto.Util.number import *

p = 134994058501022133829793113756450648798182080773931273262418798773562440624857106163310596590759607340807163876539520282102901165977612358002331391089851066812663281502398201018663717659213732276911585751665516661301930410244101046617666467321456930120075263141242119953757880295718825254018040413826880843763
e = 12927587515508549311645504126259938927362775210786958053823827936884288861306268493761629822045846148118653977616493302703588300283111036739875491883808759
c = 46583597391505868783218970830156160405763802889228578452060606957717500160663392513770581781157233604314178955789908254475724009921579917780127649365498088467948777432657442293331639740286781008682662602974865442032279819833194544535317410041738966384493317240586005380761492762248899523164168679218802048162

d = inverse(e,p-1)
print(long_to_bytes(pow(c,d,p)))

二.cnss娘的代码Ⅰ

题目:

from Crypto.Util.number import * 
from secret import flag  

m = bytes_to_long(flag)
key = []
for i in range(4):
    key.append(getPrime(128))
    
secret = []
for i in range(4):
    secret.append(m % key[i])
    
print('key =', key)
print('secret =', secret)

'''
key = [179283057970236760812385016853348861313, 243730152305882610684268424505624182831, 276375013783217805474364273321195364813, 338363147025326331069698214354955107607]
secret = [42312333420922777926503668120694248887, 188911830445106862831548334980052602782, 202272400826094059912187609891368651300, 16939666639933430404336668949000187621]

提示:

cnss娘写了一段感觉意义不明的代码,你能帮她找到flag吗?

观察题目可知这道题考察的是中国剩余定理,由于之前在BUUCTF NEWSTAR做过类似的题目,故直接写代码即可得出flag

from Crypto.Util.number import *
from sympy.ntheory.modular import crt

N = [179283057970236760812385016853348861313, 243730152305882610684268424505624182831, 276375013783217805474364273321195364813, 338363147025326331069698214354955107607]
C = [42312333420922777926503668120694248887, 188911830445106862831548334980052602782, 202272400826094059912187609891368651300, 16939666639933430404336668949000187621]

M = crt(N,C)[0]
flag = long_to_bytes(M)

print(flag)

三.RSA Ⅰ

题目:

from Crypto.Util.number import *
from secret import flag

m = bytes_to_long(flag)
p = getPrime(512)
q = getPrime(512)
n = p*q


e=65537
c = pow(m,e,n)
mask = getPrime(512)
print(f'c = {c}')
print(f'n = {n}')
print(f'mask = {mask}')
print(p|mask)
print(p&mask)

#c = 64949799997326584007544788513993497249594769744995858720976935000014197232306799968807213667255871030075230919683627404813038995304033226711042639925325815395252041199650244620814678407788637241064396318107929964286966081900052163098825412222835465966640369222321472659135622216530966800717417560715221275591
#n = 106750680418525866311589462967145265327203310954735134383588573660691518247034803380198999333962213971657327515092895034635965957228036264848532931376595751503164297061094511187060069380048933807326213369464059701069965785612620370291933800122445966488267918733547599024267999872488061941892122230382138042783
#mask = 12270330408774238331968219216635392599519489634111741706590917012819298856158311310855782884352875794146685141255943386189197362902992928716839082520848927
#13112112110892990771168306272793201342028151601627796725313855804865001339738164412798270175076178951452110894792943424133718769511979832250960465757056799
#11731832079629748669705816329667815638461774924918417348984676937048335348013101619038697983623814812736529127108466295988845879378764866277739393693264401

提示:

Can you factorize n ?

先看题目提示,直接把 n 扔网站分解,果然分解不了,然后观察代码,发现使用了 与 和 或 这两个关系词

与=1 m=p=1 ; 与=0 或=1 m=1,p=0 m=0,p=1 ; 与=0 或=0 m=0,p=0

根据这些信息我们就可以将之转换为二进制数,然后爆破出p来,最后得到flag

from Crypto.Util.number import *

c = 64949799997326584007544788513993497249594769744995858720976935000014197232306799968807213667255871030075230919683627404813038995304033226711042639925325815395252041199650244620814678407788637241064396318107929964286966081900052163098825412222835465966640369222321472659135622216530966800717417560715221275591
n = 106750680418525866311589462967145265327203310954735134383588573660691518247034803380198999333962213971657327515092895034635965957228036264848532931376595751503164297061094511187060069380048933807326213369464059701069965785612620370291933800122445966488267918733547599024267999872488061941892122230382138042783
mask = 12270330408774238331968219216635392599519489634111741706590917012819298856158311310855782884352875794146685141255943386189197362902992928716839082520848927
g1 = 13112112110892990771168306272793201342028151601627796725313855804865001339738164412798270175076178951452110894792943424133718769511979832250960465757056799
g2 = 11731832079629748669705816329667815638461774924918417348984676937048335348013101619038697983623814812736529127108466295988845879378764866277739393693264401
e = 65537

#将这些信息转换为二进制数
strmask = bin(mask)[2:]
strg1 = bin(g1)[2:]
strg2 = bin(g2)[2:]

#爆破过程
strp = []
for i in range(len(strmask)):
    if(strg2[i] == "1"):
        strp.append("1")
    else:
        if(strg1[i] == "1" and strmask[i] == "0"):
            strp.append("1")
        elif(strg1[i] == "1" and strmask[i] == "1"):
            strp.append("0")
        else:
            strp.append("0")

p = int("".join(strp),2)

q= n//p       
phi = (p-1)*(q-1)
d = inverse(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m))

四.cnss娘的代码 Ⅱ

题目:

from Crypto.Util.number import *
from secret import flag  

p = 149223181221309438217142971731290162048502071683234438807455153639165894737664410172266260056805353255967638568356843140306590887937
m = bytes_to_long(flag)
g = 7
h = pow(g, m, p)

print('h =', h)

'''
106414500627466044750537699496116452216938505790285966641538755230718107434518035561502262320845803494959251547594598724676292650073

提示:

cnss娘最近在研究一类数论中的难题,你可以帮助她吗?
Hint: SageMath的使用可以让你事半功倍

根据分析代码可知,这个是离散对数的问题,并且题目也提示了使用SageMath解密

在这里插入图片描述

from Crypto.Util.number import *

p = 149223181221309438217142971731290162048502071683234438807455153639165894737664410172266260056805353255967638568356843140306590887937
g = 7
h = 106414500627466044750537699496116452216938505790285966641538755230718107434518035561502262320845803494959251547594598724676292650073

m = discrete_log(mod(h,p),mod(g,p))
#discrete_log():用于计算离散对数。离散对数问题是指在离散数学中给定一个底数和模数,找到满足 g^x ≡ h (mod p) 的指数 x。这个函数的调用使用了两个参数:第一个参数是mod(h, p),即底数取模后的结果;第二个参数是mod(g, p),即指数取模后的结果。
print(long_to_bytes(m))

RC4学习

RC4(Ron Rivest Cipher 4)是一种流加密算法,密钥长度可变。它加解密使用相同的密钥,属于对称加密算法,是使用最广泛的序列密码。RC4是一种基于非线性数据表变换的序列密码。它以一个足够大的数据表(S盒)为基础,对表进行非线性变换,产生非线性的密钥流序列。它是一个可变密钥长度、面向字节操作的序列密码,该算法以随机置换作为基础。

RC4的S盒大小根据参数的值而变化。种子密钥长度小于等于S盒的长度大小,用来初始化S盒。RC4有两种主要算法,密钥调度算法和伪随机数生成算法。其中密钥调度算法用于对S盒的分线性排列,伪随机数生成算法用于生成密钥流。

其中的步骤主要为:初始化数据表S,初始置换数据表S,密钥流的生成。

一.初始化S表

  • 对S表进行线性填充,一般为256个字节;

    在这里插入图片描述

  • 用种子密钥填充另一个256字节的K表;
    在这里插入图片描述

  • 用K表对S表进行初始置换;
    在这里插入图片描述

二.初始置换S表

置换代码如下:

 j = 0;

  for (i = 0 ; i < 256 ; i++){(当参数n为8时,S盒大小为256)

    j = (j + S[i] + K[i]) mod 256;

    swap(S[i] , S[j]);

  }

三.密钥流的生成

为每个待加密的字节生成一个伪随机数,用来异或

代码如下:

i,j = 0;

  for r = 0 to len do //r为明文长度
      
      i = (i + 1) mod 256;

    j = (j + S[i]) mod 256;

    swap(S[i] , S[j]);

       t = (s[i] + s[j]) mod 256;

       k[r] = s[t];

举例:

在这里插入图片描述

因为这个表只有7个数,则:

i = (i + 1) mod 7 = 0 + 1 = 1;

j = (j + s[i]) mod 7 = 0 + s[i] = 0 + 0 = 0;

swap(s[0],s[1]);

t = s[0] + s[1] mod 7 = 3;

s[3] = 4;

k[0] = s[3] = 4;

反复进行该过程,直到生成的二进制的数量等于明文位的数量。加密时将k与明文中的一个字节异或,解密时将k与密文中的一个字节异或

以下为Python实现RC4的整体流程:

def swap(a,b):
    temp=a
    a=b
    b=temp

code_="gjw1115"
key_="123456"

code=[]
key=[]
for i in range(len(code_)):
    code.append(ord(code_[i]))
for i in range(len(key_)):
    key.append(ord(key_[i]))


s=[]
k=[]

for i in range(256):
    s.append(i)
    k.append(key[i%6])


j=0

for i in range(256):
    j=(j+s[i]+k[i])%256
    temp = s [i]
    s [i] = s [j]
    s [j] = temp


j=0
i=0
xor_code=[0]*len(code)
for r in range(len(code)):
    i=(i+1)%256
    j=(j+s[i])%256
    swap(s[i],s[j])
    t=(s[i]+s[j])%256
    xor_code[r]=s[t]

for i in range(len(code)):
    code[i]=code[i]^xor_code[i]
    print(hex(code[i]),end=' ')

接下来做一道有关RC4的CTF题型

听说是RC4?

题目:

key welcometoicqedu

密文UUyFTj8PCzF6geFn6xgBOYSvVTrbpNU4OF9db9wMcPD1yDbaJw==

直接看题目可以得知这道题为RC4加密,由于key和code全部已知了,所以直接使用脚本就可以解决了

注:这里使用了salt,观察可以发现plain使用了base64编码,需要先提取salt然后计算realkey,然后解密

参考blog:加密中的“Salt”_加salt-CSDN博客

plain = b'UUyFTj8PCzF6geFn6xgBOYSvVTrbpNU4OF9db9wMcPD1yDbaJw=='
key = b'welcometoicqedu'

#这些为正常的RC4解密
def rc4(plain, key):
    x = 0
    l = []
    #定义盒
    Sbox = [s for s in range(256)]
    Tbox = [key[i % len(key)] for i in range(256)]

    # swap box
    for i in range(256):
        x = (x + Sbox[i] + Tbox[i]) % 256
        Sbox[i], Sbox[x] = Sbox[x], Sbox[i]

    x = y = 0
    out = []
    
    for char in plain:
        x = (x + 1) % 256  
        y = (y + Sbox[x]) % 256  
        Sbox[y], Sbox[x] = Sbox[x], Sbox[y]
        cipher_byte = Sbox[(Sbox[x] + Sbox[y]) % 256]
        # xor
        out.append(chr(char ^ cipher_byte))
    cipher_stream = ''.join(out)
    print(cipher_stream.encode())
    return cipher_stream

#这些为获取salt操作
import base64
import hashlib

# encode=rc4(base64.b64decode(plain).decode()[len(key):],key)
salt, crypt = base64.b64decode(plain)[:16], base64.b64decode(plain)[16:]
print(salt)
realkey = hashlib.sha1(key + salt).digest()
rc4(crypt, realkey)
  • 9
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值