2

I am trying to build a module for a CTF I am planning. The idea is that you are given an encrypted file and an RSA public key and have to decrypt the file.

I am intentionally using a weak RSA key (128bit) so that it can be factored and the private exponent deduced. I am encrypting a file using openssl rsautl with the -raw padding option like so:

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

I am then attempting to walk through the exercise, taking the public key and deducing the private exponent from there. Since I have the actual private key, I am able to confirm that I have done this part correctly and have the right primes / private exponent.

In my code I read in the encrypted file, convert it to hex and then perform the decrypt operation on each hex value. This leaves me with a very large long, e.g. 133742007812331115643627009906598839927 for each decrypted value. Trying to use chr() to convert these to ascii obviously fails with a OverflowError: Python int too large to convert to C long error.

My plaintext that I am encrypting: this is a test!

The resulting encrypted value(screenshot to preserve special chars): encrypted value

The hexdump value of the encrypted file:

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

My code:

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)

Which produces the following output:

input as read from file: 6ëC=
hP>·{À3R
input in hex: 36eb433d1d0d68503eb77bc00e335212
133742007812331115643627009906598839927
73331587639103218432501997963763741611
... 14 more longs

My question is how am I supposed to convert these long values back to ascii? Or am I supposed to do some sort of translation before the decryption operation which wouldn't leave me with these longs? Note that I have tried reading the file in 64bits at a time, but that leaves me with 2 large longs that I still don't know how to convert.

I have looked at this post quite a bit and believe it probably would have helped me solve my problem if the author hadn't apparently deleted some of their comments. I didn't post this on crypto because it seems to be outside their scope since the issue isn't directly with the cryptography.

EDIT:

I did not see this question when posting (swear i looked). However even after reviewing that question and modifying my code to break the decryption into 64-bit chunks I am still left with two hex values, which when converted to ascii using chr() do not equal the original plain text:

['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']
knoight
  • 479
  • 8
  • 18
  • The data length to be encrypted must be less than the key length. For a 128-bit key the maximum data length is 15 bytes but that would be without padding and not secure. This is why data is encrypted with symmetric encryption such as AES. – zaph May 30 '17 at 19:02
  • for a 128-bit key it turns out to be 16 bytes. i know because i have tried encrypting a 15 byte file with a 128-bit key and received the "data too small for key size" error. I am encrypting with RSA using raw (no) padding. As i mentioned at the top of my post, I am trying to build an exercise for a CTF event and realize this is not secure. – knoight May 30 '17 at 19:07
  • @knoight - can you print out `m` as hex values? – zwer May 30 '17 at 20:53
  • @zwer yes the two hex values in the first list in my edit are `m` when I break the file into 64bit chunks. Is that what you mean? – knoight May 30 '17 at 21:26

1 Answers1

4

You should simply skip the part where you convert to hexadecimals. Hexadecimals are an textual representation of the ciphertext in bytes. However, you just need the bytes, not the human readable representation.

To convert to plaintext you need a function called I2OSP: Integer to Octet String Primitive, which simply converts the plaintext as number to a byte array of the same size as the key size - i.e. the size of the modulus for RSA. RSA uses unsigned numbers in the big endian format.

After that you need to decode the bytes as ASCII string and print the result.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Thank you! I found many posts about RSA and yet all the ones I read seemed to leave out this part. – knoight May 31 '17 at 12:07