Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion cryptography/hazmat/bindings/openssl/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

from cryptography.hazmat.primitives import interfaces
from cryptography.hazmat.primitives.block.ciphers import (
AES, Camellia, TripleDES,
AES, Blowfish, Camellia, TripleDES,
)
from cryptography.hazmat.primitives.block.modes import CBC, CTR, ECB, OFB, CFB

Expand Down Expand Up @@ -221,6 +221,12 @@ def _register_default_ciphers(self):
mode_cls,
GetCipherByName("des-ede3-{mode.name}")
)
for mode_cls in [CBC, CFB, OFB, ECB]:
self.register_cipher_adapter(
Blowfish,
mode_cls,
GetCipherByName("bf-{mode.name}")
)

def create_encrypt_ctx(self, cipher, mode):
return _CipherContext(self._backend, cipher, mode,
Expand Down
20 changes: 20 additions & 0 deletions cryptography/hazmat/primitives/block/ciphers.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,23 @@ def __init__(self, key):
@property
def key_size(self):
return len(self.key) * 8


class Blowfish(object):
name = "Blowfish"
block_size = 64
key_sizes = frozenset(range(32, 449, 8))

def __init__(self, key):
super(Blowfish, self).__init__()
self.key = key

# Verify that the key size matches the expected key size
if self.key_size not in self.key_sizes:
raise ValueError("Invalid key size ({0}) for {1}".format(
self.key_size, self.name
))

@property
def key_size(self):
return len(self.key) * 8
19 changes: 19 additions & 0 deletions docs/hazmat/primitives/symmetric-encryption.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,25 @@ Ciphers
``56`` bits long), they can simply be concatenated to
produce the full key. This must be kept secret.

Weak Ciphers
------------

.. warning::

These ciphers are considered weak for a variety of reasons. New
applications should avoid their use and existing applications should
strongly consider migrating away.

.. class:: Blowfish(key)

Blowfish is a block cipher developed by Bruce Schneier. It is known to be
susceptible to attacks when using weak keys. The author has recommended
that users of Blowfish move to newer algorithms like
:class:`AES`.

:param bytes key: The secret key, 32-448 bits in length (in increments of
8). This must be kept secret.


Modes
~~~~~
Expand Down
56 changes: 56 additions & 0 deletions tests/hazmat/primitives/test_blowfish.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# 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 binascii
import os

from cryptography.hazmat.primitives.block import ciphers, modes

from .utils import generate_encrypt_test
from ...utils import load_nist_vectors_from_file


class TestBlowfish(object):
test_ECB = generate_encrypt_test(
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: modes.ECB(),
)

test_CBC = generate_encrypt_test(
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: modes.CBC(binascii.unhexlify(iv)),
)

test_OFB = generate_encrypt_test(
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: modes.OFB(binascii.unhexlify(iv)),
)

test_CFB = generate_encrypt_test(
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: modes.CFB(binascii.unhexlify(iv)),
)
15 changes: 14 additions & 1 deletion tests/hazmat/primitives/test_ciphers.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import pytest

from cryptography.hazmat.primitives.block.ciphers import (
AES, Camellia, TripleDES,
AES, Camellia, TripleDES, Blowfish
)


Expand Down Expand Up @@ -65,3 +65,16 @@ def test_key_size(self, key):
def test_invalid_key_size(self):
with pytest.raises(ValueError):
TripleDES(binascii.unhexlify(b"0" * 12))


class TestBlowfish(object):
@pytest.mark.parametrize(("key", "keysize"), [
(b"0" * (keysize // 4), keysize) for keysize in range(32, 449, 8)
])
def test_key_size(self, key, keysize):
cipher = Blowfish(binascii.unhexlify(key))
assert cipher.key_size == keysize

def test_invalid_key_size(self):
with pytest.raises(ValueError):
Blowfish(binascii.unhexlify(b"0" * 6))
11 changes: 11 additions & 0 deletions tests/hazmat/primitives/vectors/ciphers/Blowfish/bf-cbc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Reformatted from https://www.schneier.com/code/vectors.txt
# to look like the NIST vectors

[ENCRYPT]

COUNT = 0
KEY = 0123456789ABCDEFF0E1D2C3B4A59687
IV = FEDCBA9876543210
# this pt is implicitly padded with null bytes for CBC
PLAINTEXT = 37363534333231204E6F77206973207468652074696D6520666F722000000000
CIPHERTEXT = 6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC
10 changes: 10 additions & 0 deletions tests/hazmat/primitives/vectors/ciphers/Blowfish/bf-cfb.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Reformatted from https://www.schneier.com/code/vectors.txt
# to look like the NIST vectors

[ENCRYPT]

COUNT = 0
KEY = 0123456789ABCDEFF0E1D2C3B4A59687
IV = FEDCBA9876543210
PLAINTEXT = 37363534333231204E6F77206973207468652074696D6520666F722000
CIPHERTEXT = E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3
Loading