1# This file is dual licensed under the terms of the Apache License, Version 2# 2.0, and the BSD License. See the LICENSE file in the root of this repository 3# for complete details. 4 5from __future__ import absolute_import, division, print_function 6 7import binascii 8 9from cryptography.hazmat.backends import default_backend 10from cryptography.hazmat.primitives import ciphers 11from cryptography.hazmat.primitives.ciphers import algorithms 12 13 14_RFC6229_KEY_MATERIALS = [ 15 (True, 16 8 * '0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20'), 17 (False, 18 8 * '1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a') 19] 20 21 22_RFC6229_OFFSETS = [ 23 0, 24 16, 25 240, 26 256, 27 496, 28 512, 29 752, 30 768, 31 1008, 32 1024, 33 1520, 34 1536, 35 2032, 36 2048, 37 3056, 38 3072, 39 4080, 40 4096 41] 42 43 44_SIZES_TO_GENERATE = [ 45 160 46] 47 48 49def _key_for_size(size, keyinfo): 50 msb, key = keyinfo 51 if msb: 52 return key[:size // 4] 53 else: 54 return key[-size // 4:] 55 56 57def _build_vectors(): 58 count = 0 59 output = [] 60 key = None 61 plaintext = binascii.unhexlify(32 * '0') 62 for size in _SIZES_TO_GENERATE: 63 for keyinfo in _RFC6229_KEY_MATERIALS: 64 key = _key_for_size(size, keyinfo) 65 cipher = ciphers.Cipher( 66 algorithms.ARC4(binascii.unhexlify(key)), 67 None, 68 default_backend()) 69 encryptor = cipher.encryptor() 70 current_offset = 0 71 for offset in _RFC6229_OFFSETS: 72 if offset % 16 != 0: 73 raise ValueError( 74 "Offset {} is not evenly divisible by 16" 75 .format(offset)) 76 while current_offset < offset: 77 encryptor.update(plaintext) 78 current_offset += len(plaintext) 79 output.append("\nCOUNT = {}".format(count)) 80 count += 1 81 output.append("KEY = {}".format(key)) 82 output.append("OFFSET = {}".format(offset)) 83 output.append("PLAINTEXT = {}".format( 84 binascii.hexlify(plaintext))) 85 output.append("CIPHERTEXT = {}".format( 86 binascii.hexlify(encryptor.update(plaintext)))) 87 current_offset += len(plaintext) 88 assert not encryptor.finalize() 89 return "\n".join(output) 90 91 92def _write_file(data, filename): 93 with open(filename, 'w') as f: 94 f.write(data) 95 96 97if __name__ == '__main__': 98 _write_file(_build_vectors(), 'arc4.txt') 99