#!/usr/bin/python # Copyright 2016 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Module for generating AES test vectors.""" from binascii import b2a_hex as b2a from Crypto.Cipher import AES from itertools import izip_longest import os modes = { AES.MODE_CBC: 'CBC', AES.MODE_CFB: 'CFB', AES.MODE_OFB: 'OFB', } template = \ ''' {pt} {key} {ct} {iv} ''' def h2be(v): # Convert input big-endian byte-string to 4-byte segmented # little-endian words. Pad-bytes (if necessary) are the empty string. word = [iter(v)] * 4 return ''.join([ ''.join(b[::-1]) for b in izip_longest(*word, fillvalue='') ]) for mode in [AES.MODE_CBC, AES.MODE_CFB, AES.MODE_OFB]: for key_bytes in [16, 24, 32]: test_num = 0 for pt_len in [5, 16, 21, 32]: # CBC mode requires block sized inputs. if mode == AES.MODE_CBC and pt_len % 16: continue test_num += 1 actual_pt_len = pt_len if pt_len % 16: pt_len = 16 * ((pt_len / 16) + 1) key = os.urandom(key_bytes) iv = os.urandom(16) pt = os.urandom(pt_len) obj = AES.new(key, mode=mode, IV=iv, segment_size=128) ct = obj.encrypt(pt) obj = AES.new(key, mode=mode, IV=iv, segment_size=128) assert obj.decrypt(ct)[:pt_len] == pt print template.format(mode=modes[mode], key_bits=str(key_bytes * 8), test_num=str(test_num), pt=b2a(h2be(pt[:actual_pt_len])), key=b2a(h2be(key)), ct=b2a(h2be(ct[:actual_pt_len])), iv=b2a(h2be(iv))),