| 55 | return recovered[0:2] == bytes([0, 2]) |
| 56 | |
| 57 | class RSAOracleAttacker: |
| 58 | def __init__(self, public_key, oracle): |
| 59 | self.public_key = public_key |
| 60 | self.oracle = oracle |
| 61 | self.stats = [] |
| 62 | |
| 63 | def _step1_blinding(self, c): |
| 64 | self.c0 = c |
| 65 | |
| 66 | self.B = 2**(self.public_key.key_size-16) |
| 67 | self.s = [1] |
| 68 | self.M = [ [Interval(2*self.B, (3*self.B)-1)] ] |
| 69 | |
| 70 | self.i = 1 |
| 71 | self.n = self.public_key.public_numbers().n |
| 72 | |
| 73 | # RSA Oracle Attack Component, part of class RSAOracleAttacker |
| 74 | def _find_s(self, start_s, s_max=None): |
| 75 | self.stats[-1].search_count += 1 |
| 76 | si = start_s |
| 77 | ci = simple_rsa_encrypt(si, self.public_key) |
| 78 | while not self.oracle((self.c0 * ci) % self.n): |
| 79 | si += 1 |
| 80 | if s_max and (si > s_max): |
| 81 | return None |
| 82 | ci = simple_rsa_encrypt(si, self.public_key) |
| 83 | return si |
| 84 | |
| 85 | # RSA Oracle Attack Component, part of class RSAOracleAttacker |
| 86 | def _step2a_start_the_searching(self): |
| 87 | si = self._find_s(start_s=gmpy2.c_div(self.n, 3*self.B)) |
| 88 | return si |
| 89 | |
| 90 | # RSA Oracle Attack Component, part of class RSAOracleAttacker |
| 91 | def _step2b_searching_with_more_than_one_interval(self): |
| 92 | si = self._find_s(start_s=self.s[-1]+1) |
| 93 | return si |
| 94 | |
| 95 | # RSA Oracle Attack Component, part of class RSAOracleAttacker |
| 96 | def _step2c_searching_with_one_interval_left(self): |
| 97 | a,b = self.M[-1][0] |
| 98 | ri = gmpy2.c_div(2*(b*self.s[-1] - 2*self.B),self.n) |
| 99 | si = None |
| 100 | |
| 101 | while si == None: |
| 102 | si = gmpy2.c_div((2*self.B+ri*self.n),b) |
| 103 | |
| 104 | s_max = gmpy2.c_div((3*self.B+ri*self.n),a) |
| 105 | si = self._find_s(start_s=si, s_max=s_max) |
| 106 | ri += 1 |
| 107 | return si |
| 108 | |
| 109 | # RSA Oracle Attack Component, part of class RSAOracleAttacker |
| 110 | def _step3_narrowing_set_of_solutions(self, si): |
| 111 | new_intervals = set() |
| 112 | for a,b in self.M[-1]: |
| 113 | r_min = gmpy2.c_div((a*si - 3*self.B + 1),self.n) |
| 114 | r_max = gmpy2.f_div((b*si - 2*self.B),self.n) |