Add support for 160 bit ARC4 keys
diff --git a/docs/development/custom-vectors/arc4.rst b/docs/development/custom-vectors/arc4.rst
new file mode 100644
index 0000000..ed8cd54
--- /dev/null
+++ b/docs/development/custom-vectors/arc4.rst
@@ -0,0 +1,30 @@
+ARC4 vector creation
+====================
+
+This page documents the code that was used to generate the ARC4 test
+vectors for key lengths not available in RFC 6229. All the vectors
+were generated using OpenSSL and verified with Go.
+
+Creation
+--------
+
+``cryptography`` was modified to support ARC4 key lengths not listed
+in RFC 6229. Then the following Python script was run to generate the
+vector files.
+
+.. literalinclude:: /development/custom-vectors/arc4/generate_arc4.py
+
+Download link: :download:`generate_arc4.py
+</development/custom-vectors/arc4/generate_arc4.py>`
+
+
+Verification
+------------
+
+The following Go code was used to verify the vectors.
+
+.. literalinclude:: /development/custom-vectors/arc4/verify_arc4.go
+    :language: go
+
+Download link: :download:`verify_arc4.go
+</development/custom-vectors/arc4/verify_arc4.go>`
diff --git a/docs/development/custom-vectors/arc4/generate_arc4.py b/docs/development/custom-vectors/arc4/generate_arc4.py
new file mode 100644
index 0000000..093bb49
--- /dev/null
+++ b/docs/development/custom-vectors/arc4/generate_arc4.py
@@ -0,0 +1,89 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives import ciphers
+from cryptography.hazmat.primitives.ciphers import algorithms
+
+
+_RFC6229_KEY_MATERIALS = [
+    (True, 8*'0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20'),
+    (False, 8*'1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a')
+]
+
+
+_RFC6229_OFFSETS = [
+    0,
+    16,
+    240,
+    256,
+    496,
+    512,
+    752,
+    768,
+    1008,
+    1024,
+    1520,
+    1536,
+    2032,
+    2048,
+    3056,
+    3072,
+    4080,
+    4096
+]
+
+
+_SIZES_TO_GENERATE = [
+    160
+]
+
+
+def _key_for_size(size, keyinfo):
+    msb, key = keyinfo
+    if msb:
+        return key[:size//4]
+    else:
+        return key[-size//4:]
+
+
+def _build_vectors():
+    count = 0
+    output = []
+    key = None
+    plaintext = binascii.unhexlify(32*'0')
+    for size in _SIZES_TO_GENERATE:
+        for keyinfo in _RFC6229_KEY_MATERIALS:
+            key = _key_for_size(size, keyinfo)
+            cipher = ciphers.Cipher(algorithms.ARC4(binascii.unhexlify(key)), None, default_backend())
+            encryptor = cipher.encryptor()
+            current_offset = 0
+            for offset in _RFC6229_OFFSETS:
+                if offset % 16 != 0:
+                    raise ValueError("Offset {} is not evenly divisible by 16".format(offset))
+                while current_offset < offset:
+                    encryptor.update(plaintext)
+                    current_offset += len(plaintext)
+                output.append("\nCOUNT = {}".format(count))
+                count += 1
+                output.append("KEY = {}".format(key))
+                output.append("OFFSET = {}".format(offset))
+                output.append("PLAINTEXT = {}".format(binascii.hexlify(plaintext)))
+                output.append("CIPHERTEXT = {}".format(binascii.hexlify(encryptor.update(plaintext))))
+                current_offset += len(plaintext)
+            assert not encryptor.finalize()
+    return "\n".join(output)
+
+
+def _write_file(data, filename):
+    with open(filename, 'w') as f:
+        f.write(data)
+
+
+if __name__ == '__main__':
+    _write_file(_build_vectors(), 'arc4.txt')
diff --git a/docs/development/custom-vectors/arc4/verify_arc4.go b/docs/development/custom-vectors/arc4/verify_arc4.go
new file mode 100644
index 0000000..508fe98
--- /dev/null
+++ b/docs/development/custom-vectors/arc4/verify_arc4.go
@@ -0,0 +1,111 @@
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"crypto/rc4"
+	"encoding/hex"
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+)
+
+func unhexlify(s string) []byte {
+	bytes, err := hex.DecodeString(s)
+	if err != nil {
+		panic(err)
+	}
+	return bytes
+}
+
+type vectorArgs struct {
+	count      string
+	offset     uint64
+	key        string
+	plaintext  string
+	ciphertext string
+}
+
+type vectorVerifier interface {
+	validate(count string, offset uint64, key, plaintext, expectedCiphertext []byte)
+}
+
+type arc4Verifier struct{}
+
+func (o arc4Verifier) validate(count string, offset uint64, key, plaintext, expectedCiphertext []byte) {
+	if offset%16 != 0 || len(plaintext) != 16 || len(expectedCiphertext) != 16 {
+		panic(fmt.Errorf("Unexpected input value encountered: offset=%v; len(plaintext)=%v; len(expectedCiphertext)=%v",
+			offset,
+			len(plaintext),
+			len(expectedCiphertext)))
+	}
+	stream, err := rc4.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	var currentOffset uint64 = 0
+	ciphertext := make([]byte, len(plaintext))
+	for currentOffset <= offset {
+		stream.XORKeyStream(ciphertext, plaintext)
+		currentOffset += uint64(len(plaintext))
+	}
+	if !bytes.Equal(ciphertext, expectedCiphertext) {
+		panic(fmt.Errorf("vector mismatch @ COUNT = %s:\n  %s != %s\n",
+			count,
+			hex.EncodeToString(expectedCiphertext),
+			hex.EncodeToString(ciphertext)))
+	}
+}
+
+func validateVectors(verifier vectorVerifier, filename string) {
+	vectors, err := os.Open(filename)
+	if err != nil {
+		panic(err)
+	}
+	defer vectors.Close()
+
+	var segments []string
+	var vector *vectorArgs
+
+	scanner := bufio.NewScanner(vectors)
+	for scanner.Scan() {
+		segments = strings.Split(scanner.Text(), " = ")
+
+		switch {
+		case strings.ToUpper(segments[0]) == "COUNT":
+			if vector != nil {
+				verifier.validate(vector.count,
+					vector.offset,
+					unhexlify(vector.key),
+					unhexlify(vector.plaintext),
+					unhexlify(vector.ciphertext))
+			}
+			vector = &vectorArgs{count: segments[1]}
+		case strings.ToUpper(segments[0]) == "OFFSET":
+			vector.offset, err = strconv.ParseUint(segments[1], 10, 64)
+			if err != nil {
+				panic(err)
+			}
+		case strings.ToUpper(segments[0]) == "KEY":
+			vector.key = segments[1]
+		case strings.ToUpper(segments[0]) == "PLAINTEXT":
+			vector.plaintext = segments[1]
+		case strings.ToUpper(segments[0]) == "CIPHERTEXT":
+			vector.ciphertext = segments[1]
+		}
+	}
+	if vector != nil {
+		verifier.validate(vector.count,
+			vector.offset,
+			unhexlify(vector.key),
+			unhexlify(vector.plaintext),
+			unhexlify(vector.ciphertext))
+	}
+}
+
+func main() {
+	validateVectors(arc4Verifier{}, "vectors/cryptography_vectors/ciphers/ARC4/arc4.txt")
+	fmt.Println("ARC4 OK.")
+}
diff --git a/src/cryptography/hazmat/primitives/ciphers/algorithms.py b/src/cryptography/hazmat/primitives/ciphers/algorithms.py
index b71dddb..c193f79 100644
--- a/src/cryptography/hazmat/primitives/ciphers/algorithms.py
+++ b/src/cryptography/hazmat/primitives/ciphers/algorithms.py
@@ -101,7 +101,7 @@
 @utils.register_interface(CipherAlgorithm)
 class ARC4(object):
     name = "RC4"
-    key_sizes = frozenset([40, 56, 64, 80, 128, 192, 256])
+    key_sizes = frozenset([40, 56, 64, 80, 128, 160, 192, 256])
 
     def __init__(self, key):
         self.key = _verify_key_size(self, key)
diff --git a/tests/hazmat/primitives/test_arc4.py b/tests/hazmat/primitives/test_arc4.py
index acd306b..00fc95b 100644
--- a/tests/hazmat/primitives/test_arc4.py
+++ b/tests/hazmat/primitives/test_arc4.py
@@ -35,6 +35,7 @@
             "rfc-6229-128.txt",
             "rfc-6229-192.txt",
             "rfc-6229-256.txt",
+            "arc4.txt"
         ],
         lambda key, **kwargs: algorithms.ARC4(binascii.unhexlify(key)),
     )
diff --git a/vectors/cryptography_vectors/ciphers/ARC4/arc4.txt b/vectors/cryptography_vectors/ciphers/ARC4/arc4.txt
new file mode 100644
index 0000000..4c586d6
--- /dev/null
+++ b/vectors/cryptography_vectors/ciphers/ARC4/arc4.txt
@@ -0,0 +1,216 @@
+
+COUNT = 0
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f644d3aa1f242c35f51b71d4faf55383
+
+COUNT = 1
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b4ec4b071c79cfe214b460d84d0d4342
+
+COUNT = 2
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 93b095fdb3da6e88465fd3b195e7ae5a
+
+COUNT = 3
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 80f27f1cf1702bd27c4b3e995ceb95d8
+
+COUNT = 4
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a5ec0488c40c6f94d9b453fe664ba9e1
+
+COUNT = 5
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = aa0371431d55c9e48c3da3a251933f1a
+
+COUNT = 6
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d7b37fe82ce43d0edf46152b40e947cf
+
+COUNT = 7
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fad08d586e5906c806881e0f3cf2057d
+
+COUNT = 8
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 61cfa6a67577bf0bc11daeb9a4080a95
+
+COUNT = 9
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d0ef0c6b23f128219c352c15881d52c1
+
+COUNT = 10
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 12e4aed2445a40b013823ef92a1537e7
+
+COUNT = 11
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3c99522399fc2b4e3d10965b954d2c05
+
+COUNT = 12
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bdf85291b809850b3ff94f28547630cd
+
+COUNT = 13
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ed9e6ebd97f43d39b69035d04baf9dde
+
+COUNT = 14
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 63bca8ef13303eb912c3acd243968fe6
+
+COUNT = 15
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 91648dd1ccb08511f990af8b7555e8a0
+
+COUNT = 16
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e2bd078d5e578d90e50d53b65364776c
+
+COUNT = 17
+KEY = 0102030405060708090a0b0c0d0e0f1011121314
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9c894f815caa4a9e60452082158faa14
+
+COUNT = 18
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 40b068b70cbe9b5115f57c86361c6f20
+
+COUNT = 19
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 534c0249ce55beadb24e7c16c4eab1ae
+
+COUNT = 20
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5856b3366925e231ef602328b07cf3b7
+
+COUNT = 21
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 280a60d06c151953db8e45fb7b0df11c
+
+COUNT = 22
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 40fc3ea8dc5512a774bcce590319ca1b
+
+COUNT = 23
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 604e10c7c490d9bdfb4c69bdfff18852
+
+COUNT = 24
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 46de8d697170633913c1625f96776aed
+
+COUNT = 25
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 67b1c2de2dd328d66c78d341b879aee7
+
+COUNT = 26
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0e03b8cfc8683da0a802bfe5dba7d8bc
+
+COUNT = 27
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d4bb24de2be6559ab2b9fb5eee38d555
+
+COUNT = 28
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bcdbbcb75b18472371753daa15843046
+
+COUNT = 29
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 51b4a22fef8c33d27de9265855a670d4
+
+COUNT = 30
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9464c6af04a56b35c80058a9d68dae99
+
+COUNT = 31
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3c91eaf71e94ced21d093ab8a08b98ef
+
+COUNT = 32
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 537f5e714a9d141a9bd5d19dfee2e19f
+
+COUNT = 33
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dfc61cece2570fa52dbda2e52b4c98b0
+
+COUNT = 34
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5a5ad75eb1bb615d6e2382eabe95e782
+
+COUNT = 35
+KEY = 08ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 11ebf8e2c10017575976a94b44407f3e
\ No newline at end of file