我正在尝试为我正在计划的CTF构建一个模块。这个想法是给你一个加密文件和一个RSA公钥,并且必须解密该文件。
我故意使用弱RSA密钥(128位),以便可以对其进行分解并推导出私有指数。我使用openssl rsautl
填充选项使用-raw
加密文件,如下所示:
openssl rsautl -encrypt -raw -inkey public_key.pem -pubin -in test.txt -out test.enc
然后我试图完成练习,拿出公钥并从那里推断私人指数。由于我有实际的私钥,我能够确认我已正确完成此部分并拥有正确的primes / private exponent。
在我的代码中,我读入加密文件,将其转换为十六进制,然后对每个十六进制值执行解密操作。这留下了一个非常大的长,例如每个解密值133742007812331115643627009906598839927
。尝试使用chr()
将这些转换为ascii显然会因OverflowError: Python int too large to convert to C long
错误而失败。
我正在加密的明文:this is a test!
加密文件的hexdump值:
hexdump -C test.enc
00000000 36 eb 43 3d 1d 0d 68 50 3e b7 7b c0 0e 33 52 12 |6.C=..hP>.
{..3R.|
00000010
我的代码:
def testdecrypt():
a = 16
e = 65537
p = 15308793451280999927
n = 225614505179301198794693425143200819953
q = 14737575883906276439
phi = (p-1)*(q-1)
d = multiplicative_inverse(e, phi)
with open('test.enc', 'rb') as file:
input = file.read()
print('input as read from file: {0}'.format(input))
input = binascii.hexlify(input)
input = input.replace('\n', '').replace('\r', '')
m = [hex(pow(int(input[i:i+a], 16), d, n)).rstrip("L") for i in range(0, len(input), a)]
print(m)
for mm in m:
str = []
mm = mm.strip('0x')
for i in range(0, len(mm), 2):
mm_chr = chr(int(mm[i:i+2], 16))
str.append(mm_chr) #put in a list for easier viewing
print(str)
产生以下输出:
input as read from file: 6ëC=
hP>·{À3R
input in hex: 36eb433d1d0d68503eb77bc00e335212
133742007812331115643627009906598839927
73331587639103218432501997963763741611
... 14 more longs
我的问题是我应该如何将这些长值转换回ascii?或者我应该在解密操作之前做一些翻译,这不会让我留下这些长片?请注意,我一次尝试以64位读取文件,但这留下了2个大长度,我仍然不知道如何转换。
我看过this post quite a bit并相信如果作者没有明显删除他们的一些评论,它可能会帮助我解决我的问题。我没有在加密上发布这个,因为它似乎超出了它们的范围,因为问题不是直接加密。
修改
发帖时我没有看到this question(我发誓)。然而,即使在查看该问题并修改我的代码以将解密分解为64位块之后,我仍然留下两个十六进制值,当使用chr()
转换为ascii时,不等于原始纯文本:
['0x4e4b0c3d7b0f232461adcc78364fef76', '0x652ac1281861415bf4d157947791b419']
['N', 'K', '\x0c', '=', '{', '\x0f', '#', '$', 'a', '\xad', '\xcc', 'x', '6', 'O', '\xef', 'v']
['e', '*', '\xc1', '(', '\x18', 'a', 'A', '[', '\xf4', '\xd1', 'W', '\x94', 'w', '\x91', '\xb4', '\x19']
答案 0 :(得分:4)
您应该只跳过转换为十六进制的部分。十六进制是密文的文本表示,以字节为单位。但是,您只需要字节,而不是人类可读的表示。
要转换为纯文本,您需要一个名为I2OSP的函数:整数到Octet String Primitive,它只是将明文作为数字转换为与密钥大小相同大小的字节数组 - 即RSA模数的大小。 RSA使用大端格式的无符号数字。
之后,您需要将字节解码为ASCII字符串并打印结果。