aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2013-11-07 14:25:44 -0800
committerAlex Gaynor <alex.gaynor@gmail.com>2013-11-07 14:25:44 -0800
commit60f1d8b89cf7eb6f4d58eed7be9b816056c1df9c (patch)
tree5912a5ebeec4f4ffe8ecd6b0fd11b1794a8772c5
parent105e8137799a2ef7ec8275e3c01d61a04884413b (diff)
parent635b542ded9ede772a2ca907e8bb5349ded333bd (diff)
downloadcryptography-60f1d8b89cf7eb6f4d58eed7be9b816056c1df9c.tar.gz
cryptography-60f1d8b89cf7eb6f4d58eed7be9b816056c1df9c.tar.bz2
cryptography-60f1d8b89cf7eb6f4d58eed7be9b816056c1df9c.zip
Merge branch 'master' into fernet
-rw-r--r--.travis.yml20
-rwxr-xr-x.travis/install.sh28
-rw-r--r--README.rst8
-rw-r--r--cryptography/exceptions.py16
-rw-r--r--cryptography/hazmat/bindings/openssl/asn1.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/backend.py71
-rw-r--r--cryptography/hazmat/bindings/openssl/bignum.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/bio.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/conf.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/crypto.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/dh.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/dsa.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/engine.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/err.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/evp.py18
-rw-r--r--cryptography/hazmat/bindings/openssl/hmac.py66
-rw-r--r--cryptography/hazmat/bindings/openssl/nid.py9
-rw-r--r--cryptography/hazmat/bindings/openssl/opensslv.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/pem.py6
-rw-r--r--cryptography/hazmat/bindings/openssl/pkcs12.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/pkcs7.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/rand.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/rsa.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/ssl.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/x509.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/x509name.py3
-rw-r--r--cryptography/hazmat/bindings/openssl/x509v3.py3
-rw-r--r--cryptography/hazmat/primitives/ciphers/__init__.py (renamed from cryptography/hazmat/primitives/block/__init__.py)4
-rw-r--r--cryptography/hazmat/primitives/ciphers/algorithms.py (renamed from cryptography/hazmat/primitives/block/ciphers.py)0
-rw-r--r--cryptography/hazmat/primitives/ciphers/base.py (renamed from cryptography/hazmat/primitives/block/base.py)14
-rw-r--r--cryptography/hazmat/primitives/ciphers/modes.py (renamed from cryptography/hazmat/primitives/block/modes.py)5
-rw-r--r--cryptography/hazmat/primitives/interfaces.py22
-rw-r--r--docs/community.rst5
-rw-r--r--docs/conf.py4
-rw-r--r--docs/contributing.rst2
-rw-r--r--docs/exceptions.rst9
-rw-r--r--docs/glossary.rst30
-rw-r--r--docs/hazmat/primitives/hmac.rst2
-rw-r--r--docs/hazmat/primitives/index.rst1
-rw-r--r--docs/hazmat/primitives/interfaces.rst59
-rw-r--r--docs/hazmat/primitives/symmetric-encryption.rst70
-rw-r--r--docs/index.rst2
-rw-r--r--tests/hazmat/bindings/test_openssl.py34
-rw-r--r--tests/hazmat/primitives/test_3des.py14
-rw-r--r--tests/hazmat/primitives/test_aes.py14
-rw-r--r--tests/hazmat/primitives/test_block.py39
-rw-r--r--tests/hazmat/primitives/test_blowfish.py18
-rw-r--r--tests/hazmat/primitives/test_camellia.py18
-rw-r--r--tests/hazmat/primitives/test_cast5.py6
-rw-r--r--tests/hazmat/primitives/test_ciphers.py2
-rw-r--r--tests/hazmat/primitives/utils.py4
-rw-r--r--tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-128.txt254
-rw-r--r--tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-192.txt254
-rw-r--r--tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-256.txt254
-rw-r--r--tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-40.txt237
-rw-r--r--tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-56.txt254
-rw-r--r--tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-64.txt254
-rw-r--r--tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-80.txt254
-rw-r--r--tox.ini2
59 files changed, 2308 insertions, 129 deletions
diff --git a/.travis.yml b/.travis.yml
index cf6ecefa..0a8771ef 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,21 +11,29 @@ env:
- TOX_ENV=py32 CC=clang
- TOX_ENV=py33 CC=clang
- TOX_ENV=pypy CC=clang
+ - TOX_ENV=py26 OPENSSL=0.9.8
+ - TOX_ENV=py27 OPENSSL=0.9.8
+ - TOX_ENV=py32 OPENSSL=0.9.8
+ - TOX_ENV=py33 OPENSSL=0.9.8
+ - TOX_ENV=pypy OPENSSL=0.9.8
+ - TOX_ENV=py26 CC=clang OPENSSL=0.9.8
+ - TOX_ENV=py27 CC=clang OPENSSL=0.9.8
+ - TOX_ENV=py32 CC=clang OPENSSL=0.9.8
+ - TOX_ENV=py33 CC=clang OPENSSL=0.9.8
+ - TOX_ENV=pypy CC=clang OPENSSL=0.9.8
- TOX_ENV=docs
- TOX_ENV=pep8
- TOX_ENV=py3pep8
install:
- - "[[ ${TOX_ENV} == pypy ]] && sudo add-apt-repository -y ppa:pypy/ppa || true"
- - "[[ ${TOX_ENV} == pypy ]] && sudo apt-get -y update && sudo apt-get -y install pypy || true"
- # This is required because we need to get rid of the Travis installed PyPy
- # or it'll take precedence over the PPA installed one.
- - "[[ ${TOX_ENV} == pypy ]] && sudo rm -rf /usr/local/pypy/bin || true"
- - pip install tox
+ - ./.travis/install.sh
script:
- tox -e $TOX_ENV
+after_success:
+ - coveralls
+
notifications:
irc:
channels:
diff --git a/.travis/install.sh b/.travis/install.sh
new file mode 100755
index 00000000..fdd71907
--- /dev/null
+++ b/.travis/install.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+set -e
+set -x
+
+if [[ "${OPENSSL}" == "0.9.8" ]]; then
+ sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ lucid main"
+fi
+
+if [[ "${TOX_ENV}" == "pypy" ]]; then
+ sudo add-apt-repository -y ppa:pypy/ppa
+fi
+
+sudo apt-get -y update
+
+if [[ "${OPENSSL}" == "0.9.8" ]]; then
+ sudo apt-get install -y --force-yes libssl-dev/lucid
+fi
+
+if [[ "${TOX_ENV}" == "pypy" ]]; then
+ sudo apt-get install -y pypy
+
+ # This is required because we need to get rid of the Travis installed PyPy
+ # or it'll take precedence over the PPA installed one.
+ sudo rm -rf /usr/local/pypy/bin
+fi
+
+pip install tox coveralls
diff --git a/README.rst b/README.rst
index c9baddea..def2e1fc 100644
--- a/README.rst
+++ b/README.rst
@@ -2,13 +2,17 @@ Cryptography
============
.. image:: https://travis-ci.org/pyca/cryptography.png?branch=master
- :target: https://travis-ci.org/pyca/cryptography
+ :target: https://travis-ci.org/pyca/cryptography
+
+.. image:: https://coveralls.io/repos/pyca/cryptography/badge.png?branch=master
+ :target: https://coveralls.io/r/pyca/cryptography?branch=master
+
``cryptography`` is a package designed to expose cryptographic recipes and
primitives to Python developers.
It is currently in early development and isn't recommended for general usage
-yet. It targets Python 2.6-2.7, Python 3.2+, as well as PyPy.
+yet. It targets Python 2.6-2.7, Python 3.2+, and PyPy.
You can find more information in the `documentation`_.
diff --git a/cryptography/exceptions.py b/cryptography/exceptions.py
new file mode 100644
index 00000000..391bed82
--- /dev/null
+++ b/cryptography/exceptions.py
@@ -0,0 +1,16 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+class UnsupportedAlgorithm(Exception):
+ pass
diff --git a/cryptography/hazmat/bindings/openssl/asn1.py b/cryptography/hazmat/bindings/openssl/asn1.py
index 5bd72e9a..719a523c 100644
--- a/cryptography/hazmat/bindings/openssl/asn1.py
+++ b/cryptography/hazmat/bindings/openssl/asn1.py
@@ -119,3 +119,6 @@ long ASN1_INTEGER_get(ASN1_INTEGER *);
BIGNUM *ASN1_INTEGER_to_BN(ASN1_INTEGER *, BIGNUM *);
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py
index fc73dd39..0c3d22d5 100644
--- a/cryptography/hazmat/bindings/openssl/backend.py
+++ b/cryptography/hazmat/bindings/openssl/backend.py
@@ -18,11 +18,14 @@ import sys
import cffi
+from cryptography.exceptions import UnsupportedAlgorithm
from cryptography.hazmat.primitives import interfaces
-from cryptography.hazmat.primitives.block.ciphers import (
+from cryptography.hazmat.primitives.ciphers.algorithms import (
AES, Blowfish, Camellia, CAST5, TripleDES,
)
-from cryptography.hazmat.primitives.block.modes import CBC, CTR, ECB, OFB, CFB
+from cryptography.hazmat.primitives.ciphers.modes import (
+ CBC, CTR, ECB, OFB, CFB
+)
class Backend(object):
@@ -54,29 +57,45 @@ class Backend(object):
"x509v3",
]
+ ffi = None
+ lib = None
+
def __init__(self):
- self.ffi = cffi.FFI()
+ self._ensure_ffi_initialized()
+
+ self.ciphers = Ciphers(self)
+ self.hashes = Hashes(self)
+ self.hmacs = HMACs(self)
+
+ @classmethod
+ def _ensure_ffi_initialized(cls):
+ if cls.ffi is not None and cls.lib is not None:
+ return
+
+ ffi = cffi.FFI()
includes = []
functions = []
macros = []
- for name in self._modules:
+ customizations = []
+ for name in cls._modules:
module_name = "cryptography.hazmat.bindings.openssl." + name
__import__(module_name)
module = sys.modules[module_name]
- self.ffi.cdef(module.TYPES)
+ ffi.cdef(module.TYPES)
macros.append(module.MACROS)
functions.append(module.FUNCTIONS)
includes.append(module.INCLUDES)
+ customizations.append(module.CUSTOMIZATIONS)
# loop over the functions & macros after declaring all the types
# so we can set interdependent types in different files and still
# have them all defined before we parse the funcs & macros
for func in functions:
- self.ffi.cdef(func)
+ ffi.cdef(func)
for macro in macros:
- self.ffi.cdef(macro)
+ ffi.cdef(macro)
# We include functions here so that if we got any of their definitions
# wrong, the underlying C compiler will explode. In C you are allowed
@@ -86,17 +105,15 @@ class Backend(object):
# is legal, but the following will fail to compile:
# int foo(int);
# int foo(short);
- self.lib = self.ffi.verify(
- source="\n".join(includes + functions),
+ lib = ffi.verify(
+ source="\n".join(includes + functions + customizations),
libraries=["crypto", "ssl"],
)
- self.lib.OpenSSL_add_all_algorithms()
- self.lib.SSL_load_error_strings()
-
- self.ciphers = Ciphers(self)
- self.hashes = Hashes(self)
- self.hmacs = HMACs(self)
+ cls.ffi = ffi
+ cls.lib = lib
+ cls.lib.OpenSSL_add_all_algorithms()
+ cls.lib.SSL_load_error_strings()
def openssl_version_text(self):
"""
@@ -128,10 +145,15 @@ class _CipherContext(object):
ctx = self._backend.ffi.gc(ctx, self._backend.lib.EVP_CIPHER_CTX_free)
registry = self._backend.ciphers._cipher_registry
- evp_cipher = registry[type(cipher), type(mode)](
- self._backend, cipher, mode
- )
- assert evp_cipher != self._backend.ffi.NULL
+ try:
+ adapter = registry[type(cipher), type(mode)]
+ except KeyError:
+ raise UnsupportedAlgorithm
+
+ evp_cipher = adapter(self._backend, cipher, mode)
+ if evp_cipher == self._backend.ffi.NULL:
+ raise UnsupportedAlgorithm
+
if isinstance(mode, interfaces.ModeWithInitializationVector):
iv_nonce = mode.initialization_vector
elif isinstance(mode, interfaces.ModeWithNonce):
@@ -297,19 +319,20 @@ class HMACs(object):
evp_md = self._backend.lib.EVP_get_digestbyname(
hash_cls.name.encode('ascii'))
assert evp_md != self._backend.ffi.NULL
- res = self._backend.lib.HMAC_Init_ex(ctx, key, len(key), evp_md,
- self._backend.ffi.NULL)
+ res = self._backend.lib.Cryptography_HMAC_Init_ex(
+ ctx, key, len(key), evp_md, self._backend.ffi.NULL
+ )
assert res != 0
return ctx
def update_ctx(self, ctx, data):
- res = self._backend.lib.HMAC_Update(ctx, data, len(data))
+ res = self._backend.lib.Cryptography_HMAC_Update(ctx, data, len(data))
assert res != 0
def finalize_ctx(self, ctx, digest_size):
buf = self._backend.ffi.new("unsigned char[]", digest_size)
buflen = self._backend.ffi.new("unsigned int *", digest_size)
- res = self._backend.lib.HMAC_Final(ctx, buf, buflen)
+ res = self._backend.lib.Cryptography_HMAC_Final(ctx, buf, buflen)
assert res != 0
self._backend.lib.HMAC_CTX_cleanup(ctx)
return self._backend.ffi.buffer(buf)[:digest_size]
@@ -319,7 +342,7 @@ class HMACs(object):
self._backend.lib.HMAC_CTX_init(copied_ctx)
copied_ctx = self._backend.ffi.gc(copied_ctx,
self._backend.lib.HMAC_CTX_cleanup)
- res = self._backend.lib.HMAC_CTX_copy(copied_ctx, ctx)
+ res = self._backend.lib.Cryptography_HMAC_CTX_copy(copied_ctx, ctx)
assert res != 0
return copied_ctx
diff --git a/cryptography/hazmat/bindings/openssl/bignum.py b/cryptography/hazmat/bindings/openssl/bignum.py
index 72d467c3..fcfadff1 100644
--- a/cryptography/hazmat/bindings/openssl/bignum.py
+++ b/cryptography/hazmat/bindings/openssl/bignum.py
@@ -32,3 +32,6 @@ int BN_hex2bn(BIGNUM **, const char *);
MACROS = """
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/bio.py b/cryptography/hazmat/bindings/openssl/bio.py
index 88be788f..c23dd0d8 100644
--- a/cryptography/hazmat/bindings/openssl/bio.py
+++ b/cryptography/hazmat/bindings/openssl/bio.py
@@ -168,3 +168,6 @@ long BIO_set_buffer_read_data(BIO *, void *, long);
#define BIO_TYPE_BASE64 ...
#define BIO_TYPE_FILTER ...
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/conf.py b/cryptography/hazmat/bindings/openssl/conf.py
index 85c7a210..4846252c 100644
--- a/cryptography/hazmat/bindings/openssl/conf.py
+++ b/cryptography/hazmat/bindings/openssl/conf.py
@@ -24,3 +24,6 @@ FUNCTIONS = """
MACROS = """
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/crypto.py b/cryptography/hazmat/bindings/openssl/crypto.py
index 501fb5a1..773d9b14 100644
--- a/cryptography/hazmat/bindings/openssl/crypto.py
+++ b/cryptography/hazmat/bindings/openssl/crypto.py
@@ -35,3 +35,6 @@ void CRYPTO_malloc_debug_init();
#define CRYPTO_MEM_CHECK_ENABLE ...
#define CRYPTO_MEM_CHECK_DISABLE ...
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/dh.py b/cryptography/hazmat/bindings/openssl/dh.py
index ac130054..b8fbf368 100644
--- a/cryptography/hazmat/bindings/openssl/dh.py
+++ b/cryptography/hazmat/bindings/openssl/dh.py
@@ -26,3 +26,6 @@ void DH_free(DH *);
MACROS = """
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/dsa.py b/cryptography/hazmat/bindings/openssl/dsa.py
index 2fa67b87..e6c369a6 100644
--- a/cryptography/hazmat/bindings/openssl/dsa.py
+++ b/cryptography/hazmat/bindings/openssl/dsa.py
@@ -28,3 +28,6 @@ void DSA_free(DSA *);
MACROS = """
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/engine.py b/cryptography/hazmat/bindings/openssl/engine.py
index b3ec3125..b76befce 100644
--- a/cryptography/hazmat/bindings/openssl/engine.py
+++ b/cryptography/hazmat/bindings/openssl/engine.py
@@ -50,3 +50,6 @@ MACROS = """
#define ENGINE_METHOD_ALL ...
#define ENGINE_METHOD_NONE ...
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/err.py b/cryptography/hazmat/bindings/openssl/err.py
index 39ae315c..6a36dee0 100644
--- a/cryptography/hazmat/bindings/openssl/err.py
+++ b/cryptography/hazmat/bindings/openssl/err.py
@@ -57,3 +57,6 @@ int ERR_GET_FUNC(unsigned long);
int ERR_GET_REASON(unsigned long);
int ERR_FATAL_ERROR(unsigned long);
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/evp.py b/cryptography/hazmat/bindings/openssl/evp.py
index 4d0fb7fc..da54f89d 100644
--- a/cryptography/hazmat/bindings/openssl/evp.py
+++ b/cryptography/hazmat/bindings/openssl/evp.py
@@ -29,9 +29,9 @@ typedef struct evp_pkey_st {
} EVP_PKEY;
static const int EVP_PKEY_RSA;
static const int EVP_PKEY_DSA;
-static const int EVP_CTRL_GCM_SET_IVLEN;
-static const int EVP_CTRL_GCM_GET_TAG;
-static const int EVP_CTRL_GCM_SET_TAG;
+static const int Cryptography_EVP_CTRL_GCM_SET_IVLEN;
+static const int Cryptography_EVP_CTRL_GCM_GET_TAG;
+static const int Cryptography_EVP_CTRL_GCM_SET_TAG;
"""
FUNCTIONS = """
@@ -95,3 +95,15 @@ int EVP_PKEY_assign_DSA(EVP_PKEY *, DSA *);
int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *);
int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *, int, int, void *);
"""
+
+CUSTOMIZATIONS = """
+#ifdef EVP_CTRL_GCM_SET_TAG
+const int Cryptography_EVP_CTRL_GCM_GET_TAG = EVP_CTRL_GCM_GET_TAG;
+const int Cryptography_EVP_CTRL_GCM_SET_TAG = EVP_CTRL_GCM_SET_TAG;
+const int Cryptography_EVP_CTRL_GCM_SET_IVLEN = EVP_CTRL_GCM_SET_IVLEN;
+#else
+const int Cryptography_EVP_CTRL_GCM_GET_TAG = -1;
+const int Cryptography_EVP_CTRL_GCM_SET_TAG = -1;
+const int Cryptography_EVP_CTRL_GCM_SET_IVLEN = -1;
+#endif
+"""
diff --git a/cryptography/hazmat/bindings/openssl/hmac.py b/cryptography/hazmat/bindings/openssl/hmac.py
index e97ac35e..10e67141 100644
--- a/cryptography/hazmat/bindings/openssl/hmac.py
+++ b/cryptography/hazmat/bindings/openssl/hmac.py
@@ -22,11 +22,69 @@ typedef struct { ...; } HMAC_CTX;
FUNCTIONS = """
void HMAC_CTX_init(HMAC_CTX *);
void HMAC_CTX_cleanup(HMAC_CTX *);
-int HMAC_Init_ex(HMAC_CTX *, const void *, int, const EVP_MD *, ENGINE *);
-int HMAC_Update(HMAC_CTX *, const unsigned char *, size_t);
-int HMAC_Final(HMAC_CTX *, unsigned char *, unsigned int *);
-int HMAC_CTX_copy(HMAC_CTX *, HMAC_CTX *);
+
+int Cryptography_HMAC_Init_ex(HMAC_CTX *, const void *, int, const EVP_MD *,
+ ENGINE *);
+int Cryptography_HMAC_Update(HMAC_CTX *, const unsigned char *, size_t);
+int Cryptography_HMAC_Final(HMAC_CTX *, unsigned char *, unsigned int *);
+int Cryptography_HMAC_CTX_copy(HMAC_CTX *, HMAC_CTX *);
"""
MACROS = """
"""
+
+CUSTOMIZATIONS = """
+int Cryptography_HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int key_len,
+ const EVP_MD *md, ENGINE *impl) {
+#if OPENSSL_VERSION_NUMBER >= 0x010000000
+ return HMAC_Init_ex(ctx, key, key_len, md, impl);
+#else
+ HMAC_Init_ex(ctx, key, key_len, md, impl);
+ return 1;
+#endif
+}
+
+int Cryptography_HMAC_Update(HMAC_CTX *ctx, const unsigned char *data,
+ size_t data_len) {
+#if OPENSSL_VERSION_NUMBER >= 0x010000000
+ return HMAC_Update(ctx, data, data_len);
+#else
+ HMAC_Update(ctx, data, data_len);
+ return 1;
+#endif
+}
+
+int Cryptography_HMAC_Final(HMAC_CTX *ctx, unsigned char *digest,
+ unsigned int *digest_len) {
+#if OPENSSL_VERSION_NUMBER >= 0x010000000
+ return HMAC_Final(ctx, digest, digest_len);
+#else
+ HMAC_Final(ctx, digest, digest_len);
+ return 1;
+#endif
+}
+
+int Cryptography_HMAC_CTX_copy(HMAC_CTX *dst_ctx, HMAC_CTX *src_ctx) {
+#if OPENSSL_VERSION_NUMBER >= 0x010000000
+ return HMAC_CTX_copy(dst_ctx, src_ctx);
+#else
+ HMAC_CTX_init(dst_ctx);
+ if (!EVP_MD_CTX_copy_ex(&dst_ctx->i_ctx, &src_ctx->i_ctx)) {
+ goto err;
+ }
+ if (!EVP_MD_CTX_copy_ex(&dst_ctx->o_ctx, &src_ctx->o_ctx)) {
+ goto err;
+ }
+ if (!EVP_MD_CTX_copy_ex(&dst_ctx->md_ctx, &src_ctx->md_ctx)) {
+ goto err;
+ }
+ memcpy(dst_ctx->key, src_ctx->key, HMAC_MAX_MD_CBLOCK);
+ dst_ctx->key_length = src_ctx->key_length;
+ dst_ctx->md = src_ctx->md;
+ return 1;
+
+ err:
+ return 0;
+#endif
+}
+"""
diff --git a/cryptography/hazmat/bindings/openssl/nid.py b/cryptography/hazmat/bindings/openssl/nid.py
index 0f5b0003..9816dde4 100644
--- a/cryptography/hazmat/bindings/openssl/nid.py
+++ b/cryptography/hazmat/bindings/openssl/nid.py
@@ -39,6 +39,11 @@ static const int NID_crl_reason;
static const int NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
"""
-FUNCTIONS = ""
+FUNCTIONS = """
+"""
+
+MACROS = """
+"""
-MACROS = ""
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/opensslv.py b/cryptography/hazmat/bindings/openssl/opensslv.py
index d1a1b3e6..d463776c 100644
--- a/cryptography/hazmat/bindings/openssl/opensslv.py
+++ b/cryptography/hazmat/bindings/openssl/opensslv.py
@@ -24,3 +24,6 @@ FUNCTIONS = """
MACROS = """
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/pem.py b/cryptography/hazmat/bindings/openssl/pem.py
index 8c8f736d..00f0dc36 100644
--- a/cryptography/hazmat/bindings/openssl/pem.py
+++ b/cryptography/hazmat/bindings/openssl/pem.py
@@ -41,4 +41,8 @@ PKCS7 *PEM_read_bio_PKCS7(BIO *, PKCS7 **, pem_password_cb *, void *);
DH *PEM_read_bio_DHparams(BIO *, DH **, pem_password_cb *, void *);
"""
-MACROS = ""
+MACROS = """
+"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/pkcs12.py b/cryptography/hazmat/bindings/openssl/pkcs12.py
index 5c002b93..d91d100f 100644
--- a/cryptography/hazmat/bindings/openssl/pkcs12.py
+++ b/cryptography/hazmat/bindings/openssl/pkcs12.py
@@ -32,3 +32,6 @@ int PKCS12_parse(PKCS12 *, const char *, EVP_PKEY **, X509 **,
PKCS12 *PKCS12_create(char *, char *, EVP_PKEY *, X509 *,
struct stack_st_X509 *, int, int, int, int, int);
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/pkcs7.py b/cryptography/hazmat/bindings/openssl/pkcs7.py
index 752bfa00..60ea3c52 100644
--- a/cryptography/hazmat/bindings/openssl/pkcs7.py
+++ b/cryptography/hazmat/bindings/openssl/pkcs7.py
@@ -32,3 +32,6 @@ int PKCS7_type_is_enveloped(PKCS7 *);
int PKCS7_type_is_signedAndEnveloped(PKCS7 *);
int PKCS7_type_is_data(PKCS7 *);
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/rand.py b/cryptography/hazmat/bindings/openssl/rand.py
index e4f6be23..848ee05a 100644
--- a/cryptography/hazmat/bindings/openssl/rand.py
+++ b/cryptography/hazmat/bindings/openssl/rand.py
@@ -35,3 +35,6 @@ int RAND_pseudo_bytes(unsigned char *, int);
MACROS = """
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/rsa.py b/cryptography/hazmat/bindings/openssl/rsa.py
index c8bf1cc0..21ed5d67 100644
--- a/cryptography/hazmat/bindings/openssl/rsa.py
+++ b/cryptography/hazmat/bindings/openssl/rsa.py
@@ -29,3 +29,6 @@ int RSA_check_key(const RSA *);
MACROS = """
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/ssl.py b/cryptography/hazmat/bindings/openssl/ssl.py
index 8aca86e4..58a64f0b 100644
--- a/cryptography/hazmat/bindings/openssl/ssl.py
+++ b/cryptography/hazmat/bindings/openssl/ssl.py
@@ -24,3 +24,6 @@ void SSL_load_error_strings();
MACROS = """
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/x509.py b/cryptography/hazmat/bindings/openssl/x509.py
index 9a51a6d0..b2ee672e 100644
--- a/cryptography/hazmat/bindings/openssl/x509.py
+++ b/cryptography/hazmat/bindings/openssl/x509.py
@@ -185,3 +185,6 @@ X509_REVOKED *sk_X509_REVOKED_value(struct x509_revoked_st *, int);
int X509_CRL_set_lastUpdate(X509_CRL *, const ASN1_TIME *);
int X509_CRL_set_nextUpdate(X509_CRL *, const ASN1_TIME *);
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/x509name.py b/cryptography/hazmat/bindings/openssl/x509name.py
index bd7abe2d..896f0ae4 100644
--- a/cryptography/hazmat/bindings/openssl/x509name.py
+++ b/cryptography/hazmat/bindings/openssl/x509name.py
@@ -46,3 +46,6 @@ int sk_X509_NAME_push(struct stack_st_X509_NAME *, X509_NAME *);
X509_NAME *sk_X509_NAME_value(struct stack_st_X509_NAME *, int);
void sk_X509_NAME_free(struct stack_st_X509_NAME *);
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/bindings/openssl/x509v3.py b/cryptography/hazmat/bindings/openssl/x509v3.py
index 413bde5f..bc26236c 100644
--- a/cryptography/hazmat/bindings/openssl/x509v3.py
+++ b/cryptography/hazmat/bindings/openssl/x509v3.py
@@ -92,3 +92,6 @@ GENERAL_NAME *sk_GENERAL_NAME_value(struct stack_st_GENERAL_NAME *, int);
const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *);
const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int);
"""
+
+CUSTOMIZATIONS = """
+"""
diff --git a/cryptography/hazmat/primitives/block/__init__.py b/cryptography/hazmat/primitives/ciphers/__init__.py
index 5b8942b6..e5a8ca52 100644
--- a/cryptography/hazmat/primitives/block/__init__.py
+++ b/cryptography/hazmat/primitives/ciphers/__init__.py
@@ -13,9 +13,9 @@
from __future__ import absolute_import, division, print_function
-from cryptography.hazmat.primitives.block.base import BlockCipher
+from cryptography.hazmat.primitives.ciphers.base import Cipher
__all__ = [
- "BlockCipher",
+ "Cipher",
]
diff --git a/cryptography/hazmat/primitives/block/ciphers.py b/cryptography/hazmat/primitives/ciphers/algorithms.py
index 8046bd26..8046bd26 100644
--- a/cryptography/hazmat/primitives/block/ciphers.py
+++ b/cryptography/hazmat/primitives/ciphers/algorithms.py
diff --git a/cryptography/hazmat/primitives/block/base.py b/cryptography/hazmat/primitives/ciphers/base.py
index ece3b32d..1599308c 100644
--- a/cryptography/hazmat/primitives/block/base.py
+++ b/cryptography/hazmat/primitives/ciphers/base.py
@@ -16,26 +16,28 @@ from __future__ import absolute_import, division, print_function
from cryptography.hazmat.primitives import interfaces
-class BlockCipher(object):
- def __init__(self, cipher, mode, backend=None):
- super(BlockCipher, self).__init__()
+class Cipher(object):
+ def __init__(self, algorithm, mode, backend=None):
+ super(Cipher, self).__init__()
if backend is None:
from cryptography.hazmat.bindings import (
_default_backend as backend,
)
- self.cipher = cipher
+ self.algorithm = algorithm
self.mode = mode
self._backend = backend
def encryptor(self):
return _CipherContext(
- self._backend.ciphers.create_encrypt_ctx(self.cipher, self.mode))
+ self._backend.ciphers.create_encrypt_ctx(self.algorithm,
+ self.mode))
def decryptor(self):
return _CipherContext(
- self._backend.ciphers.create_decrypt_ctx(self.cipher, self.mode))
+ self._backend.ciphers.create_decrypt_ctx(self.algorithm,
+ self.mode))
@interfaces.register(interfaces.CipherContext)
diff --git a/cryptography/hazmat/primitives/block/modes.py b/cryptography/hazmat/primitives/ciphers/modes.py
index a60e8a34..e54872a6 100644
--- a/cryptography/hazmat/primitives/block/modes.py
+++ b/cryptography/hazmat/primitives/ciphers/modes.py
@@ -16,6 +16,7 @@ from __future__ import absolute_import, division, print_function
from cryptography.hazmat.primitives import interfaces
+@interfaces.register(interfaces.Mode)
@interfaces.register(interfaces.ModeWithInitializationVector)
class CBC(object):
name = "CBC"
@@ -25,10 +26,12 @@ class CBC(object):
self.initialization_vector = initialization_vector
+@interfaces.register(interfaces.Mode)
class ECB(object):
name = "ECB"
+@interfaces.register(interfaces.Mode)
@interfaces.register(interfaces.ModeWithInitializationVector)
class OFB(object):
name = "OFB"
@@ -38,6 +41,7 @@ class OFB(object):
self.initialization_vector = initialization_vector
+@interfaces.register(interfaces.Mode)
@interfaces.register(interfaces.ModeWithInitializationVector)
class CFB(object):
name = "CFB"
@@ -47,6 +51,7 @@ class CFB(object):
self.initialization_vector = initialization_vector
+@interfaces.register(interfaces.Mode)
@interfaces.register(interfaces.ModeWithNonce)
class CTR(object):
name = "CTR"
diff --git a/cryptography/hazmat/primitives/interfaces.py b/cryptography/hazmat/primitives/interfaces.py
index ebf5e31e..67dbe6fa 100644
--- a/cryptography/hazmat/primitives/interfaces.py
+++ b/cryptography/hazmat/primitives/interfaces.py
@@ -25,12 +25,28 @@ def register(iface):
return register_decorator
+class Mode(six.with_metaclass(abc.ABCMeta)):
+ @abc.abstractproperty
+ def name(self):
+ """
+ A string naming this mode. (e.g. ECB, CBC)
+ """
+
+
class ModeWithInitializationVector(six.with_metaclass(abc.ABCMeta)):
- pass
+ @abc.abstractproperty
+ def initialization_vector(self):
+ """
+ The value of the initialization vector for this mode as bytes.
+ """
class ModeWithNonce(six.with_metaclass(abc.ABCMeta)):
- pass
+ @abc.abstractproperty
+ def nonce(self):
+ """
+ The value of the nonce for this mode as bytes.
+ """
class CipherContext(six.with_metaclass(abc.ABCMeta)):
@@ -65,7 +81,7 @@ class HashAlgorithm(six.with_metaclass(abc.ABCMeta)):
@abc.abstractproperty
def name(self):
"""
- A string naming this algorithm. (ex. sha256, md5)
+ A string naming this algorithm. (e.g. sha256, md5)
"""
@abc.abstractproperty
diff --git a/docs/community.rst b/docs/community.rst
index 552318da..bf1cd1c7 100644
--- a/docs/community.rst
+++ b/docs/community.rst
@@ -9,7 +9,12 @@ You can find ``cryptography`` all over the web:
* `Documentation`_
* IRC: ``#cryptography-dev`` on ``irc.freenode.net``
+Wherever we interact, we strive to follow the `Python Community Code of
+Conduct`_.
+
+
.. _`Mailing list`: https://mail.python.org/mailman/listinfo/cryptography-dev
.. _`Source code`: https://github.com/pyca/cryptography
.. _`Issue tracker`: https://github.com/pyca/cryptography/issues
.. _`Documentation`: https://cryptography.io/
+.. _`Python Community Code of Conduct`: http://www.python.org/psf/codeofconduct/
diff --git a/docs/conf.py b/docs/conf.py
index 8e0fc7be..69be32e9 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -252,7 +252,3 @@ texinfo_documents = [
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'http://docs.python.org/': None}
-
-
-# Enable the new ReadTheDocs theme
-RTD_NEW_THEME = True
diff --git a/docs/contributing.rst b/docs/contributing.rst
index e1475b88..3b301842 100644
--- a/docs/contributing.rst
+++ b/docs/contributing.rst
@@ -206,4 +206,4 @@ The HTML documentation index can now be found at ``docs/_build/html/index.html``
.. _`virtualenv`: https://pypi.python.org/pypi/virtualenv
.. _`pip`: https://pypi.python.org/pypi/pip
.. _`sphinx`: https://pypi.python.org/pypi/sphinx
-.. _`reStructured Text`: http://docutils.sourceforge.net/rst.html
+.. _`reStructured Text`: http://sphinx-doc.org/rest.html
diff --git a/docs/exceptions.rst b/docs/exceptions.rst
new file mode 100644
index 00000000..6ac11b3c
--- /dev/null
+++ b/docs/exceptions.rst
@@ -0,0 +1,9 @@
+Exceptions
+==========
+
+.. currentmodule:: cryptography.exceptions
+
+.. class:: UnsupportedAlgorithm
+
+ This is raised when a backend doesn't support the requested algorithm (or
+ combination of algorithms).
diff --git a/docs/glossary.rst b/docs/glossary.rst
new file mode 100644
index 00000000..e4fc8283
--- /dev/null
+++ b/docs/glossary.rst
@@ -0,0 +1,30 @@
+Glossary
+========
+
+.. glossary::
+
+ plaintext
+ User-readable data you care about.
+
+ ciphertext
+ The encoded data, it's not user readable. Potential attackers are able
+ to see this.
+
+ encryption
+ The process of converting plaintext to ciphertext.
+
+ decryption
+ The process of converting ciphertext to plaintext.
+
+ key
+ Secret data is encoded with a function using this key. Sometimes
+ multiple keys are used. These **must** be kept secret, if a key is
+ exposed to an attacker, any data encrypted with it will be exposed.
+
+ symmetric cryptography
+ Cryptographic operations where encryption and decryption use the same
+ key.
+
+ asymmetric cryptography
+ Cryptographic operations where encryption and decryption use different
+ keys. There are seperate encryption and decryption keys.
diff --git a/docs/hazmat/primitives/hmac.rst b/docs/hazmat/primitives/hmac.rst
index 301d72d5..bd1a4934 100644
--- a/docs/hazmat/primitives/hmac.rst
+++ b/docs/hazmat/primitives/hmac.rst
@@ -23,6 +23,8 @@ message.
equal in length to the ``digest_size`` of the hash function chosen.
You must keep the ``key`` secret.
+ This is an implementation of :rfc:`2104`.
+
.. doctest::
>>> from cryptography.hazmat.primitives import hashes, hmac
diff --git a/docs/hazmat/primitives/index.rst b/docs/hazmat/primitives/index.rst
index c81018ae..614c414a 100644
--- a/docs/hazmat/primitives/index.rst
+++ b/docs/hazmat/primitives/index.rst
@@ -10,3 +10,4 @@ Primitives
hmac
symmetric-encryption
padding
+ interfaces
diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst
new file mode 100644
index 00000000..7068316e
--- /dev/null
+++ b/docs/hazmat/primitives/interfaces.rst
@@ -0,0 +1,59 @@
+.. hazmat::
+
+Interfaces
+==========
+
+
+``cryptography`` uses `Abstract Base Classes`_ as interfaces to describe the
+properties and methods of most primitive constructs. Backends may also use
+this information to influence their operation. Interfaces should also be used
+to document argument and return types.
+
+.. _`Abstract Base Classes`: http://docs.python.org/3.2/library/abc.html
+
+
+Cipher Modes
+~~~~~~~~~~~~
+
+.. currentmodule:: cryptography.hazmat.primitives.interfaces
+
+Interfaces used by the symmetric cipher modes described in
+:ref:`Symmetric Encryption Modes <symmetric-encryption-modes>`.
+
+.. class:: Mode
+
+ A named cipher mode.
+
+ .. attribute:: name
+
+ :type: str
+
+ This should be the standard shorthand name for the mode, for example
+ Cipher-Block Chaining mode is "CBC".
+
+ The name may be used by a backend to influence the operation of a
+ cipher in conjunction with the algorithm's name.
+
+
+.. class:: ModeWithInitializationVector
+
+ A cipher mode with an initialization vector.
+
+ .. attribute:: initialization_vector
+
+ :type: bytes
+
+ Exact requirements of the initialization are described by the
+ documentation of individual modes.
+
+
+.. class:: ModeWithNonce
+
+ A cipher mode with a nonce.
+
+ .. attribute:: nonce
+
+ :type: bytes
+
+ Exact requirements of the nonce are described by the documentation of
+ individual modes.
diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst
index 5852dc21..5f1a64a1 100644
--- a/docs/hazmat/primitives/symmetric-encryption.rst
+++ b/docs/hazmat/primitives/symmetric-encryption.rst
@@ -4,7 +4,7 @@
Symmetric Encryption
====================
-.. currentmodule:: cryptography.hazmat.primitives.block
+.. currentmodule:: cryptography.hazmat.primitives.ciphers
.. testsetup::
@@ -16,24 +16,23 @@ Symmetric Encryption
Symmetric encryption is a way to encrypt (hide the plaintext value) material
where the encrypter and decrypter both use the same key.
-.. class:: BlockCipher(cipher, mode)
+.. class:: Cipher(algorithm, mode)
- Block ciphers work by encrypting content in chunks, often 64- or 128-bits.
- They combine an underlying algorithm (such as AES), with a mode (such as
+ Cipher objects combine an algorithm (such as AES) with a mode (such as
CBC, CTR, or GCM). A simple example of encrypting (and then decrypting)
content with AES is:
.. doctest::
- >>> from cryptography.hazmat.primitives.block import BlockCipher, ciphers, modes
- >>> cipher = BlockCipher(ciphers.AES(key), modes.CBC(iv))
+ >>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
+ >>> cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
>>> encryptor = cipher.encryptor()
>>> ct = encryptor.update(b"a secret message") + encryptor.finalize()
>>> decryptor = cipher.decryptor()
>>> decryptor.update(ct) + decryptor.finalize()
'a secret message'
- :param cipher: One of the ciphers described below.
+ :param algorithms: One of the algorithms described below.
:param mode: One of the modes described below.
.. method:: encryptor()
@@ -42,17 +41,26 @@ where the encrypter and decrypter both use the same key.
:class:`~cryptography.hazmat.primitives.interfaces.CipherContext`
provider.
+ If the backend doesn't support the requested combination of ``cipher``
+ and ``mode`` an :class:`cryptography.exceptions.UnsupportedAlgorithm`
+ will be raised.
+
.. method:: decryptor()
:return: A decrypting
:class:`~cryptography.hazmat.primitives.interfaces.CipherContext`
provider.
+ If the backend doesn't support the requested combination of ``cipher``
+ and ``mode`` an :class:`cryptography.exceptions.UnsupportedAlgorithm`
+ will be raised.
+
+
.. currentmodule:: cryptography.hazmat.primitives.interfaces
.. class:: CipherContext
- When calling ``encryptor()`` or ``decryptor()`` on a ``BlockCipher`` object
+ When calling ``encryptor()`` or ``decryptor()`` on a ``Cipher`` object
you will receive a return object conforming to the ``CipherContext``
interface. You can then call ``update(data)`` with data until you have fed
everything into the context. Once that is done call ``finalize()`` to
@@ -63,14 +71,20 @@ where the encrypter and decrypter both use the same key.
:param bytes data: The data you wish to pass into the context.
:return bytes: Returns the data that was encrypted or decrypted.
+ When the ``Cipher`` was constructed in a mode that turns it into a
+ stream cipher (e.g.
+ :class:`cryptography.hazmat.primitives.ciphers.modes.CTR`), this will
+ return bytes immediately, however in other modes it will return chunks,
+ whose size is determined by the cipher's block size.
+
.. method:: finalize()
:return bytes: Returns the remainder of the data.
-Ciphers
-~~~~~~~
+Algorithms
+~~~~~~~~~~
-.. currentmodule:: cryptography.hazmat.primitives.block.ciphers
+.. currentmodule:: cryptography.hazmat.primitives.ciphers.algorithms
.. class:: AES(key)
@@ -135,10 +149,13 @@ Weak Ciphers
:param bytes key: The secret key, 32-448 bits in length (in increments of
8). This must be kept secret.
+
+.. _symmetric-encryption-modes:
+
Modes
~~~~~
-.. currentmodule:: cryptography.hazmat.primitives.block.modes
+.. currentmodule:: cryptography.hazmat.primitives.ciphers.modes
.. class:: CBC(initialization_vector)
@@ -149,9 +166,29 @@ Modes
to be kept secret (they can be included
in a transmitted message). Must be the
same number of bytes as the
- ``block_size`` of the cipher. Do not
- reuse an ``initialization_vector`` with
- a given ``key``.
+ ``block_size`` of the cipher. Each time
+ something is encrypted a new
+ ``initialization_vector`` should be
+ generated. Do not reuse an
+ ``initialization_vector`` with
+ a given ``key``, and particularly do
+ not use a constant
+ ``initialization_vector``.
+
+ A good construction looks like:
+
+ .. code-block:: pycon
+
+ >>> import os
+ >>> iv = os.urandom(16)
+ >>> mode = CBC(iv)
+
+ While the following is bad and will leak information:
+
+ .. code-block:: pycon
+
+ >>> iv = "a" * 16
+ >>> mode = CBC(iv)
.. class:: CTR(nonce)
@@ -162,7 +199,8 @@ Modes
block size of less than 128-bits.
CTR (Counter) is a mode of operation for block ciphers. It is considered
- cryptographically strong.
+ cryptographically strong. It transforms a block cipher into a stream
+ cipher.
:param bytes nonce: Should be random bytes. It is critical to never reuse a
``nonce`` with a given key. Any reuse of a nonce
diff --git a/docs/index.rst b/docs/index.rst
index b9c5b5fb..b9bf1735 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -32,6 +32,8 @@ Contents
fernet
architecture
+ exceptions
+ glossary
contributing
security
community
diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py
index 9ce882e4..f1493e8d 100644
--- a/tests/hazmat/bindings/test_openssl.py
+++ b/tests/hazmat/bindings/test_openssl.py
@@ -13,9 +13,19 @@
import pytest
-from cryptography.hazmat.bindings.openssl.backend import backend
-from cryptography.hazmat.primitives.block.ciphers import AES
-from cryptography.hazmat.primitives.block.modes import CBC
+from cryptography.exceptions import UnsupportedAlgorithm
+from cryptography.hazmat.bindings.openssl.backend import backend, Backend
+from cryptography.hazmat.primitives.ciphers import Cipher
+from cryptography.hazmat.primitives.ciphers.algorithms import AES
+from cryptography.hazmat.primitives.ciphers.modes import CBC
+
+
+class FakeMode(object):
+ pass
+
+
+class FakeCipher(object):
+ pass
class TestOpenSSL(object):
@@ -39,3 +49,21 @@ class TestOpenSSL(object):
def test_register_duplicate_cipher_adapter(self):
with pytest.raises(ValueError):
backend.ciphers.register_cipher_adapter(AES, CBC, None)
+
+ def test_instances_share_ffi(self):
+ b = Backend()
+ assert b.ffi is backend.ffi
+ assert b.lib is backend.lib
+
+ def test_nonexistent_cipher(self):
+ b = Backend()
+ b.ciphers.register_cipher_adapter(
+ FakeCipher,
+ FakeMode,
+ lambda backend, cipher, mode: backend.ffi.NULL
+ )
+ cipher = Cipher(
+ FakeCipher(), FakeMode(), backend=b,
+ )
+ with pytest.raises(UnsupportedAlgorithm):
+ cipher.encryptor()
diff --git a/tests/hazmat/primitives/test_3des.py b/tests/hazmat/primitives/test_3des.py
index 6b3e0414..af6bdc04 100644
--- a/tests/hazmat/primitives/test_3des.py
+++ b/tests/hazmat/primitives/test_3des.py
@@ -20,7 +20,7 @@ from __future__ import absolute_import, division, print_function
import binascii
import os
-from cryptography.hazmat.primitives.block import ciphers, modes
+from cryptography.hazmat.primitives.ciphers import algorithms, modes
from .utils import generate_encrypt_test
from ...utils import load_nist_vectors_from_file
@@ -37,7 +37,7 @@ class TestTripleDES_CBC(object):
"TCBCvarkey.rsp",
"TCBCvartext.rsp",
],
- lambda keys, iv: ciphers.TripleDES(binascii.unhexlify(keys)),
+ lambda keys, iv: algorithms.TripleDES(binascii.unhexlify(keys)),
lambda keys, iv: modes.CBC(binascii.unhexlify(iv)),
)
@@ -50,7 +50,7 @@ class TestTripleDES_CBC(object):
"TCBCMMT3.rsp",
],
lambda key1, key2, key3, iv: (
- ciphers.TripleDES(binascii.unhexlify(key1 + key2 + key3))
+ algorithms.TripleDES(binascii.unhexlify(key1 + key2 + key3))
),
lambda key1, key2, key3, iv: modes.CBC(binascii.unhexlify(iv)),
)
@@ -67,7 +67,7 @@ class TestTripleDES_OFB(object):
"TOFBvartext.rsp",
"TOFBinvperm.rsp",
],
- lambda keys, iv: ciphers.TripleDES(binascii.unhexlify(keys)),
+ lambda keys, iv: algorithms.TripleDES(binascii.unhexlify(keys)),
lambda keys, iv: modes.OFB(binascii.unhexlify(iv)),
)
@@ -80,7 +80,7 @@ class TestTripleDES_OFB(object):
"TOFBMMT3.rsp",
],
lambda key1, key2, key3, iv: (
- ciphers.TripleDES(binascii.unhexlify(key1 + key2 + key3))
+ algorithms.TripleDES(binascii.unhexlify(key1 + key2 + key3))
),
lambda key1, key2, key3, iv: modes.OFB(binascii.unhexlify(iv)),
)
@@ -97,7 +97,7 @@ class TestTripleDES_CFB(object):
"TCFB64varkey.rsp",
"TCFB64vartext.rsp",
],
- lambda keys, iv: ciphers.TripleDES(binascii.unhexlify(keys)),
+ lambda keys, iv: algorithms.TripleDES(binascii.unhexlify(keys)),
lambda keys, iv: modes.CFB(binascii.unhexlify(iv)),
)
@@ -110,7 +110,7 @@ class TestTripleDES_CFB(object):
"TCFB64MMT3.rsp",
],
lambda key1, key2, key3, iv: (
- ciphers.TripleDES(binascii.unhexlify(key1 + key2 + key3))
+ algorithms.TripleDES(binascii.unhexlify(key1 + key2 + key3))
),
lambda key1, key2, key3, iv: modes.CFB(binascii.unhexlify(iv)),
)
diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py
index 192da648..66471fac 100644
--- a/tests/hazmat/primitives/test_aes.py
+++ b/tests/hazmat/primitives/test_aes.py
@@ -16,7 +16,7 @@ from __future__ import absolute_import, division, print_function
import binascii
import os
-from cryptography.hazmat.primitives.block import ciphers, modes
+from cryptography.hazmat.primitives.ciphers import algorithms, modes
from .utils import generate_encrypt_test
from ...utils import (
@@ -45,7 +45,7 @@ class TestAES(object):
"CBCMMT192.rsp",
"CBCMMT256.rsp",
],
- lambda key, iv: ciphers.AES(binascii.unhexlify(key)),
+ lambda key, iv: algorithms.AES(binascii.unhexlify(key)),
lambda key, iv: modes.CBC(binascii.unhexlify(iv)),
)
@@ -69,7 +69,7 @@ class TestAES(object):
"ECBMMT192.rsp",
"ECBMMT256.rsp",
],
- lambda key: ciphers.AES(binascii.unhexlify(key)),
+ lambda key: algorithms.AES(binascii.unhexlify(key)),
lambda key: modes.ECB(),
)
@@ -93,7 +93,7 @@ class TestAES(object):
"OFBMMT192.rsp",
"OFBMMT256.rsp",
],
- lambda key, iv: ciphers.AES(binascii.unhexlify(key)),
+ lambda key, iv: algorithms.AES(binascii.unhexlify(key)),
lambda key, iv: modes.OFB(binascii.unhexlify(iv)),
)
@@ -117,7 +117,7 @@ class TestAES(object):
"CFB128MMT192.rsp",
"CFB128MMT256.rsp",
],
- lambda key, iv: ciphers.AES(binascii.unhexlify(key)),
+ lambda key, iv: algorithms.AES(binascii.unhexlify(key)),
lambda key, iv: modes.CFB(binascii.unhexlify(iv)),
)
@@ -125,10 +125,10 @@ class TestAES(object):
load_openssl_vectors_from_file,
os.path.join("ciphers", "AES", "CTR"),
["aes-128-ctr.txt", "aes-192-ctr.txt", "aes-256-ctr.txt"],
- lambda key, iv: ciphers.AES(binascii.unhexlify(key)),
+ lambda key, iv: algorithms.AES(binascii.unhexlify(key)),
lambda key, iv: modes.CTR(binascii.unhexlify(iv)),
only_if=lambda backend: backend.ciphers.supported(
- ciphers.AES("\x00" * 16), modes.CTR("\x00" * 16)
+ algorithms.AES("\x00" * 16), modes.CTR("\x00" * 16)
),
skip_message="Does not support AES CTR",
)
diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py
index e0ed6697..28f34478 100644
--- a/tests/hazmat/primitives/test_block.py
+++ b/tests/hazmat/primitives/test_block.py
@@ -17,36 +17,39 @@ import binascii
import pytest
+from cryptography.exceptions import UnsupportedAlgorithm
from cryptography.hazmat.primitives import interfaces
-from cryptography.hazmat.primitives.block import BlockCipher, ciphers, modes
+from cryptography.hazmat.primitives.ciphers import (
+ Cipher, algorithms, modes
+)
-class TestBlockCipher(object):
+class TestCipher(object):
def test_instantiate_without_backend(self):
- BlockCipher(
- ciphers.AES(binascii.unhexlify(b"0" * 32)),
+ Cipher(
+ algorithms.AES(binascii.unhexlify(b"0" * 32)),
modes.CBC(binascii.unhexlify(b"0" * 32))
)
def test_creates_encryptor(self):
- cipher = BlockCipher(
- ciphers.AES(binascii.unhexlify(b"0" * 32)),
+ cipher = Cipher(
+ algorithms.AES(binascii.unhexlify(b"0" * 32)),
modes.CBC(binascii.unhexlify(b"0" * 32))
)
assert isinstance(cipher.encryptor(), interfaces.CipherContext)
def test_creates_decryptor(self):
- cipher = BlockCipher(
- ciphers.AES(binascii.unhexlify(b"0" * 32)),
+ cipher = Cipher(
+ algorithms.AES(binascii.unhexlify(b"0" * 32)),
modes.CBC(binascii.unhexlify(b"0" * 32))
)
assert isinstance(cipher.decryptor(), interfaces.CipherContext)
-class TestBlockCipherContext(object):
+class TestCipherContext(object):
def test_use_after_finalize(self, backend):
- cipher = BlockCipher(
- ciphers.AES(binascii.unhexlify(b"0" * 32)),
+ cipher = Cipher(
+ algorithms.AES(binascii.unhexlify(b"0" * 32)),
modes.CBC(binascii.unhexlify(b"0" * 32)),
backend
)
@@ -66,8 +69,8 @@ class TestBlockCipherContext(object):
decryptor.finalize()
def test_unaligned_block_encryption(self, backend):
- cipher = BlockCipher(
- ciphers.AES(binascii.unhexlify(b"0" * 32)),
+ cipher = Cipher(
+ algorithms.AES(binascii.unhexlify(b"0" * 32)),
modes.ECB(),
backend
)
@@ -84,3 +87,13 @@ class TestBlockCipherContext(object):
assert len(pt) == 80
assert pt == b"a" * 80
decryptor.finalize()
+
+ def test_nonexistent_cipher(self, backend):
+ cipher = Cipher(
+ object(), object(), backend
+ )
+ with pytest.raises(UnsupportedAlgorithm):
+ cipher.encryptor()
+
+ with pytest.raises(UnsupportedAlgorithm):
+ cipher.decryptor()
diff --git a/tests/hazmat/primitives/test_blowfish.py b/tests/hazmat/primitives/test_blowfish.py
index cd5e03a4..a7f13823 100644
--- a/tests/hazmat/primitives/test_blowfish.py
+++ b/tests/hazmat/primitives/test_blowfish.py
@@ -16,7 +16,7 @@ from __future__ import absolute_import, division, print_function
import binascii
import os
-from cryptography.hazmat.primitives.block import ciphers, modes
+from cryptography.hazmat.primitives.ciphers import algorithms, modes
from .utils import generate_encrypt_test
from ...utils import load_nist_vectors_from_file
@@ -27,10 +27,10 @@ class TestBlowfish(object):
lambda path: load_nist_vectors_from_file(path, "ENCRYPT"),
os.path.join("ciphers", "Blowfish"),
["bf-ecb.txt"],
- lambda key: ciphers.Blowfish(binascii.unhexlify(key)),
+ lambda key: algorithms.Blowfish(binascii.unhexlify(key)),
lambda key: modes.ECB(),
only_if=lambda backend: backend.ciphers.supported(
- ciphers.Blowfish("\x00" * 56), modes.ECB()
+ algorithms.Blowfish("\x00" * 56), modes.ECB()
),
skip_message="Does not support Blowfish ECB",
)
@@ -39,10 +39,10 @@ class TestBlowfish(object):
lambda path: load_nist_vectors_from_file(path, "ENCRYPT"),
os.path.join("ciphers", "Blowfish"),
["bf-cbc.txt"],
- lambda key, iv: ciphers.Blowfish(binascii.unhexlify(key)),
+ lambda key, iv: algorithms.Blowfish(binascii.unhexlify(key)),
lambda key, iv: modes.CBC(binascii.unhexlify(iv)),
only_if=lambda backend: backend.ciphers.supported(
- ciphers.Blowfish("\x00" * 56), modes.CBC("\x00" * 8)
+ algorithms.Blowfish("\x00" * 56), modes.CBC("\x00" * 8)
),
skip_message="Does not support Blowfish CBC",
)
@@ -51,10 +51,10 @@ class TestBlowfish(object):
lambda path: load_nist_vectors_from_file(path, "ENCRYPT"),
os.path.join("ciphers", "Blowfish"),
["bf-ofb.txt"],
- lambda key, iv: ciphers.Blowfish(binascii.unhexlify(key)),
+ lambda key, iv: algorithms.Blowfish(binascii.unhexlify(key)),
lambda key, iv: modes.OFB(binascii.unhexlify(iv)),
only_if=lambda backend: backend.ciphers.supported(
- ciphers.Blowfish("\x00" * 56), modes.OFB("\x00" * 8)
+ algorithms.Blowfish("\x00" * 56), modes.OFB("\x00" * 8)
),
skip_message="Does not support Blowfish OFB",
)
@@ -63,10 +63,10 @@ class TestBlowfish(object):
lambda path: load_nist_vectors_from_file(path, "ENCRYPT"),
os.path.join("ciphers", "Blowfish"),
["bf-cfb.txt"],
- lambda key, iv: ciphers.Blowfish(binascii.unhexlify(key)),
+ lambda key, iv: algorithms.Blowfish(binascii.unhexlify(key)),
lambda key, iv: modes.CFB(binascii.unhexlify(iv)),
only_if=lambda backend: backend.ciphers.supported(
- ciphers.Blowfish("\x00" * 56), modes.CFB("\x00" * 8)
+ algorithms.Blowfish("\x00" * 56), modes.CFB("\x00" * 8)
),
skip_message="Does not support Blowfish CFB",
)
diff --git a/tests/hazmat/primitives/test_camellia.py b/tests/hazmat/primitives/test_camellia.py
index 605c18d5..e1be5d1d 100644
--- a/tests/hazmat/primitives/test_camellia.py
+++ b/tests/hazmat/primitives/test_camellia.py
@@ -16,7 +16,7 @@ from __future__ import absolute_import, division, print_function
import binascii
import os
-from cryptography.hazmat.primitives.block import ciphers, modes
+from cryptography.hazmat.primitives.ciphers import algorithms, modes
from .utils import generate_encrypt_test
from ...utils import (
@@ -33,10 +33,10 @@ class TestCamellia(object):
"camellia-192-ecb.txt",
"camellia-256-ecb.txt"
],
- lambda key: ciphers.Camellia(binascii.unhexlify((key))),
+ lambda key: algorithms.Camellia(binascii.unhexlify((key))),
lambda key: modes.ECB(),
only_if=lambda backend: backend.ciphers.supported(
- ciphers.Camellia("\x00" * 16), modes.ECB()
+ algorithms.Camellia("\x00" * 16), modes.ECB()
),
skip_message="Does not support Camellia ECB",
)
@@ -45,10 +45,10 @@ class TestCamellia(object):
load_openssl_vectors_from_file,
os.path.join("ciphers", "Camellia"),
["camellia-cbc.txt"],
- lambda key, iv: ciphers.Camellia(binascii.unhexlify(key)),
+ lambda key, iv: algorithms.Camellia(binascii.unhexlify(key)),
lambda key, iv: modes.CBC(binascii.unhexlify(iv)),
only_if=lambda backend: backend.ciphers.supported(
- ciphers.Camellia("\x00" * 16), modes.CBC("\x00" * 16)
+ algorithms.Camellia("\x00" * 16), modes.CBC("\x00" * 16)
),
skip_message="Does not support Camellia CBC",
)
@@ -57,10 +57,10 @@ class TestCamellia(object):
load_openssl_vectors_from_file,
os.path.join("ciphers", "Camellia"),
["camellia-ofb.txt"],
- lambda key, iv: ciphers.Camellia(binascii.unhexlify(key)),
+ lambda key, iv: algorithms.Camellia(binascii.unhexlify(key)),
lambda key, iv: modes.OFB(binascii.unhexlify(iv)),
only_if=lambda backend: backend.ciphers.supported(
- ciphers.Camellia("\x00" * 16), modes.OFB("\x00" * 16)
+ algorithms.Camellia("\x00" * 16), modes.OFB("\x00" * 16)
),
skip_message="Does not support Camellia OFB",
)
@@ -69,10 +69,10 @@ class TestCamellia(object):
load_openssl_vectors_from_file,
os.path.join("ciphers", "Camellia"),
["camellia-cfb.txt"],
- lambda key, iv: ciphers.Camellia(binascii.unhexlify(key)),
+ lambda key, iv: algorithms.Camellia(binascii.unhexlify(key)),
lambda key, iv: modes.CFB(binascii.unhexlify(iv)),
only_if=lambda backend: backend.ciphers.supported(
- ciphers.Camellia("\x00" * 16), modes.CFB("\x00" * 16)
+ algorithms.Camellia("\x00" * 16), modes.CFB("\x00" * 16)
),
skip_message="Does not support Camellia CFB",
)
diff --git a/tests/hazmat/primitives/test_cast5.py b/tests/hazmat/primitives/test_cast5.py
index bd861150..b2988437 100644
--- a/tests/hazmat/primitives/test_cast5.py
+++ b/tests/hazmat/primitives/test_cast5.py
@@ -16,7 +16,7 @@ from __future__ import absolute_import, division, print_function
import binascii
import os
-from cryptography.hazmat.primitives.block import ciphers, modes
+from cryptography.hazmat.primitives.ciphers import algorithms, modes
from .utils import generate_encrypt_test
from ...utils import load_nist_vectors_from_file
@@ -29,10 +29,10 @@ class TestCAST5(object):
[
"cast5-ecb.txt",
],
- lambda key: ciphers.CAST5(binascii.unhexlify((key))),
+ lambda key: algorithms.CAST5(binascii.unhexlify((key))),
lambda key: modes.ECB(),
only_if=lambda backend: backend.ciphers.supported(
- ciphers.CAST5("\x00" * 16), modes.ECB()
+ algorithms.CAST5("\x00" * 16), modes.ECB()
),
skip_message="Does not support CAST5 ECB",
)
diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py
index d3870a0b..dfafab3f 100644
--- a/tests/hazmat/primitives/test_ciphers.py
+++ b/tests/hazmat/primitives/test_ciphers.py
@@ -17,7 +17,7 @@ import binascii
import pytest
-from cryptography.hazmat.primitives.block.ciphers import (
+from cryptography.hazmat.primitives.ciphers.algorithms import (
AES, Camellia, TripleDES, Blowfish, CAST5
)
diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py
index b4a8a3e6..e6e97d1d 100644
--- a/tests/hazmat/primitives/utils.py
+++ b/tests/hazmat/primitives/utils.py
@@ -6,7 +6,7 @@ import pytest
from cryptography.hazmat.bindings import _ALL_BACKENDS
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import hmac
-from cryptography.hazmat.primitives.block import BlockCipher
+from cryptography.hazmat.primitives.ciphers import Cipher
def generate_encrypt_test(param_loader, path, file_names, cipher_factory,
@@ -34,7 +34,7 @@ def encrypt_test(backend, cipher_factory, mode_factory, params, only_if,
pytest.skip(skip_message)
plaintext = params.pop("plaintext")
ciphertext = params.pop("ciphertext")
- cipher = BlockCipher(
+ cipher = Cipher(
cipher_factory(**params),
mode_factory(**params),
backend
diff --git a/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-128.txt b/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-128.txt
new file mode 100644
index 00000000..0902491b
--- /dev/null
+++ b/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-128.txt
@@ -0,0 +1,254 @@
+# Vectors from RFC 6229. Reformatted to work with the NIST loader
+[ENCRYPT]
+
+# 128-bit key
+COUNT = 0
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9ac7cc9a609d1ef7b2932899cde41b97
+
+
+COUNT = 1
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5248c4959014126a6e8a84f11d1a9e1c
+
+
+COUNT = 2
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 065902e4b620f6cc36c8589f66432f2b
+
+
+COUNT = 3
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d39d566bc6bce3010768151549f3873f
+
+
+COUNT = 4
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b6d1e6c4a5e4771cad79538df295fb11
+
+
+COUNT = 5
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c68c1d5c559a974123df1dbc52a43b89
+
+
+COUNT = 6
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c5ecf88de897fd57fed301701b82a259
+
+
+COUNT = 7
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = eccbe13de1fcc91c11a0b26c0bc8fa4d
+
+
+COUNT = 8
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e7a72574f8782ae26aabcf9ebcd66065
+
+
+COUNT = 9
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bdf0324e6083dcc6d3cedd3ca8c53c16
+
+
+COUNT = 10
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b40110c4190b5622a96116b0017ed297
+
+
+COUNT = 11
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ffa0b514647ec04f6306b892ae661181
+
+
+COUNT = 12
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d03d1bc03cd33d70dff9fa5d71963ebd
+
+
+COUNT = 13
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8a44126411eaa78bd51e8d87a8879bf5
+
+
+COUNT = 14
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fabeb76028ade2d0e48722e46c4615a3
+
+
+COUNT = 15
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c05d88abd50357f935a63c59ee537623
+
+
+COUNT = 16
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ff38265c1642c1abe8d3c2fe5e572bf8
+
+
+COUNT = 17
+KEY = 0102030405060708090a0b0c0d0e0f10
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a36a4c301ae8ac13610ccbc12256cacc
+
+# key 2
+COUNT = 18
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 720c94b63edf44e131d950ca211a5a30
+
+
+COUNT = 19
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c366fdeacf9ca80436be7c358424d20b
+
+
+COUNT = 20
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b3394a40aabf75cba42282ef25a0059f
+
+
+COUNT = 21
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4847d81da4942dbc249defc48c922b9f
+
+
+COUNT = 22
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 08128c469f275342adda202b2b58da95
+
+
+COUNT = 23
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 970dacef40ad98723bac5d6955b81761
+
+
+COUNT = 24
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3cb89993b07b0ced93de13d2a11013ac
+
+
+COUNT = 25
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ef2d676f1545c2c13dc680a02f4adbfe
+
+
+COUNT = 26
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b60595514f24bc9fe522a6cad7393644
+
+
+COUNT = 27
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b515a8c5011754f59003058bdb81514e
+
+
+COUNT = 28
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3c70047e8cbc038e3b9820db601da495
+
+
+COUNT = 29
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1175da6ee756de46a53e2b075660b770
+
+
+COUNT = 30
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 00a542bba02111cc2c65b38ebdba587e
+
+
+COUNT = 31
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5865fdbb5b48064104e830b380f2aede
+
+
+COUNT = 32
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 34b21ad2ad44e999db2d7f0863f0d9b6
+
+
+COUNT = 33
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 84a9218fc36e8a5f2ccfbeae53a27d25
+
+
+COUNT = 34
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a2221a11b833ccb498a59540f0545f4a
+
+
+COUNT = 35
+KEY = ebb46227c6cc8b37641910833222772a
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5bbeb4787d59e5373fdbea6c6f75c29b
diff --git a/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-192.txt b/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-192.txt
new file mode 100644
index 00000000..f2fbaafe
--- /dev/null
+++ b/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-192.txt
@@ -0,0 +1,254 @@
+# Vectors from RFC 6229. Reformatted to work with the NIST loader
+[ENCRYPT]
+
+# 192-bit key
+COUNT = 0
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0595e57fe5f0bb3c706edac8a4b2db11
+
+
+COUNT = 1
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dfde31344a1af769c74f070aee9e2326
+
+
+COUNT = 2
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b06b9b1e195d13d8f4a7995c4553ac05
+
+
+COUNT = 3
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6bd2378ec341c9a42f37ba79f88a32ff
+
+
+COUNT = 4
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e70bce1df7645adb5d2c4130215c3522
+
+
+COUNT = 5
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9a5730c7fcb4c9af51ffda89c7f1ad22
+
+
+COUNT = 6
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0485055fd4f6f0d963ef5ab9a5476982
+
+
+COUNT = 7
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 591fc66bcda10e452b03d4551f6b62ac
+
+
+COUNT = 8
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2753cc83988afa3e1688a1d3b42c9a02
+
+
+COUNT = 9
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 93610d523d1d3f0062b3c2a3bbc7c7f0
+
+
+COUNT = 10
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 96c248610aadedfeaf8978c03de8205a
+
+
+COUNT = 11
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0e317b3d1c73b9e9a4688f296d133a19
+
+
+COUNT = 12
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bdf0e6c3cca5b5b9d533b69c56ada120
+
+
+COUNT = 13
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 88a218b6e2ece1e6246d44c759d19b10
+
+
+COUNT = 14
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6866397e95c140534f94263421006e40
+
+
+COUNT = 15
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 32cb0a1e9542c6b3b8b398abc3b0f1d5
+
+
+COUNT = 16
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 29a0b8aed54a132324c62e423f54b4c8
+
+
+COUNT = 17
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3cb0f3b5020a98b82af9fe154484a168
+
+# key 2
+COUNT = 18
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 54b64e6b5a20b5e2ec84593dc7989da7
+
+
+COUNT = 19
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c135eee237a85465ff97dc03924f45ce
+
+
+COUNT = 20
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cfcc922fb4a14ab45d6175aabbf2d201
+
+
+COUNT = 21
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 837b87e2a446ad0ef798acd02b94124f
+
+
+COUNT = 22
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 17a6dbd664926a0636b3f4c37a4f4694
+
+
+COUNT = 23
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4a5f9f26aeeed4d4a25f632d305233d9
+
+
+COUNT = 24
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 80a3d01ef00c8e9a4209c17f4eeb358c
+
+
+COUNT = 25
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d15e7d5ffaaabc0207bf200a117793a2
+
+
+COUNT = 26
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 349682bf588eaa52d0aa1560346aeafa
+
+
+COUNT = 27
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f5854cdb76c889e3ad63354e5f7275e3
+
+
+COUNT = 28
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 532c7ceccb39df3236318405a4b1279c
+
+
+COUNT = 29
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = baefe6d9ceb651842260e0d1e05e3b90
+
+
+COUNT = 30
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e82d8c6db54e3c633f581c952ba04207
+
+
+COUNT = 31
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4b16e50abd381bd70900a9cd9a62cb23
+
+
+COUNT = 32
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3682ee33bd148bd9f58656cd8f30d9fb
+
+
+COUNT = 33
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1e5a0b8475045d9b20b2628624edfd9e
+
+
+COUNT = 34
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 63edd684fb826282fe528f9c0e9237bc
+
+
+COUNT = 35
+KEY = c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e4dd2e98d6960fae0b43545456743391
diff --git a/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-256.txt b/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-256.txt
new file mode 100644
index 00000000..35bf7863
--- /dev/null
+++ b/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-256.txt
@@ -0,0 +1,254 @@
+# Vectors from RFC 6229. Reformatted to work with the NIST loader
+[ENCRYPT]
+
+# 256-bit key
+COUNT = 0
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = eaa6bd25880bf93d3f5d1e4ca2611d91
+
+
+COUNT = 1
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cfa45c9f7e714b54bdfa80027cb14380
+
+
+COUNT = 2
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 114ae344ded71b35f2e60febad727fd8
+
+
+COUNT = 3
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 02e1e7056b0f623900496422943e97b6
+
+
+COUNT = 4
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 91cb93c787964e10d9527d999c6f936b
+
+
+COUNT = 5
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 49b18b42f8e8367cbeb5ef104ba1c7cd
+
+
+COUNT = 6
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 87084b3ba700bade955610672745b374
+
+
+COUNT = 7
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e7a7b9e9ec540d5ff43bdb12792d1b35
+
+
+COUNT = 8
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c799b596738f6b018c76c74b1759bd90
+
+
+COUNT = 9
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7fec5bfd9f9b89ce6548309092d7e958
+
+
+COUNT = 10
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 40f250b26d1f096a4afd4c340a588815
+
+
+COUNT = 11
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3e34135c79db010200767651cf263073
+
+
+COUNT = 12
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f656abccf88dd827027b2ce917d464ec
+
+
+COUNT = 13
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 18b62503bfbc077fbabb98f20d98ab34
+
+
+COUNT = 14
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8aed95ee5b0dcbfbef4eb21d3a3f52f9
+
+
+COUNT = 15
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 625a1ab00ee39a5327346bddb01a9c18
+
+
+COUNT = 16
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a13a7c79c7e119b5ab0296ab28c300b9
+
+
+COUNT = 17
+KEY = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f3e4c0a2e02d1d01f7f0a74618af2b48
+
+# key 2
+COUNT = 18
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dd5bcb0018e922d494759d7c395d02d3
+
+
+COUNT = 19
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c8446f8f77abf737685353eb89a1c9eb
+
+
+COUNT = 20
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = af3e30f9c095045938151575c3fb9098
+
+
+COUNT = 21
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f8cb6274db99b80b1d2012a98ed48f0e
+
+
+COUNT = 22
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 25c3005a1cb85de076259839ab7198ab
+
+
+COUNT = 23
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9dcbc183e8cb994b727b75be3180769c
+
+
+COUNT = 24
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a1d3078dfa9169503ed9d4491dee4eb2
+
+
+COUNT = 25
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8514a5495858096f596e4bcd66b10665
+
+
+COUNT = 26
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5f40d59ec1b03b33738efa60b2255d31
+
+
+COUNT = 27
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3477c7f764a41baceff90bf14f92b7cc
+
+
+COUNT = 28
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ac4e95368d99b9eb78b8da8f81ffa795
+
+
+COUNT = 29
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8c3c13f8c2388bb73f38576e65b7c446
+
+
+COUNT = 30
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 13c4b9c1dfb66579eddd8a280b9f7316
+
+
+COUNT = 31
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ddd27820550126698efaadc64b64f66e
+
+
+COUNT = 32
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f08f2e66d28ed143f3a237cf9de73559
+
+
+COUNT = 33
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9ea36c525531b880ba124334f57b0b70
+
+
+COUNT = 34
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d5a39e3dfcc50280bac4a6b5aa0dca7d
+
+
+COUNT = 35
+KEY = 1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 370b1c1fe655916d97fd0d47ca1d72b8
diff --git a/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-40.txt b/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-40.txt
new file mode 100644
index 00000000..5fe7d019
--- /dev/null
+++ b/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-40.txt
@@ -0,0 +1,237 @@
+# Vectors from RFC 6229. Reformatted to work with the NIST loader
+[ENCRYPT]
+
+# 40-bit key
+COUNT = 0
+KEY = 0102030405
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b2396305f03dc027ccc3524a0a1118a8
+
+COUNT = 1
+KEY = 0102030405
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6982944f18fc82d589c403a47a0d0919
+
+COUNT = 2
+KEY = 0102030405
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 28cb1132c96ce286421dcaadb8b69eae
+
+COUNT = 3
+KEY = 0102030405
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1cfcf62b03eddb641d77dfcf7f8d8c93
+
+COUNT = 4
+KEY = 0102030405
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 42b7d0cdd918a8a33dd51781c81f4041
+
+COUNT = 5
+KEY = 0102030405
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6459844432a7da923cfb3eb4980661f6
+
+COUNT = 6
+KEY = 0102030405
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ec10327bde2beefd18f9277680457e22
+
+COUNT = 7
+KEY = 0102030405
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = eb62638d4f0ba1fe9fca20e05bf8ff2b
+
+COUNT = 8
+KEY = 0102030405
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 45129048e6a0ed0b56b490338f078da5
+
+COUNT = 9
+KEY = 0102030405
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 30abbcc7c20b01609f23ee2d5f6bb7df
+
+COUNT = 10
+KEY = 0102030405
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3294f744d8f9790507e70f62e5bbceea
+
+COUNT = 11
+KEY = 0102030405
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d8729db41882259bee4f825325f5a130
+
+COUNT = 12
+KEY = 0102030405
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1eb14a0c13b3bf47fa2a0ba93ad45b8b
+
+COUNT = 13
+KEY = 0102030405
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cc582f8ba9f265e2b1be9112e975d2d7
+
+COUNT = 14
+KEY = 0102030405
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f2e30f9bd102ecbf75aaade9bc35c43c
+
+COUNT = 15
+KEY = 0102030405
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ec0e11c479dc329dc8da7968fe965681
+
+COUNT = 16
+KEY = 0102030405
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 068326a2118416d21f9d04b2cd1ca050
+
+COUNT = 17
+KEY = 0102030405
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ff25b58995996707e51fbdf08b34d875
+
+# key 2
+COUNT = 18
+KEY = 833222772a
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 80ad97bdc973df8a2e879e92a497efda
+
+
+COUNT = 19
+KEY = 833222772a
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 20f060c2f2e5126501d3d4fea10d5fc0
+
+
+COUNT = 20
+KEY = 833222772a
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = faa148e99046181fec6b2085f3b20ed9
+
+
+COUNT = 21
+KEY = 833222772a
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f0daf5bab3d596839857846f73fbfe5a
+
+
+COUNT = 22
+KEY = 833222772a
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1c7e2fc4639232fe297584b296996bc8
+
+
+COUNT = 23
+KEY = 833222772a
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3db9b249406cc8edffac55ccd322ba12
+
+
+COUNT = 24
+KEY = 833222772a
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e4f9f7e0066154bbd125b745569bc897
+
+
+COUNT = 25
+KEY = 833222772a
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 75d5ef262b44c41a9cf63ae14568e1b9
+
+
+COUNT = 26
+KEY = 833222772a
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6da453dbf81e82334a3d8866cb50a1e3
+
+
+COUNT = 27
+KEY = 833222772a
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7828d074119cab5c22b294d7a9bfa0bb
+
+
+COUNT = 28
+KEY = 833222772a
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = adb89cea9a15fbe617295bd04b8ca05c
+
+
+COUNT = 29
+KEY = 833222772a
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6251d87fd4aaae9a7e4ad5c217d3f300
+
+
+COUNT = 30
+KEY = 833222772a
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e7119bd6dd9b22afe8f89585432881e2
+
+
+COUNT = 31
+KEY = 833222772a
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 785b60fd7ec4e9fcb6545f350d660fab
+
+
+COUNT = 32
+KEY = 833222772a
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = afecc037fdb7b0838eb3d70bcd268382
+
+
+COUNT = 33
+KEY = 833222772a
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dbc1a7b49d57358cc9fa6d61d73b7cf0
+
+
+COUNT = 34
+KEY = 833222772a
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6349d126a37afcba89794f9804914fdc
+
+
+COUNT = 35
+KEY = 833222772a
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bf42c3018c2f7c66bfde524975768115
diff --git a/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-56.txt b/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-56.txt
new file mode 100644
index 00000000..78bdfd40
--- /dev/null
+++ b/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-56.txt
@@ -0,0 +1,254 @@
+# Vectors from RFC 6229. Reformatted to work with the NIST loader
+[ENCRYPT]
+
+# 56-bit key
+COUNT = 0
+KEY = 01020304050607
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 293f02d47f37c9b633f2af5285feb46b
+
+
+COUNT = 1
+KEY = 01020304050607
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e620f1390d19bd84e2e0fd752031afc1
+
+
+COUNT = 2
+KEY = 01020304050607
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 914f02531c9218810df60f67e338154c
+
+
+COUNT = 3
+KEY = 01020304050607
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d0fdb583073ce85ab83917740ec011d5
+
+
+COUNT = 4
+KEY = 01020304050607
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 75f81411e871cffa70b90c74c592e454
+
+
+COUNT = 5
+KEY = 01020304050607
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0bb87202938dad609e87a5a1b079e5e4
+
+
+COUNT = 6
+KEY = 01020304050607
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c2911246b612e7e7b903dfeda1dad866
+
+
+COUNT = 7
+KEY = 01020304050607
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 32828f91502b6291368de8081de36fc2
+
+
+COUNT = 8
+KEY = 01020304050607
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f3b9a7e3b297bf9ad804512f9063eff1
+
+
+COUNT = 9
+KEY = 01020304050607
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8ecb67a9ba1f55a5a067e2b026a3676f
+
+
+COUNT = 10
+KEY = 01020304050607
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d2aa902bd42d0d7cfd340cd45810529f
+
+
+COUNT = 11
+KEY = 01020304050607
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 78b272c96e42eab4c60bd914e39d06e3
+
+
+COUNT = 12
+KEY = 01020304050607
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f4332fd31a079396ee3cee3f2a4ff049
+
+
+COUNT = 13
+KEY = 01020304050607
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 05459781d41fda7f30c1be7e1246c623
+
+
+COUNT = 14
+KEY = 01020304050607
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = adfd3868b8e51485d5e610017e3dd609
+
+
+COUNT = 15
+KEY = 01020304050607
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ad26581c0c5be45f4cea01db2f3805d5
+
+
+COUNT = 16
+KEY = 01020304050607
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f3172ceffc3b3d997c85ccd5af1a950c
+
+
+COUNT = 17
+KEY = 01020304050607
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e74b0b9731227fd37c0ec08a47ddd8b8
+
+# key 2
+COUNT = 18
+KEY = 1910833222772a
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bc9222dbd3274d8fc66d14ccbda6690b
+
+
+COUNT = 19
+KEY = 1910833222772a
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7ae627410c9a2be693df5bb7485a63e3
+
+
+COUNT = 20
+KEY = 1910833222772a
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3f0931aa03defb300f060103826f2a64
+
+
+COUNT = 21
+KEY = 1910833222772a
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = beaa9ec8d59bb68129f3027c96361181
+
+
+COUNT = 22
+KEY = 1910833222772a
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 74e04db46d28648d7dee8a0064b06cfe
+
+
+COUNT = 23
+KEY = 1910833222772a
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9b5e81c62fe023c55be42f87bbf932b8
+
+
+COUNT = 24
+KEY = 1910833222772a
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ce178fc1826efecbc182f57999a46140
+
+
+COUNT = 25
+KEY = 1910833222772a
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8bdf55cd55061c06dba6be11de4a578a
+
+
+COUNT = 26
+KEY = 1910833222772a
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 626f5f4dce652501f3087d39c92cc349
+
+
+COUNT = 27
+KEY = 1910833222772a
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 42daac6a8f9ab9a7fd137c6037825682
+
+
+COUNT = 28
+KEY = 1910833222772a
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cc03fdb79192a207312f53f5d4dc33d9
+
+
+COUNT = 29
+KEY = 1910833222772a
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f70f14122a1c98a3155d28b8a0a8a41d
+
+
+COUNT = 30
+KEY = 1910833222772a
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2a3a307ab2708a9c00fe0b42f9c2d6a1
+
+
+COUNT = 31
+KEY = 1910833222772a
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 862617627d2261eab0b1246597ca0ae9
+
+
+COUNT = 32
+KEY = 1910833222772a
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 55f877ce4f2e1ddbbf8e13e2cde0fdc8
+
+
+COUNT = 33
+KEY = 1910833222772a
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1b1556cb935f173337705fbb5d501fc1
+
+
+COUNT = 34
+KEY = 1910833222772a
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ecd0e96602be7f8d5092816cccf2c2e9
+
+
+COUNT = 35
+KEY = 1910833222772a
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 027881fab4993a1c262024a94fff3f61
diff --git a/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-64.txt b/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-64.txt
new file mode 100644
index 00000000..dca652ef
--- /dev/null
+++ b/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-64.txt
@@ -0,0 +1,254 @@
+# Vectors from RFC 6229. Reformatted to work with the NIST loader
+[ENCRYPT]
+
+# 64-bit key
+COUNT = 0
+KEY = 0102030405060708
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 97ab8a1bf0afb96132f2f67258da15a8
+
+
+COUNT = 1
+KEY = 0102030405060708
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8263efdb45c4a18684ef87e6b19e5b09
+
+
+COUNT = 2
+KEY = 0102030405060708
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9636ebc9841926f4f7d1f362bddf6e18
+
+
+COUNT = 3
+KEY = 0102030405060708
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d0a990ff2c05fef5b90373c9ff4b870a
+
+
+COUNT = 4
+KEY = 0102030405060708
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 73239f1db7f41d80b643c0c52518ec63
+
+
+COUNT = 5
+KEY = 0102030405060708
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 163b319923a6bdb4527c626126703c0f
+
+
+COUNT = 6
+KEY = 0102030405060708
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 49d6c8af0f97144a87df21d91472f966
+
+
+COUNT = 7
+KEY = 0102030405060708
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 44173a103b6616c5d5ad1cee40c863d0
+
+
+COUNT = 8
+KEY = 0102030405060708
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 273c9c4b27f322e4e716ef53a47de7a4
+
+
+COUNT = 9
+KEY = 0102030405060708
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c6d0e7b226259fa9023490b26167ad1d
+
+
+COUNT = 10
+KEY = 0102030405060708
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1fe8986713f07c3d9ae1c163ff8cf9d3
+
+
+COUNT = 11
+KEY = 0102030405060708
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8369e1a965610be887fbd0c79162aafb
+
+
+COUNT = 12
+KEY = 0102030405060708
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0a0127abb44484b9fbef5abcae1b579f
+
+
+COUNT = 13
+KEY = 0102030405060708
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c2cdadc6402e8ee866e1f37bdb47e42c
+
+
+COUNT = 14
+KEY = 0102030405060708
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 26b51ea37df8e1d6f76fc3b66a7429b3
+
+
+COUNT = 15
+KEY = 0102030405060708
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bc7683205d4f443dc1f29dda3315c87b
+
+
+COUNT = 16
+KEY = 0102030405060708
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d5fa5a3469d29aaaf83d23589db8c85b
+
+
+COUNT = 17
+KEY = 0102030405060708
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3fb46e2c8f0f068edce8cdcd7dfc5862
+
+# key 2
+COUNT = 18
+KEY = 641910833222772a
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bbf609de9413172d07660cb680716926
+
+
+COUNT = 19
+KEY = 641910833222772a
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 46101a6dab43115d6c522b4fe93604a9
+
+
+COUNT = 20
+KEY = 641910833222772a
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cbe1fff21c96f3eef61e8fe0542cbdf0
+
+
+COUNT = 21
+KEY = 641910833222772a
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 347938bffa4009c512cfb4034b0dd1a7
+
+
+COUNT = 22
+KEY = 641910833222772a
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7867a786d00a7147904d76ddf1e520e3
+
+
+COUNT = 23
+KEY = 641910833222772a
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8d3e9e1caefcccb3fbf8d18f64120b32
+
+
+COUNT = 24
+KEY = 641910833222772a
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 942337f8fd76f0fae8c52d7954810672
+
+
+COUNT = 25
+KEY = 641910833222772a
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b8548c10f51667f6e60e182fa19b30f7
+
+
+COUNT = 26
+KEY = 641910833222772a
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0211c7c6190c9efd1237c34c8f2e06c4
+
+
+COUNT = 27
+KEY = 641910833222772a
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bda64f65276d2aacb8f90212203a808e
+
+
+COUNT = 28
+KEY = 641910833222772a
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bd3820f732ffb53ec193e79d33e27c73
+
+
+COUNT = 29
+KEY = 641910833222772a
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d0168616861907d482e36cdac8cf5749
+
+
+COUNT = 30
+KEY = 641910833222772a
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 97b0f0f224b2d2317114808fb03af7a0
+
+
+COUNT = 31
+KEY = 641910833222772a
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e59616e469787939a063ceea9af956d1
+
+
+COUNT = 32
+KEY = 641910833222772a
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c47e0dc1660919c11101208f9e69aa1f
+
+
+COUNT = 33
+KEY = 641910833222772a
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5ae4f12896b8379a2aad89b5b553d6b0
+
+
+COUNT = 34
+KEY = 641910833222772a
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6b6b098d0c293bc2993d80bf0518b6d9
+
+
+COUNT = 35
+KEY = 641910833222772a
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8170cc3ccd92a698621b939dd38fe7b9
diff --git a/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-80.txt b/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-80.txt
new file mode 100644
index 00000000..18a9efe4
--- /dev/null
+++ b/tests/hazmat/primitives/vectors/ciphers/ARC4/rfc-6229-80.txt
@@ -0,0 +1,254 @@
+# Vectors from RFC 6229. Reformatted to work with the NIST loader
+[ENCRYPT]
+
+# 80-bit key
+COUNT = 0
+KEY = 0102030405060708090a
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ede3b04643e586cc907dc21851709902
+
+
+COUNT = 1
+KEY = 0102030405060708090a
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 03516ba78f413beb223aa5d4d2df6711
+
+
+COUNT = 2
+KEY = 0102030405060708090a
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3cfd6cb58ee0fdde640176ad0000044d
+
+
+COUNT = 3
+KEY = 0102030405060708090a
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 48532b21fb6079c9114c0ffd9c04a1ad
+
+
+COUNT = 4
+KEY = 0102030405060708090a
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3e8cea98017109979084b1ef92f99d86
+
+
+COUNT = 5
+KEY = 0102030405060708090a
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e20fb49bdb337ee48b8d8dc0f4afeffe
+
+
+COUNT = 6
+KEY = 0102030405060708090a
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5c2521eacd7966f15e056544bea0d315
+
+
+COUNT = 7
+KEY = 0102030405060708090a
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e067a7031931a246a6c3875d2f678acb
+
+
+COUNT = 8
+KEY = 0102030405060708090a
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a64f70af88ae56b6f87581c0e23e6b08
+
+
+COUNT = 9
+KEY = 0102030405060708090a
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f449031de312814ec6f319291f4a0516
+
+
+COUNT = 10
+KEY = 0102030405060708090a
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bdae85924b3cb1d0a2e33a30c6d79599
+
+
+COUNT = 11
+KEY = 0102030405060708090a
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8a0feddbac865a09bcd127fb562ed60a
+
+
+COUNT = 12
+KEY = 0102030405060708090a
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b55a0a5b51a12a8be34899c3e047511a
+
+
+COUNT = 13
+KEY = 0102030405060708090a
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d9a09cea3ce75fe39698070317a71339
+
+
+COUNT = 14
+KEY = 0102030405060708090a
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 552225ed1177f44584ac8cfa6c4eb5fc
+
+
+COUNT = 15
+KEY = 0102030405060708090a
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7e82cbabfc95381b080998442129c2f8
+
+
+COUNT = 16
+KEY = 0102030405060708090a
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1f135ed14ce60a91369d2322bef25e3c
+
+
+COUNT = 17
+KEY = 0102030405060708090a
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 08b6be45124a43e2eb77953f84dc8553
+
+# key 2
+COUNT = 18
+KEY = 8b37641910833222772a
+OFFSET = 0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ab65c26eddb287600db2fda10d1e605c
+
+
+COUNT = 19
+KEY = 8b37641910833222772a
+OFFSET = 16
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bb759010c29658f2c72d93a2d16d2930
+
+
+COUNT = 20
+KEY = 8b37641910833222772a
+OFFSET = 240
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b901e8036ed1c383cd3c4c4dd0a6ab05
+
+
+COUNT = 21
+KEY = 8b37641910833222772a
+OFFSET = 256
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3d25ce4922924c55f064943353d78a6c
+
+
+COUNT = 22
+KEY = 8b37641910833222772a
+OFFSET = 496
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 12c1aa44bbf87e75e611f69b2c38f49b
+
+
+COUNT = 23
+KEY = 8b37641910833222772a
+OFFSET = 512
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 28f2b3434b65c09877470044c6ea170d
+
+
+COUNT = 24
+KEY = 8b37641910833222772a
+OFFSET = 752
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bd9ef822de5288196134cf8af7839304
+
+
+COUNT = 25
+KEY = 8b37641910833222772a
+OFFSET = 768
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 67559c23f052158470a296f725735a32
+
+
+COUNT = 26
+KEY = 8b37641910833222772a
+OFFSET = 1008
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8bab26fbc2c12b0f13e2ab185eabf241
+
+
+COUNT = 27
+KEY = 8b37641910833222772a
+OFFSET = 1024
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 31185a6d696f0cfa9b42808b38e132a2
+
+
+COUNT = 28
+KEY = 8b37641910833222772a
+OFFSET = 1520
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 564d3dae183c5234c8af1e51061c44b5
+
+
+COUNT = 29
+KEY = 8b37641910833222772a
+OFFSET = 1536
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3c0778a7b5f72d3c23a3135c7d67b9f4
+
+
+COUNT = 30
+KEY = 8b37641910833222772a
+OFFSET = 2032
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f34369890fcf16fb517dcaae4463b2dd
+
+
+COUNT = 31
+KEY = 8b37641910833222772a
+OFFSET = 2048
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 02f31c81e8200731b899b028e791bfa7
+
+
+COUNT = 32
+KEY = 8b37641910833222772a
+OFFSET = 3056
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 72da646283228c14300853701795616f
+
+
+COUNT = 33
+KEY = 8b37641910833222772a
+OFFSET = 3072
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4e0a8c6f7934a788e2265e81d6d0c8f4
+
+
+COUNT = 34
+KEY = 8b37641910833222772a
+OFFSET = 4080
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 438dd5eafea0111b6f36b4b938da2a68
+
+
+COUNT = 35
+KEY = 8b37641910833222772a
+OFFSET = 4096
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5f6bfc73815874d97100f086979357d8
diff --git a/tox.ini b/tox.ini
index d804351a..b807b878 100644
--- a/tox.ini
+++ b/tox.ini
@@ -9,7 +9,7 @@ deps =
pytest
commands =
coverage run --source=cryptography/,tests/ -m pytest
- coverage report -m --fail-under 100
+ coverage report -m
[testenv:docs]
deps = sphinx