• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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