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 ( 16 True, 17 8 * "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", 18 ), 19 ( 20 False, 21 8 * "1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a", 22 ), 23] 24 25 26_RFC6229_OFFSETS = [ 27 0, 28 16, 29 240, 30 256, 31 496, 32 512, 33 752, 34 768, 35 1008, 36 1024, 37 1520, 38 1536, 39 2032, 40 2048, 41 3056, 42 3072, 43 4080, 44 4096, 45] 46 47 48_SIZES_TO_GENERATE = [160] 49 50 51def _key_for_size(size, keyinfo): 52 msb, key = keyinfo 53 if msb: 54 return key[: size // 4] 55 else: 56 return key[-size // 4 :] 57 58 59def _build_vectors(): 60 count = 0 61 output = [] 62 key = None 63 plaintext = binascii.unhexlify(32 * "0") 64 for size in _SIZES_TO_GENERATE: 65 for keyinfo in _RFC6229_KEY_MATERIALS: 66 key = _key_for_size(size, keyinfo) 67 cipher = ciphers.Cipher( 68 algorithms.ARC4(binascii.unhexlify(key)), 69 None, 70 default_backend(), 71 ) 72 encryptor = cipher.encryptor() 73 current_offset = 0 74 for offset in _RFC6229_OFFSETS: 75 if offset % 16 != 0: 76 raise ValueError( 77 "Offset {} is not evenly divisible by 16".format( 78 offset 79 ) 80 ) 81 while current_offset < offset: 82 encryptor.update(plaintext) 83 current_offset += len(plaintext) 84 output.append("\nCOUNT = {}".format(count)) 85 count += 1 86 output.append("KEY = {}".format(key)) 87 output.append("OFFSET = {}".format(offset)) 88 output.append( 89 "PLAINTEXT = {}".format(binascii.hexlify(plaintext)) 90 ) 91 output.append( 92 "CIPHERTEXT = {}".format( 93 binascii.hexlify(encryptor.update(plaintext)) 94 ) 95 ) 96 current_offset += len(plaintext) 97 assert not encryptor.finalize() 98 return "\n".join(output) 99 100 101def _write_file(data, filename): 102 with open(filename, "w") as f: 103 f.write(data) 104 105 106if __name__ == "__main__": 107 _write_file(_build_vectors(), "arc4.txt") 108