复现比赛系列;希望对大家学习密码学有所帮助
crypto1_中秋月
题目描述:
fsskryenvkm~jl{ejs}jwflzsnpgmifq{{j{|suhzrjppnx|qvixt~whu
hint:
经此古典密码加密后,密文还是大写
该古典密码的密钥形式:
keyword+plaintext (+plaintext…+plaintext)自动钥匙⊕
显然是自动密钥加密没错了
但是需要注意到这里给出的密文并不是这种加密得到的密文(应该是大写的)
可能经过了某种变换;
题目中还有⊕;可能是异或
使用cyberchief试一试异或(cyberchief的异或选项有爆破功能)
得到一种情况恰好全部为大写字母:
YLLTMFZQITRAUSDZULBUHYSELQOXRVYNDDUDCLJWEMUOOQGCNIVGKAHWJ5
github上搜到自动密钥解密的脚本break_autokeyGitHub - hitcxy/break_autokey
修改一下脚本(因为我是python3的)运行得到flag
flag:
flag{do_you_like_classical_cipher}
crypto2_月自圆
题目:
# -*- coding:utf-8 -*-
#Author: Lazzaro
from itertools import *
from random import *
from string import *
def encrypt(m, a, si):
c=""
for i in range(len(m)):
c+=hex(((ord(m[i])) * a + ord(next(si))) % 128)[2:].zfill(2)
return c
if __name__ == "__main__":
m = '****************************************************flag{*************}'
assert(len(m)==71)
a = randint(50,100)
salt = ''.join(sample(ascii_uppercase, 4))
si = cycle(salt.lower())
c=encrypt(m, a, si)
print(c)
#3472184e657e50561c481f5c1c4e1938163e154431015e13062c1b073d4e3a444f4a5c5c7a071919167b034e1c29566647600c4e1c2956661b6c1f50622f0016317e563546202a
程序逻辑:
随机生成盐值和一个整数用于加密;
salt生成迭代对象,可以无限循环salt本身的字符;
cycle()函数的作用
用**cycle()**循环迭代,**cycle()**函数重复循环一组值,可用它循环数据集标识符对数据集进行分组
sample(序列a,n):
在从序列a中随机抽取n个元素,并将n个元素生以list形式返回。
所以实际上每次进行encrypto()函数加密盐值的只有一个字符
而a的值很小,可以一起爆破
明文中给出了部分“flag”;在密文中可以对照的找到“flag”对应的密文是1c295666”
可以对照这段字符进行爆破:看加密之后是否于密文相同;注意是需要单个字符分别爆破;
因为每次加密取得是单个字符而且si在每几次加密中可能是不同字符的(假设salt = “aes”,那么第一次加密就是si=“a”,第二次加密si = “e”,以此类推)
爆破出各个字符满足的a,进行对比可以找到唯一满足情况的a
然后爆破salt,还是代入encrypto()函数进行把爆破,看密文是否对应,需要爆破"flag{"
因为不确定salt的大小;结果爆破出来:“JESQJ”
猜测应该是salt = “JESQ”
这样就可以求解flag了,还是运用爆破明文字符(可打印字符范围);需要注意每次爆破出一个明文字符,si的值需要换到下一个,而next()函数的传参不能是非对象的,所以这里另外创建一个中间量sii,而在encrpto()函数中把next()函数去掉
代码实现:
from string import *
from random import *
from itertools import *
c = "3472184e657e50561c481f5c1c4e1938163e154431015e13062c1b073d4e3a444f4a5c5c7a071919167b034e1c29566647600c4e1c2956661b6c1f50622f0016317e563546202a"
def encrypt(m, a, si):
c=""
for i in range(len(m)):
c+=hex(((ord(m[i])) * a + ord(next(si))) % 128)[2:].zfill(2)
return c
def encrypt2(m, a, si):
c=""
for i in range(len(m)):
c+=hex(((ord(m[i])) * a + ord(si)) % 128)[2:].zfill(2)
return c
#for语句中的if语句需要分别使用,同时运行的话因为si的值固定所以无法正确爆破
# for a in range(50,100):
# for j in ascii_uppercase:
# si = cycle(j.lower())
# if encrypt("f",a,si) == "1c":
# print("f:",end="")
# print(a,j)
# if encrypt("l",a,si) == "29":
# print("l:",end="")
# print(a,j)
# if encrypt("a",a,si) == "56":
# print("a:",end="")
# print(a,j)
#"fla"爆破对比a = 67
# for j in ascii_uppercase:
# si = cycle(j.lower())
# if encrypt("f",67,si) == "1c":
# print(j)
# if encrypt("l",67,si) == "29":
# print(j)
# if encrypt("a",67,si) == "56":
# print(j)
# if encrypt("g",67,si) == "66":
# print(j)
#"flag"爆破salt得到JESQ
salt = "JESQ"
a = 67
si = cycle(salt.lower())
for i in range(0,len(c),2):
temp = c[i:i+2]
sii = next(si)
for j in range(32,127):
temp2 = encrypt2(chr(j),a,sii)
if temp == temp2:
print(chr(j),end="")
# now_is_7fad9fcb-d361-4964-821c-177c906b8d20_flag_is_flag{md5(now-salt)}
import hashlib
flag = "7fad9fcb-d361-4964-821c-177c906b8d20-JESQ" #这里太🐕了,后面加上"-JESQ"是真的有点考理解
print("")
print(hashlib.md5(flag.encode("utf8")).hexdigest())
crypto3_多少离怀
题目:
# -*- coding:utf-8 -*-
#Author: Lazzaro
from Crypto.Util.number import getPrime,isPrime
from math import gamma
import random
def nextPrime(n):
n += 2 if n & 1 else 1
while not isPrime(n):
n += 2
return n
def getNewPrime():
A = getPrime(512)
B = nextPrime(A - random.randint(1e4,1e5))
return nextPrime(gamma(B+2)%A)
p = getNewPrime()
q = getNewPrime()
r = getNewPrime()
n = p * q ** 2 * r ** 3
e = 0x10001
c = pow(flag,e,n)
#pA=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723982789
#pB=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723922147
#qA=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477881291
#qB=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477807457
#n=4451906216583258787166698210560165433649728830889954633721198623488802305844782492171757604711145165920462286487680020347239300947225371917344589502941576734875830871998499135120227347066586066943289430156378296665669974728569678779668142712266780949126509440672273927433367293606776081254094682033167575930701870261219046464773708974194213798032346187463443317770758989273370488582862531630356263732232300508706676725203199729764016766683870925164232508407363688370458877688991733322055785233669885166225464068579486683574954699370175267031949720967812902215635630884502987094547523361027411501285252862476410213277925430392164226297316310465146003494714018456407793759170649913180823814850170639706664167149612984905056804131124522209409607977589884632999710708045656852149371030046919242039957767777840304466948549383597755811307383659188216421501912831203089570725388153416013596114462069777713822433178099904907224119
#c=1996198968748552041728429851810599627895157160099076033250854211280074825148767841655949210593646824507865483166496070951130337321360509148527292165245205219296211294789087358959553387392928560150390604911087085313000622842025416521494799132969818997182731021267942464323979261593380113740152841984062184326431879167516288834455296913822921806893572566867611541664848820247889274979245086440402996661226884320574824077910315143756471444347386795428338020162169391827182914043434253974549636668126789355991920452920806351939782281969098470635517019120996509180703896707990501216102290302162705699788457579330150149320348175742131887213742989509004374645723471497302400169849858253644606818874098604333865973357374444445825761600866472906771935670261641342221394488068630591190697667016958881530367047928341661857241378511420562236766886349565409774340321441504290366223243635878057759623855735794209219474650425139791831374
hint:
注意伽马函数Γ(x)和阶乘x!的关系式
威尔逊定理
逻辑很简单:
随机生成素数pA,将pA减去一个随机在1e4到1e5之间的整数的下一个素数得到pB
素因子p = gamma(pB+2)%pA;同理q
而题目已给出pA,pB,qA,qB
错误示范:
原始想法:按着加密的算法再算一遍就好了啊,直接可以求得p和q
但是运行过程得到报错:math range error
搜一搜gamma函数;再结合hint和大佬wp;
g a m m a ( n ) = ( n − 1 ) ! gamma(n) = (n-1)! gamma(n)=(n−1)!
威尔逊定理:
( p − 1 ) ! = − 1 ( m o d p ) (p-1)!=-1~(mod~p) (p−1)!=−1 (mod p)
( p − 2 ) ! = 1 ( m o d p ) (p-2)!=1~(mod~p) (p−2)!=1 (mod p)
而题目中最后pq是等于 g a m m a ( p B + 2 ) % p A gamma(pB+2)~\%~pA gamma(pB+2) % pA
也就相当于 ( p B + 1 ) ! % p A (pB+1)!~\%~pA (pB+1)! % pA
既然有求余符号就尽量往同余1的方向带
构造这样的同余式:
( p A − 2 ) ! / ( p B + 2 ) ! ∗ ( p B + 2 ) ! ≡ 1 ( m o d p A ) (pA-2)!/(pB+2)!*(pB+2)!\equiv1~(mod~pA) (pA−2)!/(pB+2)!∗(pB+2)!≡1 (mod pA)
设 x = ( p A − 2 ) ! / ( p B + 2 ) ! x = (pA-2)!/(pB+2)! x=(pA−2)!/(pB+2)!; y = ( p B + 2 ) ! y = (pB+2)! y=(pB+2)!
要求的y的大小;也就是求x与模数pA的逆元
而 p A − 2 pA-2 pA−2与 p B + 2 pB+2 pB+2相差 1 e 4 1e4 1e4到 1 e 5 1e5 1e5之间
他们两者相除得到:
p B ∗ ( p A − 2 − p B ) ∗ . . . ∗ ( p A − 2 ) pB*(pA-2-pB)*...*(pA-2) pB∗(pA−2−pB)∗...∗(pA−2)
使用封装函数gmpy2.invert()即可求得逆元
注意这里遍历的时候需要每一个遍历量先进行求逆元;因为这样的阶乘还是太大了,中间如果有求余过程的话会简化很多计算过程
得到逆元也就是得到p和q;之后算r;使用 n / / p / / q 2 n//p//q^2 n//p//q2
算fai_n的时候需要注意素因子的次方情况下,欧拉函数等于 ( p n − p n − 1 ) (p^n-p^{n-1}) (pn−pn−1)
代码实现:
import gmpy2
from Crypto.Util.number import *
from sympy.ntheory.generate import nextprime
pA = 6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723982789
pB = 6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723922147
qA = 7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477881291
qB = 7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477807457
n = 4451906216583258787166698210560165433649728830889954633721198623488802305844782492171757604711145165920462286487680020347239300947225371917344589502941576734875830871998499135120227347066586066943289430156378296665669974728569678779668142712266780949126509440672273927433367293606776081254094682033167575930701870261219046464773708974194213798032346187463443317770758989273370488582862531630356263732232300508706676725203199729764016766683870925164232508407363688370458877688991733322055785233669885166225464068579486683574954699370175267031949720967812902215635630884502987094547523361027411501285252862476410213277925430392164226297316310465146003494714018456407793759170649913180823814850170639706664167149612984905056804131124522209409607977589884632999710708045656852149371030046919242039957767777840304466948549383597755811307383659188216421501912831203089570725388153416013596114462069777713822433178099904907224119
c = 1996198968748552041728429851810599627895157160099076033250854211280074825148767841655949210593646824507865483166496070951130337321360509148527292165245205219296211294789087358959553387392928560150390604911087085313000622842025416521494799132969818997182731021267942464323979261593380113740152841984062184326431879167516288834455296913822921806893572566867611541664848820247889274979245086440402996661226884320574824077910315143756471444347386795428338020162169391827182914043434253974549636668126789355991920452920806351939782281969098470635517019120996509180703896707990501216102290302162705699788457579330150149320348175742131887213742989509004374645723471497302400169849858253644606818874098604333865973357374444445825761600866472906771935670261641342221394488068630591190697667016958881530367047928341661857241378511420562236766886349565409774340321441504290366223243635878057759623855735794209219474650425139791831374
e = 65537
#注释部分是错误示范
#由于math range error;得到的数字超过了数学范围,不能这样直接求解
# p = sympy.nextprime(gamma(pB+2)%pA)
# print(p)
#由于pA,pB太大了,无法求阶乘
# jiec1 = 1
# jiec2 = 1
# for i in range(1,pA - 2):
# jiec1 *= i
# for i in range(1,pB + 1):
# jiec2 *= i
# x = jiec1 // jiec2
# y = gmpy2.invert(x,pA)
def getrealprime(a,b):
difference = a - 2 - (b + 1)
temp = 1
for i in range(0,difference):
temp = temp * gmpy2.invert(a-2-i,a) % a
return nextprime(temp)
p = getrealprime(pA,pB)
print(p)
q = getrealprime(qA,qB)
print(q)
r = gmpy2.iroot(n // p // q**2,3)[0]
fai_n = (p-1)*(q-1)*q*(r-1)*r**2
d = gmpy2.invert(e,fai_n)
m = pow(c,d,n)
print(long_to_bytes(m))
这是解题过程中借鉴的大佬wp:https://blog.csdn.net/hiahiachang/article/details/108800210
https://blog.csdn.net/Kr0ne/article/details/108833373?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163503761916780366522347%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163503761916780366522347&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-3-108833373.first_rank_v2_pc_rank_v29&utm_term=ctfshow+%E6%9C%88%E9%A5%BC%E6%9D%AF2020&spm=1018.2226.3001.4187