DASCTF 2023 & 0X401七月暑期挑战赛——ezDHKE
1、题目描述:
查看代码
from Crypto.Util.number import *
from Crypto.Cipher import AES
from hashlib import sha256
from random import randbytes, getrandbits
from flag import flag
def diffie_hellman(g, p, flag):
alice = getrandbits(1024)
bob = getrandbits(1024)
alice_c = pow(g, alice, p)
bob_c = pow(g, bob, p)
print(alice_c , bob_c)
key = sha256(long_to_bytes(pow(bob_c, alice, p))).digest()
iv = b"dasctfdasctfdasc"
aes = AES.new(key, AES.MODE_CBC, iv)
enc = aes.encrypt(flag)
print(enc)
def getp():
p = int(input("P = "))
assert isPrime(p)
assert p.bit_length() >= 1024 and p.bit_length() <= 2048
g = 2
diffie_hellman(g, p, flag)
getp()
2、题目分析:
首先简化一下题目流程:
y 1 ≡ g^a ( m o d p )
y 2 ≡ g^b ( m o d p )
k e y ≡ g^(a ⋅ b) ( m o d p )
已知 y 1 , y 2 , g , p , 求 k e y , 其中 p 自己选择 ( 经典的离散对数问题 D L P ) 。
只要把 p 选正确了,再使用 d i s c r e t e l o g ( ) , a , b 就能很快出来 。
当然,这里只要求出 a 或 b 就行,没有必要两个都求。哈哈~
所以,关键在于 p 的选取了 ,那当然是选 p − 1 光滑数了,因子越小且越多,结果越容易得出 。
3、获取光滑数
查看代码
# 方法一:
def myPrime(bits):
while True:
n = 2
while n.bit_length() < bits:
n *= choice(sieve_base)
if isPrime(n + 1):
return n + 1
print(myPrime(1024))
# 方法二:
def init():
primes = []
p = 1
while len(primes) < 100:
p = next_prime(p)
primes.append(int(p))
return primes
def genMyPrimeA(bits):
while True:
g = 2
while g < 2 ** bits:
g *= random.choice(primes)
g += 1
if isPrime(g):
return g
primes = init()
print(genMyPrimeA(1024))
# 方法三:
for i in range(10000):
p = (i<<1024)+1
if isPrime(p):
print(p)
break
方法三其实为最优解,毕竟因数中的2又小又多,discrete_log()打一下结果秒出p出来了,之后便是正常的过程了
# sage
from Crypto.Util.number import *
from hashlib import *
from Crypto.Cipher import AES
p = 2492173519580396207260273583035401721936818532531412721958546193123199183809628015833810174888437077034020940145692006727703873004675257294042241804202346880422458275654783154739252083431240631535327950342922477066016603941003106019151745883988610899820235937614893707165706298487812802385444940496938785114651
A = 715335919016654816446102099094868134297789515423652054915964567424119462834464392719018232157309717997941307040048634222382457383557326993555987301288353821550940739122114753538704714160461728127423897757748356821619714662475183119381090878184436346051629155728469283154001947537385729587825693056234577943934
B = 1190605702713463149128389203183792837151025572940475499564494063011978907664624042211070458987174192231198372936172558351794117665581868503042132460328029054131214174137231671140826217310830060933673159810418076714832162830913822905905701771022323126756138610124206588856655642612360214859329692667930335795861
c = b'\xce\x01 \x8c\xc7p\xb7\x1d)\x0ci[\xd8\xb1\xcc\x86\xaf\x1b\xba.PC\x99a8o\xc2\xfc\xc8\xb5w\xecO\x10\xd6:\x8d\xf0\x16u\xe2\x89\xd9\x00\xa9\x1a\x88u'
G = Zmod(p)
a = discrete_log(G(A), G(2))
key = sha256(long_to_bytes(pow(B,a,p))).digest()
iv = b'dasctfdasctfdasc'
aes = AES.new(key,AES.MODE_CBC,iv)
flag = aes.decrypt(c)
print(flag)
# b'DASCTF{8679096d-8f55-4cf6-8403-14dcafe25e26}'
上图代码使用VScode跑的,右上角需要切换内核为Sagemath而不是Python,详细内核切换与使用请参考本博客文章
[LitCTF 2023]baby_xor