Solve challenge 47 in Python
I will also implement it in Rust but prototyping is just easier and faster in Python.
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
|
import sys
|
||||||
from math import log, ceil, floor
|
from math import log, ceil, floor
|
||||||
|
from fractions import Fraction
|
||||||
|
|
||||||
|
|
||||||
e = 3
|
e = 3
|
||||||
@@ -22,6 +24,7 @@ def add_padding(m: int, k: int) -> int:
|
|||||||
r.append(0xff)
|
r.append(0xff)
|
||||||
r.append(0x0)
|
r.append(0x0)
|
||||||
r += m.to_bytes(from_len, 'big')
|
r += m.to_bytes(from_len, 'big')
|
||||||
|
assert(len(r) == k)
|
||||||
r = int.from_bytes(r, byteorder='big')
|
r = int.from_bytes(r, byteorder='big')
|
||||||
return r
|
return r
|
||||||
|
|
||||||
@@ -52,7 +55,6 @@ def decrypt(c: int) -> int:
|
|||||||
|
|
||||||
def test():
|
def test():
|
||||||
m = int.from_bytes(b"kick it, CC", byteorder='big')
|
m = int.from_bytes(b"kick it, CC", byteorder='big')
|
||||||
m = 129852745126415640677073731
|
|
||||||
assert(m == 129852745126415640677073731)
|
assert(m == 129852745126415640677073731)
|
||||||
|
|
||||||
k = bytes_needed(n)
|
k = bytes_needed(n)
|
||||||
@@ -74,6 +76,7 @@ def main():
|
|||||||
|
|
||||||
k = bytes_needed(n)
|
k = bytes_needed(n)
|
||||||
m = int.from_bytes(b"kick it, CC", byteorder='big')
|
m = int.from_bytes(b"kick it, CC", byteorder='big')
|
||||||
|
m_orig = m
|
||||||
c = encrypt(add_padding(m, k))
|
c = encrypt(add_padding(m, k))
|
||||||
assert(m == remove_padding(decrypt(c), k))
|
assert(m == remove_padding(decrypt(c), k))
|
||||||
|
|
||||||
@@ -86,7 +89,8 @@ def main():
|
|||||||
|
|
||||||
# Step 2: Searching for PKCS conforming messages.
|
# Step 2: Searching for PKCS conforming messages.
|
||||||
while True:
|
while True:
|
||||||
print(f"{i=}\n{s=}\n{m=}")
|
# print("========")
|
||||||
|
# print(f"{i=} {s=} {m=}")
|
||||||
if i == 1:
|
if i == 1:
|
||||||
# Step 2.a: Starting the search.
|
# Step 2.a: Starting the search.
|
||||||
s = ceil(n / (3 * B))
|
s = ceil(n / (3 * B))
|
||||||
@@ -99,12 +103,13 @@ def main():
|
|||||||
# Step 2.c: Searching with one interval left.
|
# Step 2.c: Searching with one interval left.
|
||||||
a, b = m[0]
|
a, b = m[0]
|
||||||
found = False
|
found = False
|
||||||
r = ceil(2 * ((b * s - 2 * B) / n))
|
r = ceil(Fraction(2 * (b * s - 2 * B), n))
|
||||||
while not found:
|
while not found:
|
||||||
s_lower = ceil((2 * B + r * n) / b)
|
s_lower = Fraction(2 * B + r * n, b)
|
||||||
s_upper = ceil((3 * B + r * n) / a)
|
s_upper = Fraction(3 * B + r * n, a)
|
||||||
assert(s_lower < s_upper + 1)
|
s_lower_ceil = ceil(s_lower)
|
||||||
for s in range(s_lower, s_upper):
|
s_upper_ceil = ceil(s_upper)
|
||||||
|
for s in range(s_lower_ceil, s_upper_ceil):
|
||||||
if oracle(c * pow(s, e, n) % n):
|
if oracle(c * pow(s, e, n) % n):
|
||||||
found = True
|
found = True
|
||||||
break
|
break
|
||||||
@@ -115,25 +120,32 @@ def main():
|
|||||||
# Step 3: Narrowing the set of solutions.
|
# Step 3: Narrowing the set of solutions.
|
||||||
m_new = []
|
m_new = []
|
||||||
for (a, b) in m:
|
for (a, b) in m:
|
||||||
lower = ceil((a * s - 3 * B + 1) / n)
|
lower = Fraction((a * s - 3 * B + 1), n)
|
||||||
upper = ceil((b * s - 2 * B) / n)
|
upper = Fraction((b * s - 2 * B), n)
|
||||||
for r in range(lower, upper):
|
lower_ceil = ceil(lower)
|
||||||
a_new = max(a, ceil((2 * B + r * n) / s))
|
upper_ceil = ceil(upper)
|
||||||
b_new = min(b, floor((3 * B - 1 + r * n) / s))
|
|
||||||
|
# If upper is an integer we have to increment it to include it into
|
||||||
|
# the range.
|
||||||
|
if upper == upper_ceil:
|
||||||
|
upper_ceil += 1
|
||||||
|
|
||||||
|
for r in range(lower_ceil, upper_ceil):
|
||||||
|
a_new = max(a, ceil(Fraction(2 * B + r * n, s)))
|
||||||
|
b_new = min(b, floor(Fraction(3 * B - 1 + r * n, s)))
|
||||||
m_new.append((a_new, b_new))
|
m_new.append((a_new, b_new))
|
||||||
m = m_new
|
m = m_new
|
||||||
|
|
||||||
# Step 4: Computing the solutions.
|
# Step 4: Computing the solutions.
|
||||||
if len(m) == 1 and m[0][0] == m[0][1]:
|
if len(m) == 1 and m[0][0] == m[0][1]:
|
||||||
m = a * pow(s0, -1, n) % n
|
m = m[0][0]
|
||||||
break
|
break
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
|
||||||
print(m)
|
assert(m == 5300541194335152988749892502228755547482451611528547105226896651010982723)
|
||||||
|
m = remove_padding(m, k)
|
||||||
|
assert(m == m_orig)
|
||||||
|
print("[okay] Challenge 47: Bleichenbacher's PKCS 1.5 Padding Oracle (Simple Case)")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user