2024网鼎杯青龙组wp:Crypto2

发布于:2024-11-03 ⋅ 阅读:(117) ⋅ 点赞:(0)

题目

附件内容如下

# coding: utf-8
#!/usr/bin/env python2

import 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 flag

def 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_char
        else:
            ciphertext += char

    return ciphertext

victory_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 t2
    if t2 == zero:
        return t2
    (m1, n1) = t1
    (m2, n2) = t2
    if m1 == m2:
        if n1 == 0 or n1 != n2:
            return zero
        else:
            k = (3 * m1 * m1 + a) % p * gmpy2.invert(2 * n1 , p) % p
    else:
        k = (n2 - n1 + p) % p * gmpy2.invert((m2 - m1 + p) % p, p) % p
    m3 = (k * k % p - m1 - m2 + p * 2) % p
    n3 = (k * (m1 - m3) % p - n1 + p) % p
    return (int(m3),int(n3))

def multiplication(x, k):
    ans = zero
    t = 1
    while(t <= k):
        if (k &t )>0:
            ans = addition(ans, x)
        x = addition(x, x)
        t <<= 1
    return ans

def getrs(z, k):
    (xp, yp) = P
    r = xp
    s = (z + r * dA % n) % n * gmpy2.invert(k, n) % n
    return r,s

z1 = 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_char
        else:
            plaintext += char

    return plaintext

victory_key = "WANGDINGCUP"
decrypted_flag = victory_decrypt(plaintext, victory_key)

print("Decrypted flag:", decrypted_flag.lower())

运行之后得到结果


网站公告

今日签到

点亮在社区的每一天
去签到