吃瓜杯&吃鸡杯
crypto
这两次的古典密码一个都不会,有两个交互的发送方式把我整晕了😢,以后再补充
闪电五连鞭·一鞭
from Crypto.Util.number import *
n = 8870619487339789349033932217513908953609539651949986489986889710933094577873155191810742828503059670650154455297603719
e = 3
with open('flag.txt', 'rb') as f:
m = bytes_to_long(f.read())
assert n > m
Zn = Zmod(n)
P = PermutationGroupElement('(1,6)(2,3,5)(4,7)')
P = Matrix(Zn, P.matrix())
def encrypt(m):
C = (m * P) ^ e
return C.list()
由于矩阵是初等矩阵,其幂次也为初等矩阵,所以最后矩阵上不为1的数字即是m^3mod(n)的结果,而n是能够分解的,正常RSA解密即可
代码如下:
import gmpy2
n = 8870619487339789349033932217513908953609539651949986489986889710933094577873155191810742828503059670650154455297603719
e = 3
P1 = 50240938337
P2 = 35200554341
P3 = 66104249843
P4 = 62183036099
P5 = 63345654131
P6 = 67704082961
P7 = 48479007809
P8 = 48105446183
P9 = 50769514811
P10 = 67515121673
P11 = 35592761021
c=6940158573485767169443582872275118843545217792197971962103010557916847970940437712181778807436191892307187137338300231
phi=(P1-1)*(P2-1)*(P3-1)*(P4-1)*(P5-1)*(P6-1)*(P7-1)*(P8-1)*(P9-1)*(P10-1)*(P11-1)
d=gmpy2.invert(e,phi)
print(pow(c,d,n))
闪电五连鞭·二鞭
from Crypto.Util.number import *
import random
random.seed(0x36D)
n = 3950848271664122675439855009329233027357977239695163232943132810210035583520735079984423511153607529820284200137188647
e = 3
with open('flag.txt', 'rb') as f:
m = bytes_to_long(f.read())
assert n > m
Zn = Zmod(n)
P = PermutationGroupElement('(1,14,25,8,23,15)(2,22,17)(3,18,13,33,11,30,26,27,10,6,16,31,28,21,29,36,7,9)(4,35,12,32,20,5,24)(19,34)')
P = Matrix(Zn, P.matrix())
A = Matrix(Zn, 36, 36, lambda x, y: random.randint(0, 0x36D))
B = A * P * A^-1
def encrypt(m):
C = (m * B) ^ e
return C.list()
矩阵细节告诉你了,和第一题没区别
代码如下:
import random
random.seed(0x36D)
n = 3950848271664122675439855009329233027357977239695163232943132810210035583520735079984423511153607529820284200137188647
Zn = Zmod(n)
P = PermutationGroupElement('(1,14,25,8,23,15)(2,22,17)(3,18,13,33,11,30,26,27,10,6,16,31,28,21,29,36,7,9)(4,35,12,32,20,5,24)(19,34)')
P = Matrix(Zn, P.matrix())
A = Matrix(Zn, 36, 36, lambda x, y: random.randint(0, 0x36D))
B = A * P * A^-1
print(B^3)
import gmpy2
n = 3950848271664122675439855009329233027357977239695163232943132810210035583520735079984423511153607529820284200137188647
e = 3
P1 = 34929570281
P2 = 45257138441
P3 = 37075595933
P4 = 52247556719
P5 = 51535960127
P6 = 52587303023
P7 = 50078700401
P8 = 65879634563
P9 = 39080096201
P10 = 56431742447
P11 = 65430660761
k=3631726152245557951349544604305122093557137441233475943486700146282835574044414322766971425339642907262597894115705095
c=266139750184072256867523233914663711299040516073239592856002179890534272023823522825949062175260062964182042569893693
phi=(P1-1)*(P2-1)*(P3-1)*(P4-1)*(P5-1)*(P6-1)*(P7-1)*(P8-1)*(P9-1)*(P10-1)*(P11-1)
c=c*gmpy2.invert(k,n)%n
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(m)
闪电五连鞭·三鞭
from Crypto.Util.number import *
import random
random.seed(0x36D)
n = 25126409997644048715497037905442671105116158875704245711785280791201683049008805107543997350200944348915833337286069203
e = 3
with open('flag.txt', 'rb') as f:
m = bytes_to_long(f.read())
assert n > m
Zn = Zmod(n)
P = PermutationGroupElement('(1,3,6,29,25,34,22,33,10,16,7)(2,21,19,17,31,9,5,30,27,35,32,11)(4,20,28,23,18,15)(8,26,14,12)(36,24,13)')
P = Matrix(Zn, P.matrix())
A = Matrix(Zn, 36, 36, lambda x, y: random.randint(0, 0x36D))
B = A * P * A^-1
def encrypt(m):
C = (m * B) ^ e
return C
matrix_map = {"I": Matrix(Zn, matrix.identity(36)), "B": B, "C": encrypt(m)}
def server_add(matrix_map):
print("第一个矩阵:")
A = input("> ").strip()
print("第二个矩阵:")
B = input("> ").strip()
C = matrix_map[A]+matrix_map[B]
print(f"这两个矩阵之和的迹是:{C.trace()},迹你实在是太美~")
return C
def server_product(matrix_map):
print("第一个矩阵:")
A = input("> ").strip()
print("第二个矩阵:")
B = input("> ").strip()
C = matrix_map[A]*matrix_map[B]
print(f"这两个矩阵之积的迹是:{C.trace()},迹你实在是太美~")
return C
def server_kproduct(matrix_map):
print("矩阵:")
A = input("> ").strip()
print("乘数:")
k = input("> ").strip()
k = int(k)
B = k * matrix_map[A]
print(f"数乘结果的迹是:{B.trace()},迹你实在是太美~")
return B
def server_power(matrix_map):
print("矩阵:")
A = input("> ").strip()
print("幂次:")
k = input("> ").strip()
k = int(k)
B = matrix_map[A] ^ k
print(f"求幂结果的迹是:{B.trace()},迹你实在是太美~")
return B
def server_save(A, matrix_map):
print("存个小档? (Y/N)")
s = input("> ").strip().upper()
if s == "Y":
print("运算结果叫啥名呢?")
S = input("> ").strip()
matrix_map[S] = A
print("存上档咯!")
WELCOME = """
欢迎来打第三鞭!
在这一鞭中,你可以尝试打出两个矩阵的和,积。
或者一个矩阵的数乘,幂次。
但是由于av50183113,所以我只会告诉你运算结果的迹,因为迹你太美。
"""
MENU = """
请开始你的表演:
[S] 打印矩阵
[+] 两矩阵相加
[*] 两矩阵相乘
[K] 一矩阵数乘
[^] 一矩阵求幂
[Q] 886
"""
print(WELCOME)
while True:
print(MENU)
try:
opt = input("> ").strip().upper()
if (opt == "S"):
print("迹你太美……baby……迹你实在是太美……")
for k, v in matrix_map.items():
print(f"{k}: {v.trace()}")
elif (opt == "+"):
M = server_add(matrix_map)
server_save(M, matrix_map)
elif (opt == "*"):
M = server_product(matrix_map)
server_save(M, matrix_map)
elif (opt == "K"):
M = server_kproduct(matrix_map)
server_save(M, matrix_map)
elif (opt == "^"):
M = server_power(matrix_map)
server_save(M, matrix_map)
elif (opt == "Q"):
print("再见!")
break
else:
print("李在……赣神魔?")
except:
print("这波和闪电鞭配合得不是很好……")
由于交互的过程只会告诉你任意矩阵的迹,但是我们会发现同余式
C≡M3B3 => tr(C)≡M3 tr(B3) 接下来就按前面那样做就行
代码如下:
import gmpy2
c=32107799284008725734877436482088603401342362148460412344579311496585237117660598070527766747517839372142582958727343
n = 25126409997644048715497037905442671105116158875704245711785280791201683049008805107543997350200944348915833337286069203
e = 3
P1 = 60561137381
P2 = 62259609689
P3 = 59742623363
P4 = 62787656051
P5 = 59072838359
P6 = 62725971677
P7 = 64819665749
P8 = 40813118459
P9 = 58190950619
P10 = 49550187209
P11 = 62853419633
phi=(P1-1)*(P2-1)*(P3-1)*(P4-1)*(P5-1)*(P6-1)*(P7-1)*(P8-1)*(P9-1)*(P10-1)*(P11-1)
c=gmpy2.invert(3,n)*c%n
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(m)
闪电五连鞭·四鞭
from Crypto.Util.number import *
import random
# 你看这个n它又长又宽
n = ???
e = 17
with open('flag.txt', 'rb') as f:
m = bytes_to_long(f.read())
assert n > m
Zn = Zmod(n)
# 就像这个B它又大又圆
B = ???
def encrypt(m):
C = (m * B) ^ e
return C
matrix_map = {"I": Matrix(Zn, matrix.identity(??)), "B": B, "C": encrypt(m)}
def server_add(matrix_map):
print("第一个矩阵:")
A = input("> ").strip()
print("第二个矩阵:")
B = input("> ").strip()
C = matrix_map[A]+matrix_map[B]
print(f"这两个矩阵之和的迹是:{C.trace()},迹你实在是太美~")
return C
def server_product(matrix_map):
print("第一个矩阵:")
A = input("> ").strip()
print("第二个矩阵:")
B = input("> ").strip()
C = matrix_map[A]*matrix_map[B]
print(f"这两个矩阵之积的迹是:{C.trace()},迹你实在是太美~")
return C
def server_kproduct(matrix_map):
print("矩阵:")
A = input("> ").strip()
print("乘数:")
k = input("> ").strip()
k = int(k)
B = k * matrix_map[A]
print(f"数乘结果的迹是:{B.trace()},迹你实在是太美~")
return B
def server_power(matrix_map):
print("矩阵:")
A = input("> ").strip()
print("幂次:")
k = input("> ").strip()
k = int(k)
B = matrix_map[A] ^ k
print(f"求幂结果的迹是:{B.trace()},迹你实在是太美~")
return B
def server_save(A, matrix_map):
print("存个小档? (Y/N)")
s = input("> ").strip().upper()
if s == "Y":
print("运算结果叫啥名呢?")
S = input("> ").strip()
matrix_map[S] = A
print("存上档咯!")
WELCOME = """
欢迎来打第四鞭!
在这一鞭中,你仍然可以尝试打出两个矩阵的和,积。
或者一个矩阵的数乘,幂次。
但是由于av50183113,所以我只会告诉你运算结果的迹,因为迹你太美。
我的n和B很大,你要忍一下……
"""
MENU = """
请开始你的表演:
[S] 打印矩阵
[+] 两矩阵相加
[*] 两矩阵相乘
[K] 一矩阵数乘
[^] 一矩阵求幂
[Q] 886
"""
print(WELCOME)
print(f'n = {n}')
while True:
print(MENU)
try:
opt = input("> ").strip().upper()
if (opt == "S"):
print("迹你太美……baby……迹你实在是太美……")
for k, v in matrix_map.items():
print(f"{k}: {v.trace()}")
elif (opt == "+"):
M = server_add(matrix_map)
server_save(M, matrix_map)
elif (opt == "*"):
M = server_product(matrix_map)
server_save(M, matrix_map)
elif (opt == "K"):
M = server_kproduct(matrix_map)
server_save(M, matrix_map)
elif (opt == "^"):
M = server_power(matrix_map)
server_save(M, matrix_map)
elif (opt == "Q"):
print("再见!")
break
else:
print("李在……赣神魔?")
except:
print("这波和闪电鞭配合得不是很好……")
这个应该是这个系列最难的一道了,由于tr(B17)=0 故条件给出的tr(c)=0 在这种情况下我们是没办法获得信息的
所以我们需要对矩阵进行一些运算是我们能获得其一些信息
运用所给选项计算(B+I)^17发现不等于0 这说明存在i∈[1,17]使Bi≠0
随便枚举一下即可接下来就使仿照3来解密,
我们有 Ci≡meiBei mod(n)
但是会发现ei在mod(phi(n))下不存在逆,我就先把e的逆算出来得到一个mi mod(n)
我看i还挺小,就直接有限域开方了,但是这方法不太好写的代码也好丑
代码如下:
import gmpy2
c=2110149061436063240946379890614449571205510110280060937710940187010356170283722801180744692753366180282882635403809344
e=17
b=11
n=9136363927463211274720971804015734445858321050728635981823337747511804888258406056847440698866771826986117867302110317
P1 = 63382647407
P2 = 56935996609
P3 = 49592197427
P4 = 49353296609
P5 = 42792011597
P6 = 54243266333
P7 = 47737805249
P8 = 54589476787
P9 = 67220211181
P10 = 63941086333
P11 = 39785678587
phi=(P1-1)*(P2-1)*(P3-1)*(P4-1)*(P5-1)*(P6-1)*(P7-1)*(P8-1)*(P9-1)*(P10-1)*(P11-1)
d=gmpy2.invert(e,phi)
c=c*gmpy2.invert(b,n)
m=pow(c,d,n)
print(m)
p=[63382647407,
56935996609,
49592197427,
49353296609,
42792011597,
54243266333,
47737805249,
54589476787,
67220211181,
63941086333,
39785678587]
c=3250313765621013956063129443635044646038173356585715703694053922423559755512305740760960461108129040879330681336825681
PR.<x>=PolynomialRing(Zmod(p[0]))
f=x^11-c
a1=f.roots()
PR.<x>=PolynomialRing(Zmod(p[1]))
f=x^11-c
a2=f.roots()
PR.<x>=PolynomialRing(Zmod(p[2]))
f=x^11-c
a3=f.roots()
PR.<x>=PolynomialRing(Zmod(p[3]))
f=x^11-c
a4=f.roots()
PR.<x>=PolynomialRing(Zmod(p[4]))
f=x^11-c
a5=f.roots()
PR.<x>=PolynomialRing(Zmod(p[5]))
f=x^11-c
a6=f.roots()
PR.<x>=PolynomialRing(Zmod(p[6]))
f=x^11-c
a7=f.roots()
PR.<x>=PolynomialRing(Zmod(p[7]))
f=x^11-c
a8=f.roots()
PR.<x>=PolynomialRing(Zmod(p[8]))
f=x^11-c
a9=f.roots()
PR.<x>=PolynomialRing(Zmod(p[9]))
f=x^11-c
a10=f.roots()
PR.<x>=PolynomialRing(Zmod(p[10]))
f=x^11-c
a11=f.roots()
for i1 in a1:
for i2 in a2:
for i3 in a3:
for i4 in a4:
for i5 in a5:
for i6 in a6:
for i7 in a7:
for i8 in a8:
for i9 in a9:
for i10 in a10:
for i11 in a11:
print(crt([int(i1[0]),int(i2[0]),int(i3[0]),int(i4[0]),int(i5[0]),int(i6[0]),int(i7[0]),int(i8[0]),int(i9[0]),int(i10[0]),int(i11[0])],[p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9],p[10]]))
分享一下wp的做法很巧妙,确实没想到(没能把所学的东西运用起来)

闪电五连鞭·五鞭
from Crypto.Util.number import *
import random
# 你们,来这里,练鞭,我看行
n = ???
e = 0x1337
with open('flag.txt', 'rb') as f:
m = bytes_to_long(f.read())
assert n > m
Zn = Zmod(n)
# 你们,来这里,练鞭,就像我给你们出题一样很开心,诶!
B = ???
def encrypt(m):
C = (m * B) ^ e
return C
matrix_map = {"B": B, "C": encrypt(m)}
available_set = set('S+*^QY')
def server_add(matrix_map):
print("第一个矩阵:")
A = input("> ").strip()
print("第二个矩阵:")
B = input("> ").strip()
C = matrix_map[A]+matrix_map[B]
print(f"这两个矩阵之和的迹是:{C.trace()},迹你实在是太美~")
return C
def server_product(matrix_map):
print("第一个矩阵:")
A = input("> ").strip()
print("第二个矩阵:")
B = input("> ").strip()
C = matrix_map[A]*matrix_map[B]
print(f"这两个矩阵之积的迹是:{C.trace()},迹你实在是太美~")
return C
def server_kproduct(matrix_map):
print("矩阵:")
A = input("> ").strip()
print("乘数:")
k = input("> ").strip()
k = int(k)
B = k * matrix_map[A]
print(f"数乘结果的迹是:{B.trace()},迹你实在是太美~")
return B
def server_power(matrix_map):
print("矩阵:")
A = input("> ").strip()
print("幂次:")
k = input("> ").strip()
k = int(k)
B = matrix_map[A] ^ k
print(f"求幂结果的迹是:{B.trace()},迹你实在是太美~")
return B
def server_save(A, matrix_map):
print("存个小档? (Y/N)")
s = input("> ").strip().upper()
if s == "Y" and s in available_set:
available_set.remove(s)
print("运算结果叫啥名呢?")
S = input("> ").strip()
matrix_map[S] = A
print("存上档咯!")
WELCOME = """
欢迎来打第五鞭!
在这一鞭中,你仍然可以尝试打出两个矩阵的和,积。
或者一个矩阵的幂次。
但是由于av50183113,所以我只会告诉你运算结果的迹,因为迹你太美。
而且,RSA置换闪电鞭讲究化劲儿,讲究四两拨千斤。
所以你的每一种操作都最多只能用一次。
年轻人要讲武德,要以和为贵。
我的n和B很大,你要忍一下……
"""
MENU = """
请开始你的表演:
[S] 打印矩阵
[+] 两矩阵相加
[*] 两矩阵相乘
[^] 一矩阵求幂
[Q] 886
"""
print(WELCOME)
print(f'n = {n}')
while True:
print(MENU)
try:
opt = input("> ").strip().upper()
if (opt == "S"):
available_set.remove(opt)
print("迹你太美……baby……迹你实在是太美……")
for k, v in matrix_map.items():
print(f"{k}: {v.trace()}")
elif (opt == "+"):
available_set.remove(opt)
M = server_add(matrix_map)
server_save(M, matrix_map)
elif (opt == "*"):
available_set.remove(opt)
M = server_product(matrix_map)
server_save(M, matrix_map)
elif (opt == "^"):
available_set.remove(opt)
M = server_power(matrix_map)
server_save(M, matrix_map)
elif (opt == "Q"):
available_set.remove(opt)
print("再见!")
break
else:
print("李在……赣神魔?")
except:
print("这波和闪电鞭配合得不是很好……")
虽然都只能用一次,但是给出的C和B大部分情况下trace都不为0
我当时开的环境刚好两个都等于0了,但是发现CB的trace不为0,于是就在加密的表达式上修改了一下正常解密就行
代码如下:
import gmpy2
c=955103709439248894586213837770898423246597271211028290529952156047094494876964974922629629185673910258820617160908894
b=69
n=7510992473064673920395921351705350262129488066167259728057599846106242381615171362065128831335267786773227316823019081
e=4919
P1 = 63895634981
P2 = 68145079363
P3 = 62513513863
P4 = 34537612589
P5 = 42312028009
P6 = 47062927963
P7 = 55471687129
P8 = 46456587337
P9 = 44997102611
P10 = 68562057983
P11 = 50465612867
phi=(P1-1)*(P2-1)*(P3-1)*(P4-1)*(P5-1)*(P6-1)*(P7-1)*(P8-1)*(P9-1)*(P10-1)*(P11-1)
c=c*gmpy2.invert(b,n)
d=gmpy2.invert(e,phi)
print(pow(c,d,n))
但是题目还含有部分置换的内容用于构造B矩阵,可以学习一下
Cop! Run!!
from Crypto.Util.number import *
from flag import flag
n = 1 << 8
p = getPrime(n)
print(p)
P.<t> = PolynomialRing(Zmod(p))
f = t * t + randrange(p)
print(f)
x = [randrange(p)]
x += [f(x[0])]
print([x_ >> (n - ceil(5 * n / 7)) for x_ in x])
flag = bytes_to_long(flag)
y = f(x[-1])
for i in range(7):
y = f(y)
flag ^^= int(y)
print(flag)
'''
92946459607669937513774102250057295249718593723232674702212854287358873135783
t^2 + 43844336985235863734419631630425915388298791521868754583032904718644333115590
[3248642833056635029095920782095626337949113592116495266, 4883935221919623989344404485025479346028101682781790392]
193207529097125793778662519051231322609402866155819915933598367395102313904490702547833
'''
多元copper,可以通过自己调个格子解

由于格还没学太明白,就直接搬的多元copper的脚本了(以后补补)
代码如下:
import itertools
def small_roots(f, bounds, m=1, d=None):
if not d:
d = f.degree()
R = f.base_ring()
N = R.cardinality()
f /= f.coefficients().pop(0)
f = f.change_ring(ZZ)
G = Sequence([], f.parent())
for i in range(m + 1):
base = N ^ (m - i) * f ^ i
for shifts in itertools.product(range(d), repeat=f.nvariables()):
g = base * prod(map(power, f.variables(), shifts))
G.append(g)
B, monomials = G.coefficient_matrix()
monomials = vector(monomials)
factors = [monomial(*bounds) for monomial in monomials]
for i, factor in enumerate(factors):
B.rescale_col(i, factor)
B = B.dense_matrix().LLL()
B = B.change_ring(QQ)
for i, factor in enumerate(factors):
B.rescale_col(i, 1 / factor)
H = Sequence([], f.parent().change_ring(QQ))
for h in filter(None, B * monomials):
H.append(h)
I = H.ideal()
if I.dimension() == -1:
H.pop()
elif I.dimension() == 0:
roots = []
for root in I.variety(ring=ZZ):
root = tuple(R(root[var]) for var in f.variables())
roots.append(root)
return roots
return []
p=92946459607669937513774102250057295249718593723232674702212854287358873135783
a=3248642833056635029095920782095626337949113592116495266<<73
b=4883935221919623989344404485025479346028101682781790392<<73
r=43844336985235863734419631630425915388298791521868754583032904718644333115590
PR.<x,y>=PolynomialRing(Zmod(p))
f=(x+a)^2-y+(r-b)
bounds=(2^73,2^73)
root=small_roots(f,bounds,m=3)
print(root)
flag=193207529097125793778662519051231322609402866155819915933598367395102313904490702547833
solve=43878231839360886026
b=b+solve
PR.<t>=PolynomialRing(Zmod(p))
f1=t^2 + 43844336985235863734419631630425915388298791521868754583032904718644333115590
y=f1(b)
for i in range(7):
y = f1(y)
flag ^^= int(y)
print(flag)
群主说要出简单的题目大家把这题想简单一点
N = 24873777989291448485268365702265085243886872900039809831478881276969311714448924581398692832639705916538111455861057354225427758736198452679468399039512440497290615485190994957684665065261280544484301856860844163436499302230085760545686486398949018187416289923500558688885485672960734334858119391323987554701544773420070317895909846297195832399677291338220818181502181317849952785959097285626009703863257450199781708945715701136683994546852422993684382468187651935055302074609980311161155531603473091857526099148935429447319415714778860215376802270686310782735079899235228731429165106477537031235405221734008734614847
e = 12436888994645724242634182851132542621943436450019904915739440638484655857224462290699346416319852958269055727930528677112713879368099226339734199519756220248645307742595497478842332532630640272242150928430422081718249651115042880272843243199474509093708144961750279344442742836480367167429059695661993777350613653317802356713323129593521588320771616955563426747034967432053960828426250168954828986666929922730060781213890566121107119389060806644531516491192343284701151238691996162679338542186167193568672632227858449997036747029810933106336313085633759799229646747282205612102678724267585967720538082620536177904609
c = 7539424334663709603622451394173266049480031393220309445902319310504736287365860451132752036622339554159799611768328686792828750952551268647863160547774237934958072391797341405165512721597085695555356929495861914056799039140107261439671707574841789330531198534325422015873621769489969596614802282764401661006564546159674397356683650318142728009273827997179696988926599672213482848150751054351595386402597000601684644207559735499031666361222038615475154046453649719203304187309556004660926226182353445661702352380654352874617084419834338343925880593023307238768452509962
属实被坑到了,写了个wiener-attack的函数发现解不出😢 后面看这个密文好像和n的bits差的有点远就随手转了一下,直接就出了明文(原来这种情况下wiener不奏效,学到了)
WINNER WINNER CHICKEN DINNER! This is easy but quite troll man. One should NOT expect that the ciphertext is equal to plaintext in the real world. Flag is: ctfshow{xielunyan___KAI!}. By the way, what a stupid encryption exponent it is!

浙公网安备 33010602011771号