def RSAVerifyPKCS15(pub_key, msg, sig): verify_against = (GroupOp.mod_exp(sig, pub_key[1], pub_key[0])).to_bytes( pub_key[0].bit_length() // 8, byteorder="big") begin_correct = verify_against.startswith(b"\x00\x01") # strip all of the ff's ff_strip = verify_against[2:] while ff_strip[0] == 0xff: ff_strip = ff_strip[1:] correct0 = ff_strip.startswith(b"\x00") hash_id_length = SHA1_ASNBitLen // 8 hash_identifier = int.from_bytes(ff_strip[1:hash_id_length + 1], byteorder="big") if hash_identifier == SHA1_ASN: hash_obj = sha1.SHA1() elif hash_identifier == SHA256_ASN: hash_obj = sha256.SHA256() else: raise ValueError("Was unable to identify hash alg") hash_obj.Update(msg) hashed_msg = hash_obj.Sum() hash_from_sig = ff_strip[hash_id_length + 1:hash_id_length + 1 + SHA1Len] check_val = (hash_from_sig == hashed_msg) return check_val and correct0 and begin_correct
def generate_shared_key(secret_val, public_val_from_other, prime): print("Secret value is {}, shared value is {}".format( secret_val, public_val_from_other)) shared_key = GroupOp.mod_exp(public_val_from_other, secret_val, prime) print(shared_key) assert shared_key < prime hash_feed = SHA1.SHA1() hash_feed.Update( shared_key.to_bytes(shared_key.bit_length() + 7 // 8, byteorder='big')) return hash_feed.Sum()
def RSAAttackerSign(pub_key, msg): hash_obj = sha1.SHA1() hash_obj.Update(msg) res = int.from_bytes(hash_obj.Sum(), byteorder="big") mod_byte_len = pub_key[0].bit_length() // 8 formatted_msg = int("0x" + "0001ffff00" + hex(SHA1_ASN)[2:] + hex(res)[2:], 16) << ((mod_byte_len - 5 - (SHA1_ASNBitLen // 8) - SHA1Len) * BYTE_SIZE) # take the cube root and round up fake_sig = find_cube_root_range(formatted_msg)[1] return fake_sig
def insecureSign(params, private_key, message): k = random.randrange(1, params["q"]) r = GroupOp.mod_exp(params["g"], k, params["p"]) % params["q"] init_hash = sha1.SHA1() init_hash.Update(message) hashed_msg_val = int.from_bytes(init_hash.Sum(), byteorder="big") % params["q"] k_inv = GroupOp.find_inverse(k, params["q"]) s = (k_inv * (hashed_msg_val + private_key * r)) % params["q"] return (r, s)
def EncodeMessage(msg, modulus): hash_sha = sha1.SHA1() hash_sha.Update(msg) msg_hash = hash_sha.Sum() hash_as_int = int.from_bytes(msg_hash, byteorder="big") mod_size = modulus.bit_length() // 8 # 00 01 ff ff ff ... 00 ASN.1 HASH numFBytes = mod_size - 3 - (SHA1_ASNBitLen // 8) - SHA1Len hash_and_length = SHA1_ASNBitLen + (SHA1Len * BYTE_SIZE) # extra byte left shift by 8 for 00 encoded_msg = int("0x01" + (numFBytes * "ff"), 16) << (BYTE_SIZE + hash_and_length) encoded_msg |= (SHA1_ASN << (SHA1Len * BYTE_SIZE)) encoded_msg |= hash_as_int return encoded_msg
def AttackerWithKnownSubKeyK(params, public_key, k, msg, msg_sig, msg_hash=None): recover_x = (msg_sig[1] * k) % params["q"] if not msg_hash: hash_obj = sha1.SHA1() hash_obj.Update(msg) msg_as_int = int.from_bytes(hash_obj.Sum(), byteorder="big") else: msg_as_int = msg_hash recover_x = (recover_x - (msg_as_int % params["q"])) % params["q"] recover_x = recover_x * (GroupOp.find_inverse(msg_sig[0], params["q"])) return recover_x % params["q"]
def DSASign(params, private_key, message, print_k=False, k=0): r = 0 s = 0 while r == 0 and s == 0: if k == 0: k = random.randrange(1, params["q"]) if print_k: print("K value is {:x}".format(k)) r = GroupOp.mod_exp(params["g"], k, params["p"]) % params["q"] if r != 0: init_hash = sha1.SHA1() init_hash.Update(message) hashed_msg_val = int.from_bytes(init_hash.Sum(), byteorder="big") % params["q"] k_inv = GroupOp.find_inverse(k, params["q"]) s = (k_inv * (hashed_msg_val + private_key * r)) % params["q"] return (r, s)
def main(): dictionary = from_file("44.txt") dict1, dict2 = isolate_repeated_k(dictionary) if not dict1: print("Could not run attack :(") else: inv_s_elt = (dict1["s"] - dict2["s"]) % challenge_params["q"] inv_s_elt = GroupOp.find_inverse(inv_s_elt, challenge_params["q"]) exp_k = (dict1["m"] - dict2["m"]) % challenge_params["q"] exp_k = (exp_k * inv_s_elt) % challenge_params["q"] recovered_x = CP43.AttackerWithKnownSubKeyK(challenge_params, challenge_public_key, exp_k, dict1["msg"], (dict1["r"], dict1["s"]), dict1["m"]) key_hash_obj = sha1.SHA1() key_hash_obj.Update(hex(recovered_x)[2:]) key = int.from_bytes(key_hash_obj.Sum(), byteorder="big") print("Recovered key is {:x} with fp {:x}".format(recovered_x, key)) return
def main(): """ parameters = DSAParamGen(42, 256) pub_key, priv_key = DSAKeyGen(parameters) test_msg = b"Lost Lenore" tag = DSASign(parameters, priv_key, test_msg) verify = DSAVerify(parameters, pub_key, test_msg, tag) if verify: print("Passed simple test") else: print("Failed simple test") print("Attempting to use stolen attacker knowledge to recover the private key...") for i in range(3): temp_pub_key, temp_priv_key = DSAKeyGen(parameters, print_x=True) msg = input("Type in message to sign: ").encode("utf-8") tag = DSASign(parameters, temp_priv_key, msg, print_k=True) k_val = input("Give k value in hex: 0x") k = int("0x" + k_val, 16) recovered_private_key = AttackerWithKnownSubKeyK(parameters, temp_pub_key, k, msg, tag) print("Recovered secret key was {:x}".format(recovered_private_key)) """ print("Attempting to crack private key from challenge...") msg_str = "For those that envy a MC it can be hazardous to your health\nSo be friendly, a matter of life and death, just like a etch-a-sketch\n" print("Checking to make sure the message string is correct...") hash_obj = sha1.SHA1() hash_obj.Update(msg_str.encode('utf-8')) result_hash = int.from_bytes(hash_obj.Sum(), byteorder="big") if not hex(result_hash) == "0xd2d0714f014a9784047eaeccf956520045c45265": raise ValueError("Object hash is incorrect") challenge_tag = (548099063082341131477253921760299949438196259240, 857042759984254168557880549501802188789837994940) challenge_params = { "p": 0x800000000000000089e1855218a0e7dac38136ffafa72eda7859f2171e25e65eac698c1702578b07dc2a1076da241c76c62d374d8389ea5aeffd3226a0530cc565f3bf6b50929139ebeac04f48c3c84afb796d61e5a4f9a8fda812ab59494232c7d2b4deb50aa18ee9e132bfa85ac4374d7f9091abc3d015efc871a584471bb1, "q": 0xf4f47f05794b256174bba6e9b396a7707e563c5b, "g": 0x5958c9d3898b224b12672c0b98e06c60df923cb8bc999d119458fef538b8fa4046c8db53039db620c094c9fa077ef389b5322a559946a71903f990f1f7e0e025e2d7f7cf494aff1a0470f5b64c36b625a097f1651fe775323556fe00b3608c887892878480e99041be601a62166ca6894bdd41a7054ec89f756ba9fc95302291 } challenge_public_key = 0x84ad4719d044495496a3201c8ff484feb45b962e7302e56a392aee4abab3e4bdebf2955b4736012f21a08084056b19bcd7fee56048e004e44984e2f411788efdc837a0d2e5abb7b555039fd243ac01f0fb2ed1dec568280ce678e931868d23eb095fde9d3779191b8c0299d6e07bbb283e6633451e535c45513b2d33c99ea17 sha_key_fp = 0x0954edd5e0afe5542a4adf012611a91912a3ec16 for i in range(0, 2**16): selector = GroupOp.mod_exp( challenge_params["g"], i, challenge_params["p"]) % challenge_params["q"] if selector == challenge_tag[0]: print("Calculated a correct r value!") # test k potential_priv_key = AttackerWithKnownSubKeyK( challenge_params, challenge_public_key, i, msg_str, challenge_tag, result_hash) key_obj = sha1.SHA1() string_feed = hex(potential_priv_key)[2:] key_obj.Update(string_feed) key = int.from_bytes(key_obj.Sum(), byteorder="big") print("Key fp is {:x}".format(key)) compute_tag = DSASign(challenge_params, potential_priv_key, msg_str.encode("utf-8"), False, i) if compute_tag[1] == challenge_tag[1]: print("Success! Key is {}".format(potential_priv_key)) return else: print("Failure, correct r but incorrect s") return
def man_in_the_middle(server_pipe, client_pipe): # .... so do I wait for them to try and send things across the wire?? # maybe???? .... have them send a signal? # wait until a signal is sent, check the client pipe and server pipe # for data, figure out the stage of the program and send the appropriate msg prime = 0 # this base will be 0 no matter what because it is p*k for some #integer k mod p sha1_dgst = SHA1.SHA1() zero_key = 0 sha1_dgst.Update( zero_key.to_bytes(zero_key.bit_length() + 7 // 8, byteorder='big')) key = sha1_dgst.Sum() pkt_to_process = None client_seq_num = 0 server_seq_num = 0 while True: print("Man in the middle is waiting to receive from pipe") # this timeout is just designed to be long enough if pkt_to_process is None: print("MitM is attempting to capture network traffic") mitm_packets_captured = sniff(iface=IFACE, timeout=10) print("MitM woke up --- I need a better way to do this") relevant_pkts = [] for pkt in mitm_packets_captured: if TCP in pkt: if pkt[TCP].sport == NEW_PROTOCOL or pkt[ TCP].dport == NEW_PROTOCOL: relevant_pkts.append(pkt) if len(relevant_pkts) != 1: if len(relevant_pkts) > 1: print("There was more than one message captured") else: print("No packets captured, continue loop") continue # TCP segment for pkt in relevant_pkts: pkt.show() pkt_to_process = relevant_pkts[-1] print("Waiting to receive from client/server pipes") ready_list = multiprocessing.connection.wait( [server_pipe, client_pipe]) for pipe in ready_list: port, message = pipe.recv() port = int(port) #mal_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # the sending server gives this to mitm if pipe.fileno() == server_pipe.fileno(): print("Received response from server in MitM") # forward on to client p if prime == 0: raise ValueError("This should have been changed") #mal_socket.connect((HOST, protocol)) if message.startswith(b"ESTABLISH"): print( "Pretending to be server to client from port {} to port {}" .format(NEW_PROTOCOL, port)) to_send_on = "ESTABLISH:{}".format(prime) to_send_on = PackForSending( bytes(to_send_on, encoding='utf-8')) # check different sequence numbers and try to send packet to server # I'm going to try and NOT fake the ack, although I arguably should... # this will just be a PA then if not pkt_to_process: raise ValueError("Something broke :( sad.") print("Last packet captured") pkt_to_process.show() # drop the padding pkt_to_process.getlayer(2).remove_payload() pkt_to_process[TCP].flags = "PA" #pkt_to_process[TCP].options = '' pkt_to_process[IP].id = pkt_to_process[IP].id + 1 pkt_to_process[TCP].seq = server_seq_num pkt_to_process[TCP].ack = client_seq_num pkt_to_process[TCP].dataofs = 5 pkt_to_process[TCP].options = '' #pkt_to_process[TCP].payload = to_send_on pkt_to_process = pkt_to_process / Raw(load=to_send_on) new_chksum = calculateTCPChecksum(pkt_to_process) pkt_to_process[TCP].chksum = new_chksum #ack_data = ack_data / TCP(dport=port, sport=NEW_PROTOCOL, flags="A", seq=mitm_packets_captured[0][TCP].ack, ack=mitm_packets_captured[0][TCP].seq + ) pkt_to_process = sr1(pkt_to_process, iface=IFACE) #pkt_to_process = None print("Packet received was the following: ") pkt_to_process.show() print("Sent packets pretending to be server, mitm") else: # now try to decrypt message recover_msg = decrypt(key, message.decode()) print( "Man in the middle recovered message from server: {}". format(recover_msg)) else: # forward to server p, g, p #print("Received response in MITM, forward to server") if message.startswith(b"ESTABLISH"): print( "Pretending to be client to server from port {} to port {}" .format(port, NEW_PROTOCOL)) inner_params = message[message.find(b"(") + 1:message.find(b")")] inner_params = inner_params.split(b",") print("Established prime") prime = int(inner_params[0]) generator = int(inner_params[1]) print("attempting to connect to server") to_send_on = "ESTABLISH: ({},{},{})".format( prime, generator, prime) to_send_on = bytes(to_send_on, encoding='utf-8') to_send_on = struct.pack("i" + str(len(to_send_on)) + "s", len(to_send_on), to_send_on) new_pkt = None if pkt_to_process[ TCP].sport != NEW_PROTOCOL and pkt_to_process[ TCP].flags == 'A': part_of_pkt = pkt_to_process[TCP] print("From the packet sniffed {}".format( hex(int.from_bytes(part_of_pkt, byteorder='big')))) new_pkt = pkt_to_process if server_seq_num == 0 and client_seq_num == 0: server_seq_num = new_pkt[TCP].ack client_seq_num = new_pkt[TCP].seq print( "Updated server number to {} and client to {}". format(server_seq_num, client_seq_num)) print(new_pkt[TCP]) old_chk_sum = new_pkt[TCP].chksum new_pkt.getlayer(2).remove_payload() new_pkt[TCP].flags = "PA" # increment the ip identification number so the server doesn't think this is a duplicate new_pkt[IP].id = new_pkt[IP].id + 1 #new_pkt[TCP].payload = bytes(to_send_on) new_pkt = new_pkt / Raw(load=to_send_on) # calculate the new tcp checksum newchecksum = calculateTCPChecksum(new_pkt) new_pkt[TCP].chksum = newchecksum else: print("This shouldn't happen! Quitting ") sys.exit(1) new_pkt.show() print("Sending packet") # what should I do here? sendp pkt_to_process = sr1(new_pkt, iface=IFACE) print("Packet received was the following: ") pkt_to_process.show() print("Mitm: Finished sending packets to server as client") else: recover_msg = decrypt(key, message.decode()) print( "Man in the middle recovered message from client: {}". format(recover_msg))