aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2013-09-10 18:57:35 -0700
committerAlex Gaynor <alex.gaynor@gmail.com>2013-09-10 18:57:35 -0700
commitc9e91e8cc1d8a5e20ec4541328afabe5d633228b (patch)
tree86754f5dd74324ae18fbc2ed9fca80d0052286ac
parent180606f3e7fd9083567e9754fca39e44b5b06b15 (diff)
parent7d9e0d9af5343aea7b4b949c20635ed414238927 (diff)
downloadcryptography-c9e91e8cc1d8a5e20ec4541328afabe5d633228b.tar.gz
cryptography-c9e91e8cc1d8a5e20ec4541328afabe5d633228b.tar.bz2
cryptography-c9e91e8cc1d8a5e20ec4541328afabe5d633228b.zip
Merge pull request #53 from reaperhulk/ecb-support-im-sorry
ECB Support
-rw-r--r--cryptography/bindings/openssl/api.py13
-rw-r--r--cryptography/primitives/block/modes.py9
-rw-r--r--cryptography/primitives/interfaces.py22
-rw-r--r--docs/primitives/symmetric-encryption.rst13
-rw-r--r--setup.py2
-rw-r--r--tests/bindings/test_openssl.py2
-rw-r--r--tests/primitives/test_nist.py47
7 files changed, 103 insertions, 5 deletions
diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py
index 54a74d03..917c1846 100644
--- a/cryptography/bindings/openssl/api.py
+++ b/cryptography/bindings/openssl/api.py
@@ -13,6 +13,8 @@
from __future__ import absolute_import, division, print_function
+from cryptography.primitives import interfaces
+
import cffi
@@ -72,11 +74,14 @@ class API(object):
)
evp_cipher = self._lib.EVP_get_cipherbyname(ciphername.encode("ascii"))
assert evp_cipher != self._ffi.NULL
- # TODO: only use the key and initialization_vector as needed. Sometimes
- # this needs to be a DecryptInit, when?
+ if isinstance(mode, interfaces.ModeWithInitializationVector):
+ iv_nonce = mode.initialization_vector
+ else:
+ iv_nonce = self._ffi.NULL
+
+ # TODO: Sometimes this needs to be a DecryptInit, when?
res = self._lib.EVP_EncryptInit_ex(
- ctx, evp_cipher, self._ffi.NULL, cipher.key,
- mode.initialization_vector
+ ctx, evp_cipher, self._ffi.NULL, cipher.key, iv_nonce
)
assert res != 0
diff --git a/cryptography/primitives/block/modes.py b/cryptography/primitives/block/modes.py
index de31f086..c722e739 100644
--- a/cryptography/primitives/block/modes.py
+++ b/cryptography/primitives/block/modes.py
@@ -13,6 +13,8 @@
from __future__ import absolute_import, division, print_function
+from cryptography.primitives import interfaces
+
class CBC(object):
name = "CBC"
@@ -20,3 +22,10 @@ class CBC(object):
def __init__(self, initialization_vector):
super(CBC, self).__init__()
self.initialization_vector = initialization_vector
+
+
+class ECB(object):
+ name = "ECB"
+
+
+interfaces.ModeWithInitializationVector.register(CBC)
diff --git a/cryptography/primitives/interfaces.py b/cryptography/primitives/interfaces.py
new file mode 100644
index 00000000..6f74ccf7
--- /dev/null
+++ b/cryptography/primitives/interfaces.py
@@ -0,0 +1,22 @@
+# 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.
+
+from __future__ import absolute_import, division, print_function
+
+import abc
+
+import six
+
+
+class ModeWithInitializationVector(six.with_metaclass(abc.ABCMeta)):
+ pass
diff --git a/docs/primitives/symmetric-encryption.rst b/docs/primitives/symmetric-encryption.rst
index 1b8d1d73..d0429d4b 100644
--- a/docs/primitives/symmetric-encryption.rst
+++ b/docs/primitives/symmetric-encryption.rst
@@ -67,3 +67,16 @@ Modes
``block_size`` of the cipher. Do not
reuse an ``initialization_vector`` with
a given ``key``.
+
+
+Insecure Modes
+--------------
+
+.. warning:: Do not use. This is an insecure mode.
+.. class:: cryptography.primitives.block.modes.ECB()
+
+ ECB (Electronic Code Book) is the simplest mode of operation for block
+ ciphers. The data is separated into blocks and each block is encrypted
+ separately. This means identical plaintext blocks will always result in
+ identical encrypted blocks. Due to this property it is not recommended
+ for use. Really, don't use it. Just. Don't.
diff --git a/setup.py b/setup.py
index 1044c979..cbbf100a 100644
--- a/setup.py
+++ b/setup.py
@@ -21,9 +21,11 @@ with open("cryptography/__about__.py") as fp:
CFFI_DEPENDENCY = "cffi>=0.6"
+SIX_DEPENDENCY = "six>=1.4.1"
install_requires = [
CFFI_DEPENDENCY,
+ SIX_DEPENDENCY
]
setup_requires = [
diff --git a/tests/bindings/test_openssl.py b/tests/bindings/test_openssl.py
index 1579f002..b23c4ccc 100644
--- a/tests/bindings/test_openssl.py
+++ b/tests/bindings/test_openssl.py
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from cryptography.bindings.openssl import api
+from cryptography.bindings.openssl.api import api
class TestOpenSSL(object):
diff --git a/tests/primitives/test_nist.py b/tests/primitives/test_nist.py
index 8bef118e..3dc8277a 100644
--- a/tests/primitives/test_nist.py
+++ b/tests/primitives/test_nist.py
@@ -86,3 +86,50 @@ class TestAES_CBC(object):
actual_ciphertext = cipher.encrypt(binascii.unhexlify(plaintext))
actual_ciphertext += cipher.finalize()
assert binascii.hexlify(actual_ciphertext) == ciphertext
+
+
+class TestAES_ECB(object):
+ @parameterize_encrypt_test(
+ "AES", "KAT",
+ ("key", "plaintext", "ciphertext"),
+ [
+ "ECBGFSbox128.rsp",
+ "ECBGFSbox192.rsp",
+ "ECBGFSbox256.rsp",
+ "ECBKeySbox128.rsp",
+ "ECBKeySbox192.rsp",
+ "ECBKeySbox256.rsp",
+ "ECBVarKey128.rsp",
+ "ECBVarKey192.rsp",
+ "ECBVarKey256.rsp",
+ "ECBVarTxt128.rsp",
+ "ECBVarTxt192.rsp",
+ "ECBVarTxt256.rsp",
+ ]
+ )
+ def test_KAT(self, key, plaintext, ciphertext):
+ cipher = BlockCipher(
+ ciphers.AES(binascii.unhexlify(key)),
+ modes.ECB()
+ )
+ actual_ciphertext = cipher.encrypt(binascii.unhexlify(plaintext))
+ actual_ciphertext += cipher.finalize()
+ assert binascii.hexlify(actual_ciphertext) == ciphertext
+
+ @parameterize_encrypt_test(
+ "AES", "MMT",
+ ("key", "plaintext", "ciphertext"),
+ [
+ "ECBMMT128.rsp",
+ "ECBMMT192.rsp",
+ "ECBMMT256.rsp",
+ ]
+ )
+ def test_MMT(self, key, plaintext, ciphertext):
+ cipher = BlockCipher(
+ ciphers.AES(binascii.unhexlify(key)),
+ modes.ECB()
+ )
+ actual_ciphertext = cipher.encrypt(binascii.unhexlify(plaintext))
+ actual_ciphertext += cipher.finalize()
+ assert binascii.hexlify(actual_ciphertext) == ciphertext