def __init__(self, prime, email, password): """ Initializes the class with a provided NIST prime, email, and password. Computes salt, v so that the password does not need to be saved. Args: prime (int): The NIST prime used by both client and server email (bytestring): The email for the user password (bytestring): The password for the user """ # Setting the password list small for testing but really, you would # need to sit here and do a long dictionary attack. I'm not wasting # my time. self.password_list = [ b'password', b'password1', b'imready', b'ready', b'krustykrab', b'1234567890', b'invalid' ] self.N = prime self.g = 2 self.k = 3 self.I = email self.salt = os.urandom(8) xH = sha256(self.salt + password).digest() if DEBUG: print('SERVER: salt: ' + str(c1.asciitohex(self.salt))) print('SERVER: xH: ' + str(c1.asciitohex(xH))) x = int.from_bytes(xH, byteorder='big') self.v = pow(self.g, x, self.N)
def login(self, email, password, A): """ Attempts to log into the SRP server with the given credentials. Args: email: The email of the user password: The password of the user A: A malicious A value. Must be 0, or multiple of N Returns: True if successful login """ # Send I, A out = queue.Queue() inp = queue.Queue() self.server.authenticate(email, A, out, inp) # S->C salt, B salt, B = inp.get() if DEBUG: print('CLIENT: salt: ' + str(c1.asciitohex(salt))) print('CLIENT: B: ' + str(B)) if A % self.N != 0: raise ValueError('Not a valid malicious A value') K = sha256(int_to_bytes(0)).digest() hmac = hmac_sha256(salt, K) if DEBUG: print('CLIENT: K: ' + str(c1.asciitohex(K))) print('CLIENT: HMAC: ' + str(c1.asciitohex(hmac))) out.put(hmac) auth = inp.get() return auth
def crack_next_byte(known, file): """ Gets the next byte of the HMAC. Args: known: The known bytes so far file: The name of the file Returns: The next byte of the HMAC """ expected_delay = DELAY * len(known) expected_delay += DELAY * 0.75 for i in range(5): time_request(file, c1.asciitohex(b'abnsbsuoabna')) for i in range(256): mac = known + bytes([i]) + bytes([0] * (19 - len(known))) t = time_request(file, c1.asciitohex(mac)) if DEBUG: __print_time_val(i, t) if t >= expected_delay: return bytes([i]) raise Exception('unexpected')
def test_dsa(self): p = b'a8f9cd201e5e35d892f85f80e4db2599a5676a3b' p += b'1d4f190330ed3256b26d0e80a0e49a8fffaaad2' p += b'a24f472d2573241d4d6d6c7480c80b4c67bb447' p += b'9c15ada7ea8424d2502fa01472e760241713dab' p += b'025ae1b02e1703a1435f62ddf4ee4c1b664066e' p += b'b22f2e3bf28bb70a2a76e4fd5ebe2d1229681b5' p += b'b06439ac9c7e9d8bde283' p = number.bytes_to_long(c1.hextoascii(p)) q = b'f85f0f83ac4df7ea0cdf8f469bfeeaea14156495' q = number.bytes_to_long(c1.hextoascii(q)) g = b'2b3152ff6c62f14622b8f48e59f8af46883b38e7' g += b'9b8c74deeae9df131f8b856e3ad6c8455dab87c' g += b'c0da8ac973417ce4f7878557d6cdf40b35b4a0c' g += b'a3eb310c6a95d68ce284ad4e25ea28591611ee0' g += b'8b8444bd64b25f3f7c572410ddfb39cc728b9c9' g += b'36f85f419129869929cdb909a6a3a99bbe08921' g += b'6368171bd0ba81de4fe33' g = number.bytes_to_long(c1.hextoascii(g)) msg = b'3b46736d559bd4e0c2c1b2553a33ad3c6cf23c' msg += b'ac998d3d0c0e8fa4b19bca06f2f386db2dcff' msg += b'9dca4f40ad8f561ffc308b46c5f31a7735b5f' msg += b'a7e0f9e6cb512e63d7eea05538d66a75cd0d4' msg += b'234b5ccf6c1715ccaaf9cdc0a2228135f716e' msg += b'e9bdee7fc13ec27a03a6d11c5c5b3685f5190' msg += b'0b1337153bc6c4e8f52920c33fa37f4e7' msg = c1.hextoascii(msg) x = b'c53eae6d45323164c7d07af5715703744a63fc3a' x = number.bytes_to_long(c1.hextoascii(x)) y = b'313fd9ebca91574e1c2eebe1517c57e0c21b0209' y += b'872140c5328761bbb2450b33f1b18b409ce9ab7' y += b'c4cd8fda3391e8e34868357c199e16a6b2eba06' y += b'd6749def791d79e95d3a4d09b24c392ad89dbf1' y += b'00995ae19c01062056bb14bce005e8731efde17' y += b'5f95b975089bdcdaea562b32786d96f5a31aedf' y += b'75364008ad4fffebb970b' y = number.bytes_to_long(c1.hextoascii(y)) params = p, q, g pub = y priv = x k = b'98cbcc4969d845e2461b5f66383dd503712bbcfa' k = number.bytes_to_long(c1.hextoascii(k)) r, s, k = dsa_sign_with_k(msg, params, priv, k) sig = r, s r = c1.asciitohex(number.long_to_bytes(r)) s = c1.asciitohex(number.long_to_bytes(s)) self.assertEqual(r, b'50ed0e810e3f1c7cb6ac62332058448bd8b284c0'.upper()) self.assertEqual(s, b'c6aded17216b46b7e4b6f2a97c1ad7cc3da83fde'.upper()) self.assertTrue(dsa_verify(msg, sig, params, pub)) self.assertEqual(get_x_from_k(msg, sig, params, k), x)
def __auth(self, email, A, inp, output): self.salt = b'0' * 8 b = 1 B = 2 # x needs to not be canceled out by bad math u = 1 # these two values make it S = g**(a+x) % N output.put([self.salt, B, u]) # Generate S = (A * v**u)**b % N, K if DEBUG: print('SERVER: S: ' + str(S)) print('SERVER: K: ' + str(c1.asciitohex(K))) print('SERVER: hmac: ' + str(c1.asciitohex(hmac))) client_hmac = inp.get() self.__dictionary_attack(client_hmac, self.salt, A, u) output.put(False)
def test_challenge_5(self): pt = b'Burning \'em, if you ain\'t quick and nimble\n' pt += b'I go crazy when I hear a cymbal' ct = repeating_key_xor(pt, b'ICE') ans = b'0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272' ans += b'a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f' self.assertEqual(c1.asciitohex(ct), ans.upper())
def pre_process(self): """ Preproccesses the messages by padding appropriately. """ ## The message, M, shall be padded before hash computation ## begins. The purpose of this padding is to ensure that ## the padded message is a multiple of 512 bits. ## Append a 1 bit to the end of the message, followed by k ## zero bits, where k is the smallest, non-negative solution ## to the equation ## l + 1 + k === 448 mod 512 message_bit_len = self.l * 8 # NOTE: it took me FOREVER to realize that the l passed in # for c29 is used only as a the postfix, and the rest uses # len(message) message_len = len(self.message) # Instead of calculating the number of zeros, we'll create # a buffer of zeros and fill it at the start and end num_blocks = math.ceil((message_len + 9) / 64) new_len = int(num_blocks * 64) new_msg = bytearray(new_len) new_msg[0:message_len+1] = self.message + bytes([0x80]) postfix = struct.pack(b'>Q', message_bit_len) new_msg[-len(postfix):] = postfix self.l = new_len self.message = bytes(new_msg) ## After the message has been padded, it must be parsed into N ## m-bit blocks before the hash computation can begin. ## For SHA-1, the padded message is parsed into N 512-bit blocks. self.n = self.l // 64 if DEBUG: print('State after preprocessing:') print('MSG: ' + c1.asciitohex(self.message)) print('LEN: ' + str(self.l))
def test_challenge_43(self): message = b'For those that envy a MC it can be hazardous to your health\n' message += b'So be friendly, a matter of life and death, just like a etch-a-sketch\n' self.assertEqual(c1.asciitohex(sha1(message).digest()), b'd2d0714f014a9784047eaeccf956520045c45265'.upper()) k = random.randrange(1, 2**16) r = 548099063082341131477253921760299949438196259240 s = 857042759984254168557880549501802188789837994940 sig = r, s k, x = brute_force_k(message, sig, self.params, self.pub) xb = hex(x)[2:].encode('ascii') r2, s2, k2 = dsa_sign_with_k(message, self.params, x, k) actual = c1.asciitohex(sha1(xb).digest()) self.assertEqual(actual, b'0954edd5e0afe5542a4adf012611a91912a3ec16'.upper()) self.assertEqual(r2, r) self.assertEqual(s2, s)
def test_challenge_44(self): msgs = get_all_msgs() k, x = find_repeated_k(msgs, self.params) xb = hex(x)[2:].encode('ascii') xh = c1.asciitohex(sha1(xb).digest()) self.assertEqual(xh, b'ca8f6f7c66fa362d40760d135b763eb8527d3d52'.upper()) return
def timing_attack(file): """ Executes the timing attack. Args: file: The name of the file to attack Returns: The cracked HMAC value. """ known = b'' for i in range(20): known += crack_next_byte(known, file) if DEBUG: print(c1.asciitohex(known)) return c1.asciitohex(known)
def __auth(self, email, A, inp, output): # Send salt, B b = int.from_bytes(os.urandom(8), byteorder='big') B = pow(self.g, b, self.N) if DEBUG: print('SERVER: B: ' + str(B)) u = int.from_bytes(os.urandom(16), byteorder='big') output.put([self.salt, B, u]) # Generate S = (A * v**u)**b % N, K S = pow(A * pow(self.v, u, self.N), b, self.N) K = sha256(int_to_bytes(S)).digest() hmac = hmac_sha256(self.salt, K) if DEBUG: print('SERVER: S: ' + str(S)) print('SERVER: K: ' + str(c1.asciitohex(K))) print('SERVER: hmac: ' + str(c1.asciitohex(hmac))) client_hmac = inp.get() output.put(hmac == client_hmac)
def __init__(self, prime, email, password): """ Initializes the class with a provided NIST prime, email, and password. Computes salt, v so that the password does not need to be saved. Args: prime (int): The NIST prime used by both client and server email (bytestring): The email for the user password (bytestring): The password for the user """ self.N = prime self.g = 2 self.k = 3 self.I = email self.salt = os.urandom(8) xH = sha256(self.salt + password).digest() if DEBUG: print('SERVER: salt: ' + str(c1.asciitohex(self.salt))) print('SERVER: xH: ' + str(c1.asciitohex(xH))) x = int.from_bytes(xH, byteorder='big') self.v = pow(self.g, x, self.N)
def login(self, email, password): """ Attempts to log into the SRP server with the given credentials. Args: email: The email of the user password: The password of the user Returns: True if successful login """ a = int.from_bytes(os.urandom(8), byteorder='big') A = pow(self.g, a, self.N) # Send I, A out = queue.Queue() inp = queue.Queue() self.server.authenticate(email, A, out, inp) # S->C salt, B salt, B = inp.get() if DEBUG: print('CLIENT: salt: ' + str(c1.asciitohex(salt))) print('CLIENT: B: ' + str(B)) # Compute uH uH = sha256(int_to_bytes(A) + int_to_bytes(B)).digest() u = int.from_bytes(uH, byteorder='big') # Generate xH, K, S= (B - k * g**x)**(a + u*x) % N xH = sha256(salt + password).digest() x = int.from_bytes(xH, byteorder='big') S = pow(B - self.k * pow(self.g, x, self.N), (a + u*x), self.N) K = sha256(int_to_bytes(S)).digest() hmac = hmac_sha256(salt, K) if DEBUG: print('CLIENT: uH: ' + str(c1.asciitohex(uH))) print('CLIENT: xH: ' + str(c1.asciitohex(xH))) print('CLIENT: S: ' + str(S)) print('CLIENT: K: ' + str(c1.asciitohex(K))) print('CLIENT: HMAC: ' + str(c1.asciitohex(hmac))) out.put(hmac) auth = inp.get() return auth
def get_state(message): """ Gets the SHA-1 state array from the message Args: message: The message to extract the state from Returns: List containing the SHA-1 state for injection. """ h = c1.asciitohex(c28.mac_sha1(message)) new_h = [int(h[i:i + 8], 16) for i in range(0, len(h), 8)] return new_h
def hamming_dist(str1, str2): """ Calculates the Hamming distance between two bytestrings. Args: str1: The first bytestring str2: The second bytestring Returns: The hamming distance between the two given strings """ # XOR each character, convert to binary representation, # and count the 1's. This gives you the differing bits. xord = c1.asciitohex(c2.xorstrs(str1, str2)) return bin(int(xord, base=16)).count('1')
def insecure_compare(str1, str2): """ Compares two strings for equality with an artificial timing leak. Args: str1: The first string str2: The second string Returns: True if the strings are equal. """ if DEBUG: print(c1.asciitohex(str1)) print(c1.asciitohex(str2)) result = True if len(str1) != len(str2): return False for i in range(len(str1)): result &= str1[i] == str2[i] if result: time.sleep(DELAY) else: return result return result
def digest(self): """ Produces the message digest. Returns: A bytestring containing the message digest. """ # Process each 16-word block for i in range(self.n): chunk = self.message[i * 64:(i + 1) * 64] if DEBUG: print('Chunk: ' + str(c1.asciitohex(chunk))) # Copy block into X X = [0] * 16 for j in range(16): val = chunk[j * 4:(j + 1) * 4] X[j] = struct.unpack("<I", val)[0] # Save register values AA, BB, CC, DD = self.h # Round 1 self.__round1(X) if DEBUG: print('After round 1: ' + str(map(hex, self.h))) self.__round2(X) if DEBUG: print("After round 2: " + str(map(hex, self.h))) self.__round3(X) if DEBUG: print("After round 3: " + str(map(hex, self.h))) vals = [AA, BB, CC, DD] self.h = list(map(sum32, zip(self.h, vals))) if DEBUG: print('After first block: ' + str(map(hex, self.h))) # Return the final hash value as bytes result = b''.join(list(map(lambda x: struct.pack("<I", x), self.h))) return result
def pkcs15_verify_bad(message, signature, pub): """ Bad PKCS1.5 verify algorithm that uses regular expression check Args: message: The message signature: The message signature pub: The RSA public key Returns: True if signature validates """ m = c39.rsa_decrypt(signature, pub) m = c1.asciitohex(m) regexp = b'3021300906052B0E03021A05000414' r = re.compile(regexp) m = r.split(m) if len(m) != 2: return False h = c1.hextoascii(m[1])[:20] return h == sha1(message).digest()
def crack_next_byte(known, file): """ Gets the next byte of the HMAC by sending every byte 5 times and taking an average. Args: known: The known bytes so far file: The name of the file Returns: The next byte of the HMAC """ avgs = dict().fromkeys(range(256), 0) # To get this just right, we'll do multiple attempts for each byte # and take the average. If the average is within range, we take it. for a in range(5): for i in range(256): mac = known + bytes([i]) + bytes([0] * (19 - len(known))) t = time_request(file, c1.asciitohex(mac)) avgs.update({i : avgs.get(i) + t}) maxAvg = -1 maxI = -1 for i in range(256): avgs.update({i : avgs.get(i) / 5.0}) if DEBUG: __print_time_val(i, t) # Instead of breaking when we find the expected-delay, # we're just going to take the one with the highest avergae. if avgs.get(i) > maxAvg: maxAvg = avgs.get(i) maxI = i return bytes([maxI])
def test4(self): result = MD4(b'A' * 1000000).digest() result = c1.asciitohex(result) expected = b'a13f9ee75c400d8e6837bd724fb92d66'.upper() self.assertEqual(result, expected)
def test4(self): result = MYSHA1(b'a' * 1000000).digest() result = c1.asciitohex(result) expected = b'34AA973CD4C4DAA4F61EEB2BDBAD27316534016F' self.assertEqual(result, expected)
def test3(self): msg = b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" result = MYSHA1(msg).digest() result = c1.asciitohex(result) expected = b'A49B2446A02C645BF419F995B67091253A04A259' self.assertEqual(result, expected)
def test2(self): msg = b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" result = MYSHA1(msg).digest() result = c1.asciitohex(result) expected = b'84983E441C3BD26EBAAE4AA1F95129E5E54670F1' self.assertEqual(result, expected)
def test1(self): result = c1.asciitohex(MYSHA1(b'abc').digest()) expected = b'a9993e364706816aba3e25717850c26c9cd0d89d'.upper() self.assertEqual(result, expected)
def test3(self): msg = b"" result = MD4(msg).digest() result = c1.asciitohex(result) expected = b'31d6cfe0d16ae931b73c59d7e0c089c0'.upper() self.assertEqual(result, expected)
def test2(self): msg = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" result = MD4(msg).digest() result = c1.asciitohex(result) expected = b'043f8582f241db351ce627e153e7f0e4'.upper() self.assertEqual(result, expected)
def test_challenge_2(self): actual = c1.asciitohex(xorstrs(self.str1, self.str2)) expected = b'746865206b696420646f6e277420706c6179'.upper() self.assertEqual(actual, expected)
def test1(self): result = c1.asciitohex(MD4(b'abc').digest()) expected = b'a448017aaf21d8525fc10ae87aa6729d'.upper() self.assertEqual(result, expected)