crypto1_中秋月
此夜中秋月,清光十万家*** 自动钥匙⊕ 明文全大写,得到后转小写,并以_连接单词。 格式:flag{xxx}。 @⎝Lazzaro⎠师傅供题
fsskryenvkm~jl{ejs}jwflzsnpgmifq{{j{|suhzrjppnx|qvixt~whu
看起来毫无头绪,观察提示,自动钥匙,也就是autokey密码。
网上有它的python2脚本,但是解密后发现不正确,自动钥匙后面有异或的操作,可能题目给出的密文是通过异或得出来的,我们需要再进行异或一下,于是有
message="fsskryenvkm~jl{ejs}jwflzsnpgmifq{{j{|suhzrjppnx|qvixt~whu"
for i in range(255):#ASCLL---```0-255
res=''
for j in range (0,len(message)):
temp =ord(message[j])^i#python中的^表示异或,在进行异或步骤时,需要把^前后两个数转换为二进制
if 65<=temp<=90 or 97<=temp<=122:#65-90表示A-Z,97-122表示a-z
res+=(chr(temp))
if len(res)==len(message):
print(res)
运行脚本后得到两组数字,再根据题目的提示发现有密文均为大写,即选择密文
YLLTMFZQITRAUSDZULBUHYSELQOXRVYNDDUDCLJWEMUOOQGCNIVGKAHWJ
再根据python脚本,即有
from ngram_score import ngram_score
from pycipher import Autokey
import re
from itertools import permutations
qgram = ngram_score('quadgrams.txt')
trigram = ngram_score('trigrams.txt')
ctext = 'YLLTMFZQITRAUSDZULBUHYSELQOXRVYNDDUDCLJWEMUOOQGCNIVGKAHWJ'
ctext = re.sub(r'[^A-Z]','',ctext.upper())
# keep a list of the N best things we have seen, discard anything else
class nbest(object):
def __init__(self,N=1000):
self.store = []
self.N = N
def add(self,item):
self.store.append(item)
self.store.sort(reverse=True)
self.store = self.store[:self.N]
def __getitem__(self,k):
return self.store[k]
def __len__(self):
return len(self.store)
#init
N=100
for KLEN in range(8,20):
rec = nbest(N)
for i in permutations('ABCDEFGHIJKLMNOPQRSTUVWXYZ',3):
key = ''.join(i) + 'A'*(KLEN-len(i))
pt = Autokey(key).decipher(ctext)
score = 0
for j in range(0,len(ctext),KLEN):
score += trigram.score(pt[j:j+3])
rec.add((score,''.join(i),pt[:30]))
next_rec = nbest(N)
for i in range(0,KLEN-3):
for k in range(N):
for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
key = rec[k][1] + c
fullkey = key + 'A'*(KLEN-len(key))
pt = Autokey(fullkey).decipher(ctext)
score = 0
for j in range(0,len(ctext),KLEN):
score += qgram.score(pt[j:j+len(key)])
next_rec.add((score,key,pt[:30]))
rec = next_rec
next_rec = nbest(N)
bestkey = rec[0][1]
pt = Autokey(bestkey).decipher(ctext)
bestscore = qgram.score(pt)
for i in range(N):
pt = Autokey(rec[i][1]).decipher(ctext)
score = qgram.score(pt)
if score > bestscore:
bestkey = rec[i][1]
bestscore = score
print(bestscore,'autokey, klen',KLEN,':"'+bestkey+'",',Autokey(bestkey).decipher(ctext).lower())
得到一句明文为,ohnoyoufindtheflagtheflagforyouisdoyoulikeclassicalcipher
得到flag
flag{do_you_like_classical_cipher}
autokey密码
中文为自动密钥密码,是属于多表替换密码的一种,该密钥的构成形式为关键字+明文。
举个例子
明文:THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
关键词:CULTURE
密钥: CULTURE THE QUICK BROWN FOX JUMPS OVER THE
然后再采取与维吉尼亚密码相同的加密方式,在字母表中进行替换
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jIAVNT7s-1665645554165)(C:\Users\25964\AppData\Roaming\Typora\typora-user-images\image-20221013143850119.png)]
即可得到对应的密文
VBP JOZGD IVEQV HYY AIICX CSNL FWW ZVDP WVK
在线解密网站:
http://www.atoolbox.net/Tool.php?Id=920
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
先来分析一下题目的源码
他首先定义了一个加密函数,接下来进行了两个操作,生成字母以及一个迭代,接下来输出密文。
可以发现,原本定义的m明文长度为71位,解密后的c变成了142位,也就是翻了两倍,这是我们的一个信息点
因为我们现在未知的,一个是a,一个是salt,在已知信息m中给了我们一段flag,它处于第53位,对应到密文里,翻倍也就是106位,就可以根据这个信息来进行爆破
因此我们得到对应关系
f ⇒ 1c l ⇒ 29 a ⇒ 56 g ⇒ 66
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__":
for i in range(50,100):
for j in ascii_uppercase:
si = cycle(j.lower())
if encrypt('l', i, si)=='29':
print('i =',i,'\tj =',j)
if encrypt('f', i, si)=='1c':
print('i =',i,'\tj =',j)
我们二者取共同点,得到a=67
再使用他得加密函数,通过a来求得salt
if encrypt('a', 67, si)=='56':
print('j =',j)
if encrypt('g', 67, si)=='66':
print('j =',j)
即我们现在得到了,a=67,salt=JESQ,即有
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(si)) % 128)[2:].zfill(2)
return c
if __name__ == "__main__":
salt = 'JESQ'
si = cycle(salt.lower())
c = '3472184e657e50561c481f5c1c4e1938163e154431015e13062c1b073d4e3a444f4a5c5c7a071919167b034e1c29566647600c4e1c2956661b6c1f50622f0016317e563546202a'
res = ''
for i in range(0,len(c),2):
ssi = next(si)
for j in range(32,127):
if encrypt(chr(j),67,ssi)==c[i]+c[i+1]:
res += chr(j)
print(res)
得到res
now_is_7fad9fcb-d361-4964-821c-177c906b8d20_flag_is_flag{md5(now-salt)}
由flag后文得知,还需要再进行一次md5加密,加密后为需要得flag
flag{1efce62ee0a96e39149e2179db1dd04c}
crypto3_多少离怀
Weird Γ(x)? @⎝Lazzaro⎠师傅供题
# -*- 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
观察它给出得数字,p,q,n,c已经全部给出,现在只剩一个(gamma(B+2)%A)是未知数,而这涉及到伽马函数,即
gamma(n)=(n-1)!
那我们就可以转换成
(B+1)!%A
再根据威尔逊定理第一条
当且仅当p为素数时:(p-1)! ≡ -1 (mod p)
推论:(p-2)! ≡ 1 (mod p)
设出(A-2)!%A=1
再令x=(A-2)/(B+1)!,y=(B+1)!,即可得到x * y ≡ 1 (mod A),因为现在y是x关于A得一个逆元,所以我们要先求X%A,进而求出y%A。
from Crypto.Util.number import getPrime,isPrime
import gmpy2
def nextPrime(n):
n += 2 if n & 1 else 1
while not isPrime(n):
n += 2
return n
def factorial_mod(A,B):
ans = 1
tmp = pow(-1,1,A)
for i in range(B+1,A):
ans = (ans*gmpy2.invert(i,A))%A
return (ans*tmp)%A
pA = 6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723982789
pB = 6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723922147
qA = 7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477881291
qB = 7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477807457
n = 4451906216583258787166698210560165433649728830889954633721198623488802305844782492171757604711145165920462286487680020347239300947225371917344589502941576734875830871998499135120227347066586066943289430156378296665669974728569678779668142712266780949126509440672273927433367293606776081254094682033167575930701870261219046464773708974194213798032346187463443317770758989273370488582862531630356263732232300508706676725203199729764016766683870925164232508407363688370458877688991733322055785233669885166225464068579486683574954699370175267031949720967812902215635630884502987094547523361027411501285252862476410213277925430392164226297316310465146003494714018456407793759170649913180823814850170639706664167149612984905056804131124522209409607977589884632999710708045656852149371030046919242039957767777840304466948549383597755811307383659188216421501912831203089570725388153416013596114462069777713822433178099904907224119
c = 1996198968748552041728429851810599627895157160099076033250854211280074825148767841655949210593646824507865483166496070951130337321360509148527292165245205219296211294789087358959553387392928560150390604911087085313000622842025416521494799132969818997182731021267942464323979261593380113740152841984062184326431879167516288834455296913822921806893572566867611541664848820247889274979245086440402996661226884320574824077910315143756471444347386795428338020162169391827182914043434253974549636668126789355991920452920806351939782281969098470635517019120996509180703896707990501216102290302162705699788457579330150149320348175742131887213742989509004374645723471497302400169849858253644606818874098604333865973357374444445825761600866472906771935670261641342221394488068630591190697667016958881530367047928341661857241378511420562236766886349565409774340321441504290366223243635878057759623855735794209219474650425139791831374
e = 0x10001
p = nextPrime(factorial_mod(pA,pB+1))
q = nextPrime(factorial_mod(qA,qB+1))
r=gmpy2.iroot(n//(p*q*q),3)[0]
phi=(p-1)*q*(q-1)*r*r*(r-1)
d=gmpy2.invert(e,phi)
flag=gmpy2.powmod(c,d,n)
import binascii
print(binascii.unhexlify(hex(flag)[2:]))
flag{N0w_U_knOw_how_70_u5E_W1lS0n'5_Th30r3m~}