密码学实战 - HTB TwoForOne

161 阅读5分钟

概述

TwoForOne是来自于HTB(hackthebox.com)的一个容易级密码学挑战,完成该挑战所需要掌握的知识点在于RSA加密算法。

题目分析

相关的任务文件包括两个RSA公钥文件key1.pemkey2.pem,以及相对应的两个密文文件message1message2. 任务说明中则提示相同的明文被加密两次。


## 解题过程

首先获得RSA公钥文件所提供的参数,

```python
from Crypto.PublicKey import RSA
with open('key1.pem') as f:
  key1 = RSA.importKey(f.read())
  
with open('key2.pem') as f:
  key2 = RSA.importKey(f.read())

key1

RsaKey(n=25080356853331150673712092961488349508728123694382279186941974911344272809718201683391687288116618021523872262260746884803456249468108932413753368793568123710905490623939699616018064364038794824072468125668702688048418916712950393799664781694224559810656290997284081084848717062228887604668548576609649709572412523306016494962925450783098637867249337121156908328927249731928363360657779226929980928871118145919627109584218577535657544952661333527174942990937484743860494188129607347202336812042045820577108243818426559386634634103676467773122325120858908782192357380855678371737765634819794619802582481594876770433687, e=65537)

key2

RsaKey(n=25080356853331150673712092961488349508728123694382279186941974911344272809718201683391687288116618021523872262260746884803456249468108932413753368793568123710905490623939699616018064364038794824072468125668702688048418916712950393799664781694224559810656290997284081084848717062228887604668548576609649709572412523306016494962925450783098637867249337121156908328927249731928363360657779226929980928871118145919627109584218577535657544952661333527174942990937484743860494188129607347202336812042045820577108243818426559386634634103676467773122325120858908782192357380855678371737765634819794619802582481594876770433687, e=343223)

我们可以得知这两个公钥文件的n值相同,但e值不同。 并且e1e2互质。 根据RSA加密算法,在这种情况下,可以使用如下公式获得明文。

mc1ac2b(modn)m \equiv c_1 ^ a * c_2 ^ b \pmod {n}

其中c1c2是两个密文,ab则是满足贝祖等式a * e1 + b * e2 = gcd(e1, e2)的系数。

首先从密文文件获取c1c2, 注意两个密文文件都使用base64编码。

import base64
from Crypto.Util.number import bytes_to_long, long_to_bytes

with open('message1') as f:
  data = f.read()
  ciper_text_1 = bytes_to_long(base64.b64decode(data))
  
with open('message2') as f:
  data = f.read()
  ciper_text_2 = bytes_to_long(base64.b64decode(data))

然后使用扩展欧几里得算法计算ab, 这里使用的是SymPy库。

from sympy.core.numbers import igcdex
a, b, gcd = igcdex(key1.e, key2.e)

最后使用上述的公式计算得到明文。

m = pow(ciper_text_1, a, key1.n) * pow(ciper_text_2, b, key1.n)
m = m % key1.n

message = long_to_bytes(m)
print(message)