Skip to content
This repository was archived by the owner on Mar 24, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions RSA-encryption/Attack-LSBit-Oracle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,25 +91,31 @@ Consider two messages 2\*m and 4\*m [\[1\]](https://crypto.stackexchange.com/que
You must be wondering how condition 3 and 4 above hold true. You will understand better when you see the script implementing this:
```python
e = 65537
upper_limit = N
upper_limit = 1
lower_limit = 0
denominator = 1

flag = ""
i = 1
# for 1024 bit N
while i <= 1024:
chosen_ct = long_to_bytes((bytes_to_long(flag_enc)*pow(2**i, e, N)) % N)
output = _decrypt(chosen_ct)
delta = upper_limit - lower_limit
upper_limit *= 2
lower_limit *= 2
denominator *= 2
if ord(output[-1]) == 0:
upper_limit = (upper_limit + lower_limit)/2
upper_limit -= delta
elif ord(output[-1]) == 1:
lower_limit = (lower_limit + upper_limit)/2
lower_limit += delta
else:
throw Exception
i += 1

# Decrypted ciphertext
print long_to_bytes(upper_limit)
flag = upper_limit * N / denominator
print long_to_bytes(flag)
```

Now try understanding the conditions 3 and 4 using the above script:
Expand All @@ -119,7 +125,7 @@ Now try understanding the conditions 3 and 4 using the above script:

It is somewhat similar to binary search algorithm, because our attack is doing the same (lowering the range of `m` until we get `m`), hence the complexity of this attack is **log<sub>2</sub>n**.

Note that the above script messes up the last byte of the plaintext. I am trying to find out why, and will update the README as soon as I get it.
Note that we keep track of the numerators and denominators separately, or else we end up with a messed up last byte from truncating along the way.

I have written a script illustrating a server vulnerable to this attack, which you can find here: [encrypt.py](encrypt.py). You can also find the script I wrote to attack the above vulnerable service, which you can find here: [exploit.py](exploit.py)

Expand Down
18 changes: 11 additions & 7 deletions RSA-encryption/Attack-LSBit-Oracle/exploit.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,25 @@ def _decrypt(ciphertext):
print "\n\n"

e = 65537
upper_limit = N
upper_limit = 1
lower_limit = 0
denominator = 1

flag = ""
i = 1
while i <= 1034:
for i in range(1, N.bit_length()+1):
chosen_ct = long_to_bytes((bytes_to_long(flag_enc)*pow(2**i, e, N)) % N)
output = _decrypt(chosen_ct)
delta = upper_limit - lower_limit
upper_limit *= 2
lower_limit *= 2
denominator *= 2
if ord(output[-1]) == 0:
upper_limit = (upper_limit + lower_limit)/2
upper_limit -= delta
elif ord(output[-1]) == 1:
lower_limit = (lower_limit + upper_limit)/2
lower_limit += delta
else:
break
print "Unsuccessfull"
i += 1

print "Flag : ", long_to_bytes(lower_limit)
flag = N * lower_limit / denominator
print "Flag : ", long_to_bytes(flag)
27 changes: 13 additions & 14 deletions RSA-encryption/Attack-LSBit-Oracle/lsbitoracle.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@
from Crypto.PublicKey import RSA


def lsbitoracle(flag_enc, _decrypt, e, N, upper_limit, lower_limit):
def lsbitoracle(flag_enc, _decrypt, e, N):
"""
Reference: https://crypto.stackexchange.com/questions/11053/rsa-least-significant-bit-oracle-attack

Function implementing LSBit Oracle Attack

*Warning*: Function does not return the last byte of the final plaintext

:parameters:
flag_enc : str
Ciphertext you want to decrypt
Expand All @@ -19,26 +17,27 @@ def lsbitoracle(flag_enc, _decrypt, e, N, upper_limit, lower_limit):
Public Key exponent
N : long
Public Key Modulus
upper_limit: long
Maximum value of corresponding plaintext of flag_enc
lower_limit: long
Minimum value of corresponding plaintext of flag_enc

Since the attack messes up with the last byte of the plaintext, lsbitoracle
function returns only flag[:-1]. It returns -1 in case of any Exception
Returns -1 in case of any Exception
"""
flag = ""
i = 1
while lower_limit < upper_limit:
lower_limit = 0
upper_limit = 1
denominator = 1
for i in range(1, N.bit_length()+1):
chosen_ct = long_to_bytes((bytes_to_long(flag_enc)*pow(2**i, e, N)) % N)
output = _decrypt(chosen_ct)
delta = upper_limit - lower_limit
upper_limit *= 2
lower_limit *= 2
denominator *= 2
if ord(output[-1]) == 0:
upper_limit = (upper_limit + lower_limit)/2
upper_limit -= delta
elif ord(output[-1]) == 1:
lower_limit = (lower_limit + upper_limit)/2
lower_limit += delta
else:
return -1
i += 1
# clearing the last byte from the flag
flag = lower_limit & (~0xff)
flag = N * lower_limit / denominator
return long_to_bytes(flag)