class RSA_Signature_PKCS_1_5: def __init__(self, s, e=3): self.key = RSA(s, e=e) self.key.generate_keys() self.key_length_bytes = s / 8 def sign(self, message): h = hashlib.sha1(message).hexdigest() to_sign = '0001' + 'ff' * (self.key_length_bytes - 38) + '00' + ASN1_SHA1 + h to_sign_integer = rsa_string_to_integer(to_sign.decode('hex')) signature = self.key.decrypt(to_sign_integer, encode=False) return signature def insecure_verify(self, signature, message): m = self.key.encrypt(signature, encode=False) m = rsa_integer_to_string(m).encode('hex') m = '00' * (self.key_length_bytes - len(m) / 2) + m h = hashlib.sha1(message).hexdigest() regex = '0001(ff)*00' + ASN1_SHA1 + h if re.search(regex, m) is not None: return True else: return False
def __init__(self, s, e=65537): self.key = RSA(s, e=e) self.key.generate_keys() # replace RSA params self.key.p = getPrime(128) self.key.q = getPrime(128) self.key.N = self.key.p * self.key.q self.key.et = (self.key.p - 1) * (self.key.q - 1) self.key.d = modinv(self.key.e, self.key.et) assert self.key.d is not None, 'modinv failed' self.key.public_key = (self.key.N, self.key.e) self.key.private_key = (self.key.N, self.key.d) #self.key_length_bytes = s / 8 self.key_length_bytes = (len(bin(self.key.N)[2:-1]) + 7) / 8
def __init__(self, s, e=3): self.key = RSA(s, e=e) self.key.generate_keys() self.key_length_bytes = s / 8
class RSA_PKCS_1_5: def __init__(self, s, e=65537): self.key = RSA(s, e=e) self.key.generate_keys() # replace RSA params self.key.p = getPrime(128) self.key.q = getPrime(128) self.key.N = self.key.p * self.key.q self.key.et = (self.key.p - 1) * (self.key.q - 1) self.key.d = modinv(self.key.e, self.key.et) assert self.key.d is not None, 'modinv failed' self.key.public_key = (self.key.N, self.key.e) self.key.private_key = (self.key.N, self.key.d) #self.key_length_bytes = s / 8 self.key_length_bytes = (len(bin(self.key.N)[2:-1]) + 7) / 8 def pad_pkcs(self, message): padding_string_length = self.key_length_bytes - 3 - len(message) padding_string = crypto_non_zero_random_bytes(padding_string_length) padded = bytearray([0, 2]) + padding_string + bytearray( [0]) + bytearray(message) assert len(padded) == self.key_length_bytes, 'padding failed' return padded def unpad_pkcd(self, message): assert len(message) == self.key_length_bytes, 'cannot begin unpadding' #print list(message) if message[0] != 0 or message[1] != 2: raise Exception('invalid pkcs#1 padding') i = 2 while message[i] != 0: i += 1 return message[i + 1:] def encrypt(self, message): padded = self.pad_pkcs(message) i = bytes_to_integer(padded) return self.key.encrypt(i, encode=False) def decrypt(self, ciphertext): m_int = self.key.decrypt(ciphertext, encode=False) m = integer_to_bytes(m_int, self.key_length_bytes) unpadded = self.unpad_pkcd(m) return unpadded def encrypt_no_pkcs(self, message): i = bytes_to_integer(message) return self.key.encrypt(i, encode=False) def decrypt_no_pkcs(self, ciphertext): m_int = self.key.decrypt(ciphertext, encode=False) m = integer_to_bytes(m_int, self.key_length_bytes) return m
def encrypt_broadcast_message(message): rsa = RSA(2048, e=3) rsa.generate_keys() return rsa.encrypt(message), rsa.N
import sys sys.setrecursionlimit(1500) sys.path.insert(0, '../set_1_basics') sys.path.insert(0, '../set_5_diffie_hellman_friends') from utils import random_integer from implement_rsa import RSA, modinv, rsa_string_to_integer, rsa_integer_to_string ORACLE_KEY = RSA(2048, e=3) ORACLE_KEY.generate_keys() ORACLE_HISTORY = [] # prevent submission of the same ciphertext twice def unpadded_message_oracle(ciphertext): if ciphertext in ORACLE_HISTORY: raise Exception('i have already seen this ciphertext') message = ORACLE_KEY.decrypt(ciphertext) ORACLE_HISTORY.append(ciphertext) return message def exploit_oracle(ciphertext): n = ORACLE_KEY.N e = ORACLE_KEY.e s = random_integer(2, n-1) crafted_c = (pow(s, e, n) * ciphertext) % n crafted_p = unpadded_message_oracle(crafted_c) crafted_p = rsa_string_to_integer(crafted_p)
import sys sys.setrecursionlimit(1500) sys.path.insert(0, '../set_1_basics') sys.path.insert(0, '../set_5_diffie_hellman_friends') from utils import random_integer, base64_to_bytearray from implement_rsa import RSA, modinv, rsa_string_to_integer, rsa_integer_to_string from decimal import * from math import ceil, floor, log ORACLE_KEY = RSA(1024, e=65537) ORACLE_KEY.generate_keys() def parity_oracle(ciphertext): plaintext_int = ORACLE_KEY.decrypt(ciphertext, encode=False) return plaintext_int % 2 == 0 def attack_parity_oracle(ciphertext, e, n): lb = Decimal(0) ub = Decimal(n) k = int(ceil(log(n, 2))) # n. of iterations getcontext().prec = k # allows for 'precise enough' floats c = ciphertext enctwo = pow(2, e, n) for i in xrange(1, k+1): c = (c * enctwo) % n nb = (lb + ub) / 2 if parity_oracle(c):