def test_output_overlapping_memoryview(self): """Verify result can be stored in overlapping memory""" term1 = memoryview(bytearray(unhexlify(b"ff339a83e5cd4cdf5649"))) expected_xor = unhexlify(b"be72dbc2a48c0d9e1708") result = strxor_c(term1, 65, output=term1) self.assertEqual(result, None) self.assertEqual(term1, expected_xor)
def test_invalid_mac(self): from Cryptodome.Util.strxor import strxor_c cipher = ChaCha20_Poly1305.new(key=self.key_256, nonce=self.nonce_96) ct, mac = cipher.encrypt_and_digest(self.data_128) invalid_mac = strxor_c(mac, 0x01) cipher = ChaCha20_Poly1305.new(key=self.key_256, nonce=self.nonce_96) self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, invalid_mac)
def test_invalid_mac(self): from Cryptodome.Util.strxor import strxor_c cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) ct, mac = cipher.encrypt_and_digest(self.data_128) invalid_mac = strxor_c(mac, 0x01) cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, invalid_mac)
def test_invalid_mac(self): from Cryptodome.Util.strxor import strxor_c cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) ct, mac = cipher.encrypt_and_digest(self.data_128) invalid_mac = strxor_c(mac, 0x01) cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, invalid_mac)
def test_output_memoryview(self): term1 = unhexlify(b"ff339a83e5cd4cdf5649") original_term1 = term1[:] expected_result = unhexlify(b"be72dbc2a48c0d9e1708") output = memoryview(bytearray(len(term1))) result = strxor_c(term1, 65, output=output) self.assertEqual(result, None) self.assertEqual(output, expected_result) self.assertEqual(term1, original_term1)
def runTest(self): key = binascii.a2b_hex(b(self.key)) data = binascii.a2b_hex(b(self.input)) # Strip whitespace from the expected string (which should be in lowercase-hex) expected = b("".join(self.result.split())) h = self.module.new(key, **self.params) h.update(data) out1_bin = h.digest() out1 = binascii.b2a_hex(h.digest()) out2 = h.hexdigest() # Verify that correct MAC does not raise any exception h.hexverify(out1) h.verify(out1_bin) # Verify that incorrect MAC does raise ValueError exception wrong_mac = strxor_c(out1_bin, 255) self.assertRaises(ValueError, h.verify, wrong_mac) self.assertRaises(ValueError, h.hexverify, "4556") h = self.module.new(key, data, **self.params) out3 = h.hexdigest() out4 = binascii.b2a_hex(h.digest()) # Test .copy() h2 = h.copy() h.update(b("blah blah blah")) # Corrupt the original hash object out5 = binascii.b2a_hex(h2.digest( )) # The copied hash object should return the correct result # PY3K: Check that hexdigest() returns str and digest() returns bytes if sys.version_info[0] > 2: self.assertTrue(isinstance(h.digest(), type(b("")))) self.assertTrue(isinstance(h.hexdigest(), type(""))) # PY3K: Check that .hexverify() accepts bytes or str if sys.version_info[0] > 2: h.hexverify(h.hexdigest()) h.hexverify(h.hexdigest().encode('ascii')) # PY3K: hexdigest() should return str, and digest() should return bytes self.assertEqual(expected, out1) if sys.version_info[0] == 2: self.assertEqual(expected, out2) self.assertEqual(expected, out3) else: self.assertEqual(expected.decode(), out2) self.assertEqual(expected.decode(), out3) self.assertEqual(expected, out4) self.assertEqual(expected, out5)
def runTest(self): key = binascii.a2b_hex(b(self.key)) data = binascii.a2b_hex(b(self.input)) # Strip whitespace from the expected string (which should be in lowercase-hex) expected = b("".join(self.result.split())) h = self.module.new(key, **self.params) h.update(data) out1_bin = h.digest() out1 = binascii.b2a_hex(h.digest()) out2 = h.hexdigest() # Verify that correct MAC does not raise any exception h.hexverify(out1) h.verify(out1_bin) # Verify that incorrect MAC does raise ValueError exception wrong_mac = strxor_c(out1_bin, 255) self.assertRaises(ValueError, h.verify, wrong_mac) self.assertRaises(ValueError, h.hexverify, "4556") h = self.module.new(key, data, **self.params) out3 = h.hexdigest() out4 = binascii.b2a_hex(h.digest()) # Test .copy() h2 = h.copy() h.update(b("blah blah blah")) # Corrupt the original hash object out5 = binascii.b2a_hex(h2.digest()) # The copied hash object should return the correct result # PY3K: Check that hexdigest() returns str and digest() returns bytes if sys.version_info[0] > 2: self.assertTrue(isinstance(h.digest(), type(b("")))) self.assertTrue(isinstance(h.hexdigest(), type(""))) # PY3K: Check that .hexverify() accepts bytes or str if sys.version_info[0] > 2: h.hexverify(h.hexdigest()) h.hexverify(h.hexdigest().encode('ascii')) # PY3K: hexdigest() should return str, and digest() should return bytes self.assertEqual(expected, out1) if sys.version_info[0] == 2: self.assertEqual(expected, out2) self.assertEqual(expected, out3) else: self.assertEqual(expected.decode(), out2) self.assertEqual(expected.decode(), out3) self.assertEqual(expected, out4) self.assertEqual(expected, out5)
def runTest(self): tag = unhexlify(b"fb447350c4e868c52ac3275cf9d4327e") msg = b'' for msg_len in range(5000 + 1): key = tag + strxor_c(tag, 0xFF) nonce = tag[::-1] if msg_len > 0: msg = msg + tobytes(tag[0]) auth = Poly1305.new(key=key, nonce=nonce, cipher=AES, data=msg) tag = auth.digest() # Compare against output of original DJB's poly1305aes-20050218 self.assertEqual("CDFA436DDD629C7DC20E1128530BAED2", auth.hexdigest().upper())
def runTest(self): result_hex = hexlify(self.result) # Verify result h = self.module.new(self.key, **self.params) h.update(self.data) self.assertEqual(self.result, h.digest()) self.assertEqual(hexlify(self.result).decode('ascii'), h.hexdigest()) # Verify that correct MAC does not raise any exception h.verify(self.result) h.hexverify(result_hex) # Verify that incorrect MAC does raise ValueError exception wrong_mac = strxor_c(self.result, 255) self.assertRaises(ValueError, h.verify, wrong_mac) self.assertRaises(ValueError, h.hexverify, "4556") # Verify again, with data passed to new() h = self.module.new(self.key, self.data, **self.params) self.assertEqual(self.result, h.digest()) self.assertEqual(hexlify(self.result).decode('ascii'), h.hexdigest()) # Test .copy() try: h = self.module.new(self.key, self.data, **self.params) h2 = h.copy() h3 = h.copy() # Verify that changing the copy does not change the original h2.update(b"bla") self.assertEqual(h3.digest(), self.result) # Verify that both can reach the same state h.update(b"bla") self.assertEqual(h.digest(), h2.digest()) except NotImplementedError: pass # PY3K: Check that hexdigest() returns str and digest() returns bytes self.assertTrue(isinstance(h.digest(), type(b""))) self.assertTrue(isinstance(h.hexdigest(), type(""))) # PY3K: Check that .hexverify() accepts bytes or str h.hexverify(h.hexdigest()) h.hexverify(h.hexdigest().encode('ascii'))
def test_degradation(self): sub_key1 = bchr(1) * 8 sub_key2 = bchr(255) * 8 # K1 == K2 self.assertRaises(ValueError, DES3.adjust_key_parity, sub_key1 * 2 + sub_key2) # K2 == K3 self.assertRaises(ValueError, DES3.adjust_key_parity, sub_key1 + sub_key2 * 2) # K1 == K2 == K3 self.assertRaises(ValueError, DES3.adjust_key_parity, sub_key1 * 3) # K1 == K2 (with different parity) self.assertRaises(ValueError, DES3.adjust_key_parity, sub_key1 + strxor_c(sub_key1, 1) + sub_key2)
def runTest(self): sub_key1 = bchr(1) * 8 sub_key2 = bchr(255) * 8 # K1 == K2 self.assertRaises(ValueError, DES3.new, sub_key1 * 2 + sub_key2, DES3.MODE_ECB) # K2 == K3 self.assertRaises(ValueError, DES3.new, sub_key1 + sub_key2 * 2, DES3.MODE_ECB) # K1 == K2 == K3 self.assertRaises(ValueError, DES3.new, sub_key1 * 3, DES3.MODE_ECB) # K2 == K3 (parity is ignored) self.assertRaises(ValueError, DES3.new, sub_key1 + sub_key2 + strxor_c(sub_key2, 0x1), DES3.MODE_ECB)
def runTest(self): sub_key1 = bchr(1) * 8 sub_key2 = bchr(255) * 8 # K1 == K2 self.assertRaises(ValueError, DES3.new, sub_key1 * 2 + sub_key2, DES3.MODE_ECB) # K2 == K3 self.assertRaises(ValueError, DES3.new, sub_key1 + sub_key2 * 2, DES3.MODE_ECB) # K1 == K2 == K3 self.assertRaises(ValueError, DES3.new, sub_key1 *3, DES3.MODE_ECB) # K2 == K3 (parity is ignored) self.assertRaises(ValueError, DES3.new, sub_key1 + sub_key2 + strxor_c(sub_key2, 0x1), DES3.MODE_ECB)
def find_pt(cts: Iterator[bytes]) -> bytes: pts = (strxor.strxor_c(ct, k) for ct in cts for k in range(256)) return max(pts, key=heuristic)
def test3(self): self.assertEqual(strxor_c(b(""), 90), b(""))
def test_verify(self): h = Poly1305.new(key=self.key, cipher=AES) mac = h.digest() h.verify(mac) wrong_mac = strxor_c(mac, 255) self.assertRaises(ValueError, h.verify, wrong_mac)
def decrypt(ct): return strxor_c(ct, find_key(ct))
def _crypt(self, t: bytes) -> bytes: return strxor.strxor_c(t, self.k)
def test_verify(self): h = self.BLAKE2.new(digest_bytes=self.max_bytes, key=b"4") mac = h.digest() h.verify(mac) wrong_mac = strxor_c(mac, 255) self.assertRaises(ValueError, h.verify, wrong_mac)
def find_key(ct): heuristic = lambda k: sum(b in b" etaoin" for b in strxor_c(ct, k)) return max(range(256), key=heuristic)
if __name__ == "__main__": encrypted_message, iv = encryption_oracle() secret = b'' attacked_message = iv + encrypted_message for i in range(0, len(attacked_message) - AES.block_size, AES.block_size): # For each block decrypted_block = b'' for j in range(AES.block_size - 1, -1, -1): # For every char in block padding_bit = AES.block_size - j # Get block to XOR with xor_block = strxor_c(decrypted_block, padding_bit) # TODO: Figure out why random bytes were better than just a single byte repeated xor_block = get_random_bytes(AES.block_size - len(xor_block)) + xor_block # Try every bit till padding satisfies new_attacked = attacked_message[:i] + \ strxor(attacked_message[i:i+AES.block_size], xor_block) + \ attacked_message[i+AES.block_size:i+2*AES.block_size] attacked_iv = new_attacked[:AES.block_size] attacked_ciphertext = new_attacked[AES.block_size:] while not decryption_oracle(attacked_ciphertext, attacked_iv): xor_block = xor_block[:j] + \ bytes([(xor_block[j] + 1) % 256]) + xor_block[j+1:]
def test_bytearray(self): term1 = unhexlify(b"ff339a83e5cd4cdf5649") term1_ba = bytearray(term1) result = unhexlify(b"be72dbc2a48c0d9e1708") self.assertEqual(strxor_c(term1_ba, 65), result)
def find_pt(cts): pts = (strxor_c(ct, k) for ct in cts for k in range(256)) heuristic = lambda pt: sum(b in b" etaoin" for b in pt) return max(pts, key=heuristic)
def test_memoryview(self): term1 = unhexlify(b"ff339a83e5cd4cdf5649") term1_mv = memoryview(term1) result = unhexlify(b"be72dbc2a48c0d9e1708") self.assertEqual(strxor_c(term1_mv, 65), result)
def test1(self): term1 = unhexlify(b("ff339a83e5cd4cdf5649")) result = unhexlify(b("be72dbc2a48c0d9e1708")) self.assertEqual(strxor_c(term1, 65), result)
def test2(self): term1 = unhexlify(b("ff339a83e5cd4cdf5649")) self.assertEqual(strxor_c(term1, 0), term1)
def heuristic(k: int) -> int: # Number of common characters in the resulting plaintext. Higher is better. return sum(1 for b in strxor.strxor_c(ct, k) if b in common_chars)
def test3(self): self.assertEqual(strxor_c(b"", 90), b"")
def test2(self): term1 = unhexlify(b"ff339a83e5cd4cdf5649") self.assertEqual(strxor_c(term1, 0), term1)
def test1(self): term1 = unhexlify(b"ff339a83e5cd4cdf5649") result = unhexlify(b"be72dbc2a48c0d9e1708") self.assertEqual(strxor_c(term1, 65), result)
def test_verify(self): h = self.new() mac = h.digest() h.verify(mac) wrong_mac = strxor_c(mac, 255) self.assertRaises(ValueError, h.verify, wrong_mac)