Crypto
[Very Easy] Dynastic 凯撒变体
source.py
from secret import FLAG
from random import randint
def to_identity_map(a):
return ord(a) - 0x41
def from_identity_map(a):
return chr(a % 26 + 0x41)
def encrypt(m):
c = ''
for i in range(len(m)):
ch = m[i]
if not ch.isalpha():
ech = ch
else:
chi = to_identity_map(ch)
ech = from_identity_map(chi + i)
c += ech
return c
with open('output.txt', 'w') as f:
f.write('Make sure you wrap the decrypted text with the HTB flag format :-]\n')
f.write(encrypt(FLAG))
output.txt
Make sure you wrap the decrypted text with the HTB flag format :-]
DJF_CTA_SWYH_NPDKK_MBZ_QPHTIGPMZY_KRZSQE?!_ZL_CN_PGLIMCU_YU_KJODME_RYGZXL
解题:
1、分析源码:
对于加密函数,遍历flag的每个字符,对于不是字母的字符,不做变换,对于字母,先由其ascii值减去0x41
,再结果进行加i
运算,模26
取余后,再加上0x41
,然后输出密文。
2、解题思路
0x41
刚好是A的ascii
值,所以该题为简单的单表替换,密文均为大写,为凯撒的变体,第一位右移1
位,第二位右移2
位,解密对应相反的方法,第一位左移1
位,第二位左移2
位,依次类推
3、解题代码
def to_identity_map(a):
return ord(a) - 0x41
def from_identity_map(a):
return chr(a % 26 + 0x41)
def decrypt(enc):
flag = ''
for i in range(len(enc)):
ech = enc[i]
if not ech.isalpha():
m = ech
else:
echi = to_identity_map(ech)
m = from_identity_map(echi - i)
flag += m
return flag
cipher = "DJF_CTA_SWYH_NPDKK_MBZ_QPHTIGPMZY_KRZSQE?!_ZL_CN_PGLIMCU_YU_KJODME_RYGZXL"
print("HTB{"+decrypt(cipher)+"}")
HTB{DID_YOU_KNOW_ABOUT_THE_TRITHEMIUS_CIPHER?!_IT_IS_SIMILAR_TO_CAESAR_CIPHER}
[Very Easy] Primary Knowledge 基本RSA
source.py
import math
from Crypto.Util.number import getPrime, bytes_to_long
from secret import FLAG
m = bytes_to_long(FLAG)
n = math.prod([getPrime(1024) for _ in range(2**0)])
e = 0x10001
c = pow(m, e, n)
with open('output.txt', 'w') as f:
f.write(f'{n = }\n')
f.write(f'{e = }\n')
f.write(f'{c = }\n')
output.txt
n = 144595784022187052238125262458232959109987136704231245881870735843030914418780422519197073054193003090872912033596512666042758783502695953159051463566278382720140120749528617388336646147072604310690631290350467553484062369903150007357049541933018919332888376075574412714397536728967816658337874664379646535347
e = 65537
c = 15114190905253542247495696649766224943647565245575793033722173362381895081574269185793855569028304967185492350704248662115269163914175084627211079781200695659317523835901228170250632843476020488370822347715086086989906717932813405479321939826364601353394090531331666739056025477042690259429336665430591623215
1、代码分析
n = math.prod([getPrime(1024) for _ in range(2**0)])
该代码,说明n
就是素数(只有一个因数乘积),直接解密即可
2、解题
from Crypto.Util.number import *
import gmpy2
n = 144595784022187052238125262458232959109987136704231245881870735843030914418780422519197073054193003090872912033596512666042758783502695953159051463566278382720140120749528617388336646147072604310690631290350467553484062369903150007357049541933018919332888376075574412714397536728967816658337874664379646535347
e = 65537
c = 15114190905253542247495696649766224943647565245575793033722173362381895081574269185793855569028304967185492350704248662115269163914175084627211079781200695659317523835901228170250632843476020488370822347715086086989906717932813405479321939826364601353394090531331666739056025477042690259429336665430591623215
def compute_phi(n):
return n-1
def compute_private_key(n,e):
phi = compute_phi(n)
d = gmpy2.invert(e,phi)
return d
print(long_to_bytes(pow(c,compute_private_key(n,e),n)))
b'HTB{0h_d4mn_4ny7h1ng_r41s3d_t0_0_1s_1!!!}'
[Very Easy] Makeshift
source.py
from secret import FLAG
flag = FLAG[::-1]
new_flag = ''
for i in range(0, len(flag), 3):
new_flag += flag[i+1]
new_flag += flag[i+2]
new_flag += flag[i]
print(new_flag)
!?}De!e3d_5n_nipaOw_3eTR3bt4{_THB
1、代码分析
- 第二个字符作为第一个字符
- 第三个字符作为第二个字符
- 第一个字符作为第三个字符
2、解题
- 第三个字符作为第一个字符
- 第一个字符作为第二个字符
- 第二个字符作为第三个字符
- 再将其转置
3、解决
def decrypt(c):
flag = ""
for i in range(0,len(c),3):
flag += c[i+2]
flag += c[i]
flag += c[i+1]
flag = flag[::-1]
return flag
cipher = "!?}De!e3d_5n_nipaOw_3eTR3bt4{_THB"
print(decrypt(cipher))
HTB{4_b3tTeR_w3apOn_i5_n3edeD!?!}
[Easy] Blunt 离散对数问题
source.py
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.number import getPrime, long_to_bytes
from hashlib import sha256
from secret import FLAG
import random
p = getPrime(32)
print(f'p = 0x{p:x}')
g = random.randint(1, p-1)
print(f'g = 0x{g:x}')
a = random.randint(1, p-1)
b = random.randint(1, p-1)
A, B = pow(g, a, p), pow(g, b, p)
print(f'A = 0x{A:x}')
print(f'B = 0x{B:x}')
C = pow(A, b, p)
assert C == pow(B, a, p)
# now use it as shared secret
hash = sha256()
hash.update(long_to_bytes(C))
key = hash.digest()[:16]
iv = b'\xc1V2\xe7\xed\xc7@8\xf9\\\xef\x80\xd7\x80L*'
cipher = AES.new(key, AES.MODE_CBC, iv)
encrypted = cipher.encrypt(pad(FLAG, 16))
print(f'ciphertext = {encrypted}')
output.txt
p = 0xdd6cc28d
g = 0x83e21c05
A = 0xcfabb6dd
B = 0xc4a21ba9
ciphertext = b'\x94\x99\x01\xd1\xad\x95\xe0\x13\xb3\xacZj{\x97|z\x1a(&\xe8\x01\xe4Y\x08\xc4\xbeN\xcd\xb2*\xe6{'
1、代码分析
首先给出32位的素数p,又给出1~p-1
的数g,给出a,b两个数,对a,b处理,得到A,B:pow(g,a,p)
,然后又C=pow(A,b,p)
,取C的哈希值的前16位作为AES的密钥,对flag进行加密,那我们求得flag的关键,就是得到密钥key,即求得C的值,因为a,b未知,我们求得a,b中的一个值即可,且
是典型的离散对数问题
2、题目分析
欧拉定理
对于任意的a,m,只要gcd(a,m)=1
,有
阶:对于与m互质的数a,满足\(a^n \equiv 1(mod \quad m)\)的最小整数n,为a模m的阶
若阶等于phi(n)
时,称其为模m的原根
BSGS(小步大步法)
作为该题,我们要求得a的值,即求,满足题目条件,且小于p-1的所有值,我们令a = k*s+r
其中,我们令s=p^(1/2)(向下取整),(r<s)
,因为a<p,所以,k和r均在0~m
的范围内,因此
即
\[y*(g^{-ks})=g^r \]枚举r的值,计算\(g^r\)的值,存放在集合中,因为s是确定的,所以每一个a的都与唯一的(k,r)挂钩,我们就可以再枚举k的值,计算\(yg^{-ks}\)的值,如果结果在集合中,说明我们得到了所求的a
因为该题中g的值较小,采用该方法,将时间与空间折中的方式
3、代码
import math
import hashlib
from Crypto.Util.number import *
from Crypto.Cipher import AES
p = 0xdd6cc28d
g = 0x83e21c05
A = 0xcfabb6dd
B = 0xc4a21ba9
ciphertext = b'\x94\x99\x01\xd1\xad\x95\xe0\x13\xb3\xacZj{\x97|z\x1a(&\xe8\x01\xe4Y\x08\xc4\xbeN\xcd\xb2*\xe6{'
def bsgs(g, y, p):
m = int(math.ceil(math.sqrt(p - 1)))
S = {pow(g, j, p): j for j in range(m)}
gs = pow(g, p - 1 - m, p)
for i in range(m):
if y in S:
return i * m + S[y]
y = y * gs % p
return None
C = pow(B,bsgs(g,A,p),p)
hash = hashlib.sha256()
hash.update(long_to_bytes(C))
key = hash.digest()[:16]
iv = b'\xc1V2\xe7\xed\xc7@8\xf9\\\xef\x80\xd7\x80L*'
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = cipher.decrypt(ciphertext)
print(decrypted)
b'HTB{y0u_n3ed_a_b1gGeR_w3ap0n!!}\x01'
参考:https://ctf-wiki.org/crypto/asymmetric/discrete-log/discrete-log/
[Easy] Iced Tea 对称加密
source.py
import os
from secret import FLAG
from Crypto.Util.Padding import pad
from Crypto.Util.number import bytes_to_long as b2l, long_to_bytes as l2b
from enum import Enum
class Mode(Enum):
ECB = 0x01
CBC = 0x02
class Cipher:
def __init__(self, key, iv=None):
self.BLOCK_SIZE = 64
self.KEY = [b2l(key[i:i+self.BLOCK_SIZE//16]) for i in range(0, len(key), self.BLOCK_SIZE//16)]
self.DELTA = 0x9e3779b9
self.IV = iv
if self.IV:
self.mode = Mode.CBC
else:
self.mode = Mode.ECB
def _xor(self, a, b):
return b''.join(bytes([_a ^ _b]) for _a, _b in zip(a, b))
def encrypt(self, msg):
msg = pad(msg, self.BLOCK_SIZE//8)
blocks = [msg[i:i+self.BLOCK_SIZE//8] for i in range(0, len(msg), self.BLOCK_SIZE//8)]
ct = b''
if self.mode == Mode.ECB:
for pt in blocks:
ct += self.encrypt_block(pt)
elif self.mode == Mode.CBC:
X = self.IV
for pt in blocks:
enc_block = self.encrypt_block(self._xor(X, pt))
ct += enc_block
X = enc_block
return ct
def encrypt_block(self, msg):
m0 = b2l(msg[:4])
m1 = b2l(msg[4:])
K = self.KEY
msk = (1 << (self.BLOCK_SIZE//2)) - 1
s = 0
for i in range(32):
s += self.DELTA
m0 += ((m1 << 4) + K[0]) ^ (m1 + s) ^ ((m1 >> 5) + K[1])
m0 &= msk
m1 += ((m0 << 4) + K[2]) ^ (m0 + s) ^ ((m0 >> 5) + K[3])
m1 &= msk
m = ((m0 << (self.BLOCK_SIZE//2)) + m1) & ((1 << self.BLOCK_SIZE) - 1) # m = m0 || m1
return l2b(m)
if __name__ == '__main__':
KEY = os.urandom(16)
cipher = Cipher(KEY)
ct = cipher.encrypt(FLAG)
with open('output.txt', 'w') as f:
f.write(f'Key : {KEY.hex()}\nCiphertext : {ct.hex()}')
1、代码分析
首先生成了16位随机生成的key,然后对key进行了分组,将其分为了四部分,作为加密流密钥,其次,选择了ECB模式,然后对flag进行加密,将flag填充为8字节的倍数,然后按8字节分块,采用ECB模式,对每一分块,进行加密
再看分块加密,将其分为两部分,分别转换为数字,两部分别加上不同的数,然后与msk做与运算,说明只保留32位二进制,溢出的高位舍去,经过多次的循环再将两部分合到一起,高位依然是高位,然后添加到密文中
2、解题思路
对于对称加密来讲,我们只需将其过程逆过来即可
3、代码:
from Crypto.Util.number import bytes_to_long as b2l, long_to_bytes as l2b
msg = 'b36c62d96d9daaa90634242e1e6c76556d020de35f7a3b248ed71351cc3f3da97d4d8fd0ebc5c06a655eb57f2b250dcb2b39c8b2000297f635ce4a44110ec66596c50624d6ab582b2fd92228a21ad9eece4729e589aba644393f57736a0b870308ff00d778214f238056b8cf5721a843'
msg = bytes.fromhex(msg)
DELTA = 0x9e3779b9
BLOCK_SIZE = 64
key="850c1413787c389e0b34437a6828a1b2"
key = bytes.fromhex(key)
K = [b2l(key[i:i+BLOCK_SIZE//16]) for i in range(0, len(key), BLOCK_SIZE//16)]
print(K)
blocks = [msg[i:i+BLOCK_SIZE//8] for i in range(0,len(msg),BLOCK_SIZE//8)]
def decry(msg):
m0 = b2l(pt[:4])
m1 = b2l(pt[4:])
s = 0x9e3779b9*33
msk = (1 << (BLOCK_SIZE // 2)) - 1
for i in range(32):
s = s - DELTA
m1 -= ((m0 << 4) + K[2]) ^ (m0 + s) ^ ((m0 >> 5) + K[3])
m1 &= msk
m0 -= ((m1 << 4) + K[0]) ^ (m1 + s) ^ ((m1 >> 5) + K[1])
m0 &= msk
m = ((m0<<(BLOCK_SIZE//2)) +m1) & ((1 << BLOCK_SIZE) - 1)
return l2b(m)
flag = b''
for pt in blocks:
flag+=decry(pt)
print(flag)
b'HTB{th1s_1s_th3_t1ny_3ncryp710n_4lg0r1thm_____y0u_m1ght_h4v3_4lr34dy_s7umbl3d_up0n_1t_1f_y0u_d0_r3v3rs1ng}\x06\x06\x06\x06\x06\x06'
[Medium] Partial Tenacity
source.py
from secret import FLAG
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
class RSACipher:
def __init__(self, bits):
self.key = RSA.generate(bits)
self.cipher = PKCS1_OAEP.new(self.key)
def encrypt(self, m):
return self.cipher.encrypt(m)
def decrypt(self, c):
return self.cipher.decrypt(c)
cipher = RSACipher(1024)
enc_flag = cipher.encrypt(FLAG)
with open('output.txt', 'w') as f:
f.write(f'n = {cipher.key.n}\n')
f.write(f'ct = {enc_flag.hex()}\n')
f.write(f'p = {str(cipher.key.p)[::2]}\n')
f.write(f'q = {str(cipher.key.q)[1::2]}')
output.txt
n = 118641897764566817417551054135914458085151243893181692085585606712347004549784923154978949512746946759125187896834583143236980760760749398862405478042140850200893707709475167551056980474794729592748211827841494511437980466936302569013868048998752111754493558258605042130232239629213049847684412075111663446003
ct = 7f33a035c6390508cee1d0277f4712bf01a01a46677233f16387fae072d07bdee4f535b0bd66efa4f2475dc8515696cbc4bc2280c20c93726212695d770b0a8295e2bacbd6b59487b329cc36a5516567b948fed368bf02c50a39e6549312dc6badfef84d4e30494e9ef0a47bd97305639c875b16306fcd91146d3d126c1ea476
p = 151441473357136152985216980397525591305875094288738820699069271674022167902643
q = 15624342005774166525024608067426557093567392652723175301615422384508274269305
1、代码分析
正常的RSA加密,给出了p,q的不同位,该题需要我们恢复p,q,即可拿到flag
2、思路
首先,我们可以使用一个掩码来表示哪一位的缺失,安全的RSA中,p,q的长度一般是一致的,我们便可以生成p,q的掩码,比如0代表该位缺失
def create_masks(primelen):#primelen是根号n的长度
pmask = ''.join(['1' if i % 2 == 0 else '0' for i in range(primelen)])
qmask = ''.join(['1' if i % 2 == 1 else '0' for i in range(primelen)])
return pmask, qmask
其次,我们假设n = 3221,p=41,q = 81,此时pmask=10,qmask = 01,然后已知的p,q为4,1,对于最后一位数,n = 1,我们可以列出所有的可能式,比如
\[\\ 1*1=1 \\3*7=21\\ 7*2=21 \\9*9=81 \]所以可以得出p的最后以为也是1,然后是倒数第二位,n = 2,p=4,此时
\[3*4=12 \\ 8*4 = 32 \]所以有两个值,3,8,我们可以进行运算,
\[41*31 = 1271 \\ 41*81 = 3221 \]可以看到,乘积结尾为21,即可恢复p,q
算法可以概括如下:
-
对于位置i的数字,我们可以提取pmask和qmask的第i个字符。
-
如果pmask[i] = 1,那么我们知道p的第i位数字,所以提取它。
- 暴力测试q的所有10个可能的候选值。
- 检查是否n(mod10i ) == ( p ⋅ q ) (mod10i ) 。
- 满足这个关系的q[i]的候选值就是正确的。
-
否则,我们知道q的第i位数字,所以提取它,并重复相同的步骤,直到p,q的所有位都被恢复。
def restore(i,n,know,check,hint):
msk = 10**(i+1)
know = 10**i*(hint%10)+know #提取已知位,并恢复
for d in range(10):
test = 10**i*d+ check #为未知的位,赋高位,来做检验
if n%msk == (know * test)%msk :
check = test
hint = hint //10
return know,check,hint
def factor(n,p,q,hp,hq,pmask,qmask):
for i in range(len(pmask)):
if pmask[-i-1] == '1':
p,q,hp = restore(i,n,p,q,hp)
else:
q,p,hq = restore(i,n,q,p,hq)
assert n==p*q
return p*q
3、代码
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from gmpy2 import *
from Crypto.Util.number import *
n = 118641897764566817417551054135914458085151243893181692085585606712347004549784923154978949512746946759125187896834583143236980760760749398862405478042140850200893707709475167551056980474794729592748211827841494511437980466936302569013868048998752111754493558258605042130232239629213049847684412075111663446003
ct = 0x7f33a035c6390508cee1d0277f4712bf01a01a46677233f16387fae072d07bdee4f535b0bd66efa4f2475dc8515696cbc4bc2280c20c93726212695d770b0a8295e2bacbd6b59487b329cc36a5516567b948fed368bf02c50a39e6549312dc6badfef84d4e30494e9ef0a47bd97305639c875b16306fcd91146d3d126c1ea476
hp = 151441473357136152985216980397525591305875094288738820699069271674022167902643
hq = 15624342005774166525024608067426557093567392652723175301615422384508274269305
def create_masks(primelen):
pmask = ''.join(['1' if i % 2 == 0 else '0' for i in range(primelen)])
qmask = ''.join(['1' if i % 2 == 1 else '0' for i in range(primelen)])
return pmask, qmask
def restore(i,n,know,check,hint):
msk = 10**(i+1)
know = 10**i*(hint%10)+know #提取已知位,并恢复
for d in range(10):
test = 10**i*d+ check #为未知的位,赋高位,来做检验
if n%msk == (know * test)%msk :
check = test
hint = hint //10
return know,check,hint
def factor(n,p,q,hp,hq,pmask,qmask):
for i in range(len(pmask)):
if pmask[-i-1] == '1':
p,q,hp = restore(i,n,p,q,hp)
else:
q,p,hq = restore(i,n,q,p,hq)
assert n==p*q
return p,q
def decrypt(p, q, n, ct):
e = 0x10001
d = pow(e, -1, (p-1)*(q-1))
key = RSA.construct((n, e, d))
flag = PKCS1_OAEP.new(key).decrypt(ct)
return flag
ct = long_to_bytes(ct)
pmask,qmask = create_masks(len(str(int(sqrt(n)))))
p,q = factor(n,0,0,hp,hq,pmask,qmask)
print(decrypt(p,q,n,ct))
b'HTB{v3r1fy1ng_pr1m3s_m0dul0_p0w3rs_0f_10!}'
[Medium] Arranged ECC
source.py
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.number import long_to_bytes
from hashlib import sha256
from secret import FLAG, p, b, priv_a, priv_b
F = GF(p)
E = EllipticCurve(F, [726, b])
G = E(926644437000604217447316655857202297402572559368538978912888106419470011487878351667380679323664062362524967242819810112524880301882054682462685841995367, 4856802955780604241403155772782614224057462426619061437325274365157616489963087648882578621484232159439344263863246191729458550632500259702851115715803253)
A = G * priv_a
B = G * priv_b
print(A)
print(B)
C = priv_a * B
assert C == priv_b * A
# now use it as shared secret
secret = C[0]
hash = sha256()
hash.update(long_to_bytes(secret))
key = hash.digest()[16:32]
iv = b'u\x8fo\x9aK\xc5\x17\xa7>[\x18\xa3\xc5\x11\x9en'
cipher = AES.new(key, AES.MODE_CBC, iv)
encrypted = cipher.encrypt(pad(FLAG, 16))
print(encrypted)
output.txt
(6174416269259286934151093673164493189253884617479643341333149124572806980379124586263533252636111274525178176274923169261099721987218035121599399265706997 : 2456156841357590320251214761807569562271603953403894230401577941817844043774935363309919542532110972731996540328492565967313383895865130190496346350907696 : 1)
(4226762176873291628054959228555764767094892520498623417484902164747532571129516149589498324130156426781285021938363575037142149243496535991590582169062734 : 425803237362195796450773819823046131597391930883675502922975433050925120921590881749610863732987162129269250945941632435026800264517318677407220354869865 : 1)
b'V\x1b\xc6&\x04Z\xb0c\xec\x1a\tn\xd9\xa6(\xc1\xe1\xc5I\xf5\x1c\xd3\xa7\xdd\xa0\x84j\x9bob\x9d"\xd8\xf7\x98?^\x9dA{\xde\x08\x8f\x84i\xbf\x1f\xab'
1、代码分析
首先,定义了一个椭圆曲线E,有一个生成元G,且p,b未知,A=aG,B=bG中a,b保密,双方交换abG,作为加密的公钥使用,所求即为公钥
2、思路
对于这个椭圆曲线,给出的参数不全,我们可以先求得所有参数,椭圆曲线构成了一个群,加法和乘法对于这个群是闭合的,所以,A,B也为椭圆曲线上的点,且该椭圆方程为
\[y^2 \equiv x^3 + ax+b (mod \quad p) \]可知:
\[y^2 = x^3 + ax + b + k*p \]A,B,G点显然都满足这个条件,我们可以列出方程
\[a_y^2 = a_x^3 + aa_x +b + k_1p \\ b_y^2 = b_x^3 + ab_x +b + k_2 p \\ g_y^2 = g_x^3 + ag_x +b + k_3 p \]联立可知(k1-k2)*p
和(k2-k3)*p
,(k1-k3)*p
,我们对其求最大公因数,即可得到p
x1 = A[1]^2 - B[1]^2 - A[0]^3 - 726*A[0] + B[0]^3 + 726*B[0]
x2 = A[1]^2 - G[1]^2 - A[0]^3 - 726*A[0] + G[0]^3 + 726*G[0]
p = gcd(x1, x2)
对于b
\[b = (a_y^2 - a_x^3 - aa_x) (mod \quad p) \]b = (A[1]^2 - A[0]^3 - 726*A[0]) % p
这样就得到了椭圆曲线的参数,我们想到打印出G.order
来查看一下,该曲线有多少个点
sage: G.order()
11
只有11个点,那说明abG
只有11中可能,我们可以对其遍历,判断的条件为解密后的明文是否有关键字
代码:
from gmpy2 import *
from Crypto.Util.number import long_to_bytes
from hashlib import *
from Crypto.Cipher import AES
c = b'V\x1b\xc6&\x04Z\xb0c\xec\x1a\tn\xd9\xa6(\xc1\xe1\xc5I\xf5\x1c\xd3\xa7\xdd\xa0\x84j\x9bob\x9d"\xd8\xf7\x98?^\x9dA{\xde\x08\x8f\x84i\xbf\x1f\xab'
A = (6174416269259286934151093673164493189253884617479643341333149124572806980379124586263533252636111274525178176274923169261099721987218035121599399265706997, 2456156841357590320251214761807569562271603953403894230401577941817844043774935363309919542532110972731996540328492565967313383895865130190496346350907696)
B = (4226762176873291628054959228555764767094892520498623417484902164747532571129516149589498324130156426781285021938363575037142149243496535991590582169062734, 425803237362195796450773819823046131597391930883675502922975433050925120921590881749610863732987162129269250945941632435026800264517318677407220354869865)
G = (926644437000604217447316655857202297402572559368538978912888106419470011487878351667380679323664062362524967242819810112524880301882054682462685841995367, 4856802955780604241403155772782614224057462426619061437325274365157616489963087648882578621484232159439344263863246191729458550632500259702851115715803253)
x1 = A[1]^2 - B[1]^2 - A[0]^3 - 726*A[0] + B[0]^3 + 726*B[0]
x2 = A[1]^2 - G[1]^2 - A[0]^3 - 726*A[0] + G[0]^3 + 726*G[0]
p = gcd(x1, x2)
b = (A[1]^2 - A[0]^3 - 726*A[0]) % p
F = GF(p)
E = EllipticCurve(F, [726, b])
G = E(G[0], G[1])
def decrypt(Q):
secret = int(Q[0])
hash = sha256()
hash.update(long_to_bytes(secret))
key = hash.digest()[16:32]
iv = b'u\x8fo\x9aK\xc5\x17\xa7>[\x18\xa3\xc5\x11\x9en'
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = cipher.decrypt(c)
return decrypted
for i in range(1, 12):
P = i*G
msg = decrypt(P)
if b'HTB{' in msg:
print(msg)
break
b'HTB{0rD3r_mUsT_b3_prEs3RveD_!!@!}\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f'
标签:return,self,flag,key,import,Cryptowp,def
From: https://www.cnblogs.com/zMeedA/p/18137882