def challenge_6(): with open('6.txt') as f: data = base64.b64decode(f.read()) keysize_candidates = list() for keysize in range(1, 30): chunks = chunk_into(data, keysize) pairs = itertools.combinations(chunks[:4], 2) score = 0 for a, b in pairs: hscore = hamming(a, b) logger.debug(hscore) score += hscore / keysize score /= 4 keysize_candidates.append((keysize, score)) keysize_probability = sorted(keysize_candidates, key=lambda x: x[1]) logger.info("Probable keysizes: {}".format(keysize_probability[:5])) for keysize, score in keysize_probability[:3]: key_ints = list() logger.debug(keysize) chunks = chunk_into(data, keysize) transposed = zip(*chunks[:-1]) for c in transposed: try: _, key_int = english_freq(bytes(c)) key_ints.append(key_int) except TypeError: break if len(key_ints) == keysize: return xor_with_key(data, bytes(key_ints))
def test_challenge_5(self): data = b"""Burning 'em, if you ain't quick and nimble I go crazy when I hear a cymbal""" output = binascii.unhexlify("0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272" "a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f") key = b'ICE' self.assertEqual(output, xor_with_key(data, key))
def decrypt(self, data): assert len(data) % 16 == 0 blocks = chunk_into(data, 16) plain = list() for block in blocks: plain.append(xor_with_key(ECB(self.key).decrypt(block), self._state)) self._state = block return unpad(b''.join(plain))
def main(): piecemeal = [bytes(x) for x in zip(*CIPHERTEXTS)] keystream = list() for x in piecemeal: c = english_freq(x) keystream.append(c[1]) for ct in CIPHERTEXTS: logger.info(xor_with_key(ct, bytes(keystream)))
def encrypt(self, data): ret = list() blocks = chunk_into(data, BLOCKSIZE) for i, block in enumerate(blocks): _ks = self.cipher.encrypt(struct.pack('<2Q', self.nonce, i)) logger.debug(block) logger.debug(_ks) ret.append(xor_with_key(block, _ks)) return b''.join(ret)
def decrypt(self, data): assert len(data) % 16 == 0 blocks = chunk_into(data, 16) plain = list() for block in blocks: plain.append( xor_with_key(ECB(self.key).decrypt(block), self._state)) self._state = block return unpad(b''.join(plain))
def test_challenge_5(self): data = b"""Burning 'em, if you ain't quick and nimble I go crazy when I hear a cymbal""" output = binascii.unhexlify( "0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272" "a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f" ) key = b'ICE' self.assertEqual(output, xor_with_key(data, key))
def encrypt(self, data): if not len(data) % 16 == 0: data = pkcs7pad(data, 16) blocks = chunk_into(data, 16) ciphertext = list() for block in blocks: cipherblock = ECB(self.key).encrypt(xor_with_key(block, self._state)) ciphertext.append(cipherblock) self._state = cipherblock return b''.join(ciphertext)
def encrypt(self, data): if not len(data) % 16 == 0: data = pkcs7pad(data, 16) blocks = chunk_into(data, 16) ciphertext = list() for block in blocks: cipherblock = ECB(self.key).encrypt( xor_with_key(block, self._state)) ciphertext.append(cipherblock) self._state = cipherblock return b''.join(ciphertext)
def main(): """ This actually solves Challenge 19 as Challenge 20 is meant to be solved. Deal with it :D :return: """ ciphertexts = encrypt() l = len(max(ciphertexts, key=len)) keystream = list() for x in range(l): z = bytes(ct[x] for ct in ciphertexts if len(ct) > x) c = english_freq(z) logger.fatal(c) keystream.append(c[1]) for ct in ciphertexts: logger.info(xor_with_key(ct, bytes(keystream)))
def challenge_15(): idxs = (0, 6, 11, 13) flipper = bytearray(16) inject = b':admin<true:x<' for i in idxs: flipper[i] = 1 for i in range(0, BLOCKSIZE): ct = c15_enc(b'x' * i + inject) paste = xor_with_key(ct[32:48], flipper) new_ct = ct[:32] + paste + ct[48:] if c15_verify(new_ct): return True else: logger.fatal('Bitflip attack failed') ct = c15_enc(inject) return c15_verify(ct)