def decAESCBC_keep_padding(ctext, key): blocks = make_segments(ctext, 16) IV = chr(0) * 16 cipher = AES.new(key, AES.MODE_ECB) ptext = '' for block in blocks: ptext += fixedXOR(IV, cipher.decrypt(block)) IV = block return ptext
def decAESCBC(ctext, key): blocks = make_segments(ctext, 16) IV = key cipher = AES.new(key, AES.MODE_ECB) ptext = '' for block in blocks: ptext += fixedXOR(IV, cipher.decrypt(block)) IV = block return check_and_strip_PKCS(ptext)
def decrypt_and_validate(ctext): blocks = make_segments(ctext, 16) IV = fixed_oracle_key cipher = AES.new(fixed_oracle_key, AES.MODE_ECB) ptext = '' for block in blocks: ptext += fixedXOR(IV, cipher.decrypt(block)) IV = block ascii_compliant(ptext) return check_and_strip_PKCS(ptext)
def encAESCBC(ptext, key): """ Encrypts ptext under key with AES in CBC mode. Rules for input and output are the same as for the pycrypto function used as primitive (i.e., bytestrings). """ cipher = AES.new(key, AES.MODE_ECB) pad_length = 16 - (len(ptext) % 16) ptext = PKCS(ptext, pad_length) blocks = make_segments(ptext, 16) IV = key ctext = '' for block in blocks: output = cipher.encrypt(fixedXOR(IV, block)) # needs to be string or read-only buffer ctext += output IV = output return ctext
def CTR_break2( ): # need to adapt some of the functions from set1 before this will work ctexts = loadCT() min_length = min([len(ctext) for ctext in ctexts]) num_blocks = min_length / 16 decrypt_length = num_blocks * 16 vigs = [] for i in xrange(0, decrypt_length, 16): vig = [ctext[i:i + 16] for ctext in ctexts] vigs.append(vig) ptexts = [] keys = [] for vig in vigs: key, decrypted = breakVig(vig) keys.append(key) ptexts.append(make_segments(decrypted, 16)) ptexts = zip(*ptexts) print 'Maximum overlap in samples: ' + str(min_length) print 'Decrypt length: ' + str(decrypt_length) for i in xrange(len(ptexts)): print 'Ciphertext: ' + ctexts[i] print 'Plaintext: ' + ptexts[i] print '\n'
def padding_attack(): ctext, IV = send_token() cblocks = [IV] cblocks.extend(make_segments(ctext, 16)) maul = bytearray('\x00') * 16 pblocks = [] for i in xrange(len(cblocks) - 1): P = '' C = cblocks[i + 1] # block to be decrypted padding_value = 0 for j in xrange(15, -1, -1): # break block attack_value = 0 for k in xrange(256): # scan for valid padding maul[j] = k sub = ''.join(map(chr, maul)) + C if padding_oracle(sub): if j == 15: # check for edge case: valid padding != \x01 subsub = sub[:j - 1] + chr(ord('\xFF') ^ ord(sub[j - 1])) + sub[j:] if not padding_oracle(subsub): # in edge case continue attack_value = k break else: # full loop with no match raise ValueError('No match found for block %s, byte %s' % (i + 1, j)) # if we make it here, a match was found and the padding is as expected padding_value += 1 P = chr(((padding_value) ^ attack_value) ^ ord(cblocks[i][j])) + P maul[j] = (padding_value ^ attack_value) ^ (padding_value + 1) for t in xrange(j + 1, len(maul)): maul[t] ^= (padding_value ^ (padding_value + 1)) pblocks.append(P) return check_and_strip_PKCS(''.join(pblocks)), decAESCBC( ctext, fixed_oracle_key)