【问题标题】:Convert decrypted RSA value to string将解密的 RSA 值转换为字符串
【发布时间】:2017-10-31 08:27:25
【问题描述】:

我正在尝试为我正在计划的 CTF 构建一个模块。这个想法是给你一个加密文件和一个 RSA 公钥,并且必须解密文件。

我有意使用弱 RSA 密钥(128 位),以便对其进行分解并推导出私有指数。我正在使用openssl rsautl-raw 填充选项加密文件,如下所示:

openssl rsautl -encrypt -raw -inkey public_key.pem -pubin -in test.txt -out test.enc

然后我尝试完成这个练习,获取公钥并从那里推导出私有指数。因为我有实际的私钥,所以我能够确认我已经正确地完成了这部分并且拥有正确的素数/私有指数。

在我读入加密文件的代码中,将其转换为十六进制,然后对每个十六进制值执行解密操作。这给我留下了一个非常大的长,例如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 并相信如果作者没有明显删除他们的一些 cmets,它可能会帮助我解决我的问题。我没有在加密上发布此内容,因为它似乎超出了他们的范围,因为问题不直接与加密有关。

编辑:

发帖时我没有看到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']

【问题讨论】:

  • 要加密的数据长度必须小于密钥长度。对于 128 位密钥,最大数据长度为 15 个字节,但没有填充且不安全。这就是为什么使用 AES 等对称加密对数据进行加密的原因。
  • 对于 128 位密钥,它原来是 16 个字节。我知道是因为我尝试使用 128 位密钥加密 15 字节文件并收到“数据对于密钥大小而言太小”错误。我正在使用原始(无)填充使用 RSA 进行加密。正如我在帖子顶部提到的,我正在尝试为 CTF 活动构建一个练习,并意识到这并不安全。
  • @knoight - 你能将m 打印为十六进制值吗?
  • @zwer 是的,当我将文件分成 64 位块时,我编辑的第一个列表中的两个十六进制值是 m。是这个意思吗?

标签: python encryption cryptography rsa


【解决方案1】:

您应该直接跳过转换为十六进制的部分。十六进制是密文的文本表示,以字节为单位。但是,您只需要字节,而不是人类可读的表示。

要转换为纯文本,您需要一个名为 I2OSP:Integer to Octet String Primitive 的函数,它只是将纯文本作为数字转换为与密钥大小相同大小的字节数组 - 即 RSA 模数的大小。 RSA 使用大端格式的无符号数。

之后,您需要将字节解码为 ASCII 字符串并打印结果。

【讨论】:

  • 谢谢!我发现了很多关于 RSA 的帖子,但我读到的所有帖子似乎都忽略了这部分。
猜你喜欢
  • 1970-01-01
  • 2014-02-06
  • 2011-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-15
相关资源
最近更新 更多