2024网鼎杯青龙组wp:Crypto2
题目
附件内容如下
# coding: utf-8
#!/usr/bin/env python2import gmpy2
import random
import binascii
from hashlib import sha256
from sympy import nextprime
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.number import long_to_bytes
from FLAG import flag
#flag = 'wdflag{123}'
import flagdef victory_encrypt(plaintext, key):key = key.upper()key_length = len(key)plaintext = plaintext.upper()ciphertext = ''for i, char in enumerate(plaintext):if char.isalpha():shift = ord(key[i % key_length]) - ord('A')encrypted_char = chr((ord(char) - ord('A') + shift) % 26 + ord('A'))ciphertext += encrypted_charelse:ciphertext += charreturn ciphertextvictory_key = "WANGDINGCUP"
victory_encrypted_flag = victory_encrypt(flag, victory_key)p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
a = 0
b = 7
xG = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
yG = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
G = (xG, yG)
n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
h = 1
zero = (0,0)dA = nextprime(random.randint(0, n))if dA > n:print("warning!!")def addition(t1, t2):if t1 == zero:return t2if t2 == zero:return t2(m1, n1) = t1(m2, n2) = t2if m1 == m2:if n1 == 0 or n1 != n2:return zeroelse:k = (3 * m1 * m1 + a) % p * gmpy2.invert(2 * n1 , p) % pelse:k = (n2 - n1 + p) % p * gmpy2.invert((m2 - m1 + p) % p, p) % pm3 = (k * k % p - m1 - m2 + p * 2) % pn3 = (k * (m1 - m3) % p - n1 + p) % preturn (int(m3),int(n3))def multiplication(x, k):ans = zerot = 1while(t <= k):if (k &t )>0:ans = addition(ans, x)x = addition(x, x)t <<= 1return ansdef getrs(z, k):(xp, yp) = Pr = xps = (z + r * dA % n) % n * gmpy2.invert(k, n) % nreturn r,sz1 = random.randint(0, p)
z2 = random.randint(0, p)
k = random.randint(0, n)
P = multiplication(G, k)
hA = multiplication(G, dA)
r1, s1 = getrs(z1, k)
r2, s2 = getrs(z2, k)print("r1 = {}".format(r1))
print("r2 = {}".format(r2))
print("s1 = {}".format(s1))
print("s2 = {}".format(s2))
print("z1 = {}".format(z1))
print("z2 = {}".format(z2))key = sha256(long_to_bytes(dA)).digest()
cipher = AES.new(key, AES.MODE_CBC)
iv = cipher.iv
encrypted_flag = cipher.encrypt(pad(victory_encrypted_flag.encode(), AES.block_size))
encrypted_flag_hex = binascii.hexlify(iv + encrypted_flag).decode('utf-8')print("Encrypted flag (AES in CBC mode, hex):", encrypted_flag_hex)# output
# r1 = 111817653331957669294460466848850458804857945556928458406600106150268654577388
# r2 = 111817653331957669294460466848850458804857945556928458406600106150268654577388
# s1 = 86614391420642776223990568523561232627667766343605236785504627521619587526774
# s2 = 99777373725561160499828739472284705447694429465579067222876023876942075279416
# z1 = 96525870193778873849147733081234547336150390817999790407096946391065286856874
# z2 = 80138688082399628724400273131729065525373481983222188646486307533062536927379
# ('Encrypted flag (AES in CBC mode, hex):', u'6c201c3c4e8b0a2cdd0eca11e7101d45d7b33147d27ad1b9d57e3d1e20c7b3c2e36b8da3142dfd5abe335a604ce7018878b9f157099211a7bbda56ef5285ec0b')
已知为凯撒加密,椭圆曲线加密,aes加密
使用密钥明文flag凯撒加密。每个字符通过其对应的密钥字符进行位移加密,非字母字符保持不变。
生成一个随机的私钥(dA),并计算相应的公钥(hA)。使用椭圆曲线点加法和乘法实现密钥的生成。对两个随机数 (z1 和 z2) 进行签名,得到签名对 (r1, s1) 和 (r2, s2)。
用 SHA-256 生成的密钥对经过凯撒加密的明文进行 AES 加密,使用 CBC 模式,并生成一个初始化向量(IV)。将加密的标志转换为十六进制格式输出。
有函数getrs(),可以知道:
s1=(z1+r1*dA)*k逆, s2=(z2+r2*dA)*k逆, 其中: k逆 和 dA未知。 k逆是 k对模n的逆元。
解一元二次方程就得到: k 和 dA。
dA 的 sha256就是AES的秘钥,密文的前16字节是AES的IV, 后面的16字节以后的密文,就是真实的密文,
解密出来后, 在用维吉尼亚密码解密就出明文了
维吉尼亚密码的解密,直接用题目给的, 把 +shift 改成 -shift, 其它不变,就是解密函数
需要知道dA进行aes密钥
payload
from Crypto.Hash import SHA256
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from Crypto.Util.number import long_to_bytes
import binascii
from gmpy2 import invert# 从输出中获取给定的值
r = 111817653331957669294460466848850458804857945556928458406600106150268654577388
s1 = 86614391420642776223990568523561232627667766343605236785504627521619587526774
s2 = 99777373725561160499828739472284705447694429465579067222876023876942075279416
z1 = 96525870193778873849147733081234547336150390817999790407096946391065286856874
z2 = 80138688082399628724400273131729065525373481983222188646486307533062536927379
n_hex = "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
n = int(n_hex, 16)# 计算 k 和 dA
delta_z = (z1 - z2) % n
delta_s = (s1 - s2) % n
k = (delta_z * invert(delta_s, n)) % n
dA = ((s1 * k - z1) * invert(r, n)) % n# 使用 dA 作为密钥对密文解密
key = SHA256.new(long_to_bytes(dA)).digest()encrypted_flag_hex = "6c201c3c4e8b0a2cdd0eca11e7101d45d7b33147d27ad1b9d57e3d1e20c7b3c2e36b8da3142dfd5abe335a604ce7018878b9f157099211a7bbda56ef5285ec0b"
encrypted_flag_bytes = bytes.fromhex(encrypted_flag_hex)
iv = encrypted_flag_bytes[:16]
encrypted_flag = encrypted_flag_bytes[16:]cipher = AES.new(key, AES.MODE_CBC, iv=iv)
plaintext_padded = cipher.decrypt(encrypted_flag)
plaintext = unpad(plaintext_padded, AES.block_size).decode()# 使用 Victory Cipher 解密
def victory_decrypt(ciphertext, key):key = key.upper()key_length = len(key)plaintext = ""for i, char in enumerate(ciphertext.upper()):if char.isalpha():shift = ord(key[i % key_length]) - ord("A")decrypted_char = chr((ord(char) - ord("A") - shift + 26) % 26 + ord("A"))plaintext += decrypted_charelse:plaintext += charreturn plaintextvictory_key = "WANGDINGCUP"
decrypted_flag = victory_decrypt(plaintext, victory_key)print("Decrypted flag:", decrypted_flag.lower())
运行之后得到结果