Fast, efficient Blowfish cipher implementation in pure Python (3.4+).

Overview

PyPI CI

blowfish

This module implements the Blowfish cipher using only Python (3.4+).

Blowfish is a block cipher that can be used for symmetric-key encryption. It has a 8-byte block size and supports a variable-length key, from 4 to 56 bytes. It's fast, free and has been analyzed considerably. It was designed by Bruce Schneier and more details about it can be found at <https://www.schneier.com/blowfish.html>.

Dependencies

  • Python 3.4+

Features

  • Fast (well, as fast you can possibly go using only Python 3.4+)
  • Efficient; generators/iterators are used liberally to reduce memory usage
  • Cipher-Block Chaining (CBC) mode
  • Cipher-Block Chaining with Ciphertext Stealing (CBC-CTS) mode
  • Propagating Cipher-Block Chaining (PCBC) mode
  • Cipher Feedback (CFB) mode
  • Output Feedback (OFB) mode
  • Counter (CTR) mode
  • Electronic Codebook (ECB) mode
  • Electronic Codebook with Ciphertext Stealing (ECB-CTS) mode

Installation

If you just need a Blowfish cipher in your Python project, feel free to manually copy blowfish.py to your package directory (license permitting).

distutils

To install the module to your Python distribution, use the included distutils script:

$ python setup.py install

pip

Stable versions can be installed from pypi using pip:

$ pip install blowfish

pip can also install the latest development version directly from git:

$ pip install 'git+https://github.com/jashandeep-sohi/python-blowfish.git'

Development

Want to add a mode of operation? Speed up encryption?

Make your changes to a clone of the repository at https://github.com/jashandeep-sohi/python-blowfish and send me a pull request.

Tests

Tests are written using the Python unittest framework. All tests currently reside in the test.py file and can be run using the distutils script:

$ python setup.py test

Bugs

Are you having problems? Please let me know at https://github.com/jashandeep-sohi/python-blowfish/issues

Usage

Warning

Cryptography is complex, so please don't use this module in anything critical without understanding what you are doing and checking the source code to make sure it is doing what you want it to.

Note

This is just a quick overview on how to use the module. For detailed documentation please see the docstrings in the module.

First create a Cipher object with a key.

import blowfish

cipher = blowfish.Cipher(b"Key must be between 4 and 56 bytes long.")

By default this initializes a Blowfish cipher that will interpret bytes using the big-endian byte order. Should the need arrise to use the little-endian byte order, provide "little" as the second argument.

cipher_little = blowfish.Cipher(b"my key", byte_order = "little")

Block

To encrypt or decrypt a block of data (8 bytes), use the encrypt_block or decrypt_block methods of the Cipher object.

from os import urandom

block = urandom(8)

ciphertext = cipher.encrypt_block(block)
plaintext = cipher.decrypt_block(ciphertext)

assert block == plaintext

As these methods can only operate on 8 bytes of data, they're of little practical use. Instead, use one of the implemented modes of operation.

Cipher-Block Chaining Mode (CBC)

To encrypt or decrypt data in CBC mode, use encrypt_cbc or decrypt_cbc methods of the Cipher object. CBC mode can only operate on data that is a multiple of the block-size in length.

data = urandom(10 * 8) # data to encrypt
iv = urandom(8) # initialization vector

data_encrypted = b"".join(cipher.encrypt_cbc(data, iv))
data_decrypted = b"".join(cipher.decrypt_cbc(data_encrypted, iv))

assert data == data_decrypted

Cipher-Block Chaining with Ciphertext Stealing (CBC-CTS)

To encrypt or decrypt data in CBC-CTS mode, use encrypt_cbc_cts or decrypt_cbc_cts methods of the Cipher object. CBC-CTS mode can operate on data of any length greater than 8 bytes.

data = urandom(10 * 8 + 6) # data to encrypt
iv = urandom(8) # initialization vector

data_encrypted = b"".join(cipher.encrypt_cbc_cts(data, iv))
data_decrypted = b"".join(cipher.decrypt_cbc_cts(data_encrypted, iv))

assert data == data_decrypted

Propagating Cipher-Block Chaining Mode (PCBC)

To encrypt or decrypt data in PCBC mode, use encrypt_pcbc or decrypt_pcbc methods of the Cipher object. PCBC mode can only operate on data that is a multiple of the block-size in length.

data = urandom(10 * 8) # data to encrypt
iv = urandom(8) # initialization vector

data_encrypted = b"".join(cipher.encrypt_pcbc(data, iv))
data_decrypted = b"".join(cipher.decrypt_pcbc(data_encrypted, iv))

assert data == data_decrypted

Cipher Feedback Mode (CFB)

To encrypt or decrypt data in CFB mode, use encrypt_cfb or decrypt_cfb methods of the Cipher object. CFB mode can operate on data of any length.

data = urandom(10 * 8 + 7) # data to encrypt
iv = urandom(8) # initialization vector

data_encrypted = b"".join(cipher.encrypt_cfb(data, iv))
data_decrypted = b"".join(cipher.decrypt_cfb(data_encrypted, iv))

assert data == data_decrypted

Output Feedback Mode (OFB)

To encrypt or decrypt data in OFB mode, use encrypt_ofb or decrypt_ofb methods of the Cipher object. OFB mode can operate on data of any length.

data = urandom(10 * 8 + 1) # data to encrypt
iv = urandom(8) # initialization vector

data_encrypted = b"".join(cipher.encrypt_ofb(data, iv))
data_decrypted = b"".join(cipher.decrypt_ofb(data_encrypted, iv))

assert data == data_decrypted

Counter Mode (CTR)

To encrypt or decrypt data in CTR mode, use encrypt_ctr or decrypt_ctr methods of the Cipher object. CTR mode can operate on data of any length. Although you can use any counter you want, a simple increment by one counter is secure and the most popular. So for convenience sake a simple increment by one counter is implemented by the blowfish.ctr_counter function. However, you should implement your own for optimization purposes.

from operator import xor

data = urandom(10 * 8 + 2) # data to encrypt

# increment by one counters
nonce = int.from_bytes(urandom(8), "big")
enc_counter = blowfish.ctr_counter(nonce, f = xor)
dec_counter = blowfish.ctr_counter(nonce, f = xor)

data_encrypted = b"".join(cipher.encrypt_ctr(data, enc_counter))
data_decrypted = b"".join(cipher.decrypt_ctr(data_encrypted, dec_counter))

assert data == data_decrypted

Electronic Codebook Mode (ECB)

Note: ECB mode does not provide strong confidentiality, regardless of the cipher, and is not recommended for use in applications.

To encrypt or decrypt data in ECB mode, use encrypt_ecb or decrypt_ecb methods of the Cipher object. ECB mode can only operate on data that is a multiple of the block-size in length.

data = urandom(10 * 8) # data to encrypt

data_encrypted = b"".join(cipher.encrypt_ecb(data))
data_decrypted = b"".join(cipher.decrypt_ecb(data_encrypted))

assert data == data_decrypted

Electronic Codebook Mode with Cipher Text Stealing (ECB-CTS)

Note: the warning pertaining to ECB mode above also applies to ECB-CTS.

To encrypt or decrypt data in ECB-CTS mode, use encrypt_ecb_cts or decrypt_ebc_cts methods of the Cipher object. ECB-CTS mode can operate on data of any length greater than 8 bytes.

data = urandom(10 * 8 + 5) # data to encrypt

data_encrypted = b"".join(cipher.encrypt_ecb_cts(data))
data_decrypted = b"".join(cipher.decrypt_ecb_cts(data_encrypted))

assert data == data_decrypted
Comments
  • Bad Pi!

    Bad Pi!

    After using 'PI' sign in source, i can't install module via pip on Kubuntu/Pythin3.5, and QPython/Python3.5. When i remove 'PI' sign, importing of module works well. `

    import blowfish Traceback (most recent call last): File "", line 1, in File "blowfish.py", line 32 SyntaxError: Non-ASCII character '\xcf' in file blowfish.py on line 32, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

    `

    opened by Moneetor 3
  • Bytes to str and back, ctr_counter

    Bytes to str and back, ctr_counter

    Hoping you might be able to point me in the right direction.

    I'm using encrypt_ctr successfully, however the storage medium I'm using requires me to store into str. I'm not sure what encoding/decoding to use to make it go to a str, and then be able to be converted from str back to bytes for decrypt_ctr to handle.

    At the moment, decryption is sort of like:

    encryptedBytes = b"".join(encryptedBytesList)
    with open(metadata["filename"], "wb") as openFile:
                decoded_data = b"".join(self.cipher.decrypt_ctr(data, self.encrypt_counter))
                openFile.write(decoded_data)
    

    And encryption, sort of like:

    with open(os.path.expanduser("~/reddiSync/") + filename, "rb") as openFile:
                data = openFile.read()
                encoded_data = b"".join(self.cipher.encrypt_ctr(data, self.encrypt_counter))
            encoded_list = [encoded_data[i:i+1000] for i in range(0, len(data), 1000)]
            return [str(x) for x in encoded_list]
    

    Its ensuring the original conversion to str that's the issue.

    UTF-8 isn't compatible with some of the bytes produced, so is there an encoding I could use?

    opened by shakna-israel 2
  • DES_set_key_checked in blowfish

    DES_set_key_checked in blowfish

    I encountered a problem about DES_cfb64_encrypt, i use "cipher.encrypt_cfb(data, iv)" but incorrect result. i found that no similar function in cipher.

    opened by jmpews 2
  • Docs - electronic code book

    Docs - electronic code book

    One of the first items under "Usage" on the README is how to use ECB mode. I would like to suggest that this section should be accompanied by a warning that ECB mode is inherently insecure and does not provide strong secrecy. It is in fact very vulnerable to cryptanlysis and secrecy can be compromised even without side-channels.

    I would also recommend that this section not be placed first in the documentation.

    A set of images on wikipedia illustrates dramatically the way ECB mode leaks data: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#ECB

    opened by leifurhauks 1
  • Add a 'test' command to setup.py to run unittests

    Add a 'test' command to setup.py to run unittests

    Now tests can be run using the distutils script:

    $ python setup.py test -vv
    running test
    running build_py
    test_decrypt_block (test.Cipher) ... ok
    test_encrypt_block (test.Cipher) ... ok
    test_decrypt_block (test.CipherLittleEndian) ... ok
    test_encrypt_block (test.CipherLittleEndian) ... ok
    test_cbc_cts_mode (test.ModesOfOperation) ... ok
    test_cbc_mode (test.ModesOfOperation) ... ok
    test_cfb_mode (test.ModesOfOperation) ... ok
    test_ctr_mode (test.ModesOfOperation) ... ok
    test_ecb_cts_mode (test.ModesOfOperation) ... ok
    test_ecb_mode (test.ModesOfOperation) ... ok
    test_ofb_mode (test.ModesOfOperation) ... ok
    test_pcbc_mode (test.ModesOfOperation) ... ok
    
    ----------------------------------------------------------------------
    Ran 12 tests in 1.816s
    
    OK
    
    enhancement 
    opened by jashandeep-sohi 0
  • Fix little-endian byte-order input encryption and decryption.

    Fix little-endian byte-order input encryption and decryption.

    This fixes bug https://github.com/jashandeep-sohi/python-blowfish/issues/9.

    u4_1_struct is used to split 32-bit integers into 4 bytes. The higher 8 bits should be the first byte, the next 8 bits should be the next byte, and so on. So, it should always be in big-endian byte order and not be dependent on the byte_order option.

    opened by jashandeep-sohi 0
  • Add custom exceptions for incorrect input data

    Add custom exceptions for incorrect input data

    Currently, the generic struct.error is raised when the input data is not the correct length. Raise a custom exception so it's a bit more clear as to why the call failed.

    enhancement 
    opened by jashandeep-sohi 0
  • Need example for encrypt/decrypt for a large file (say 1mb)

    Need example for encrypt/decrypt for a large file (say 1mb)

    Hello there this is just awesome. However, I am in a hurry and looing for a sample code which encrypts and decrypts a big file what is the cost of encryption? is it O(n) ? thanks Sriram

    opened by sriramb12 0
This repo provides a package to automatically select a random seed based on ancient Chinese Xuanxue

🤞 Random Luck Deep learning is acturally the alchemy. This repo provides a package to automatically select a random seed based on ancient Chinese Xua

Tong Zhu(朱桐) 33 Jan 03, 2023
Word document generator with python

In this study, real world data is anonymized. The content is completely different, but the structure is the same. It was a script I prepared for the backend of a work using UiPath.

Ezgi Turalı 3 Jan 30, 2022
Elliptic curve cryptography (ed25519) beginner tutorials in Python 3

ed25519_tutorials Elliptic curve cryptography (ed25519) beginner tutorials in Python 3 Instructions Just download the repo and read the tutorial files

6 Dec 27, 2022
An MkDocs plugin that simplifies configuring page titles and their order

MkDocs Awesome Pages Plugin An MkDocs plugin that simplifies configuring page titles and their order The awesome-pages plugin allows you to customize

Lukas Geiter 282 Dec 28, 2022
EasyModerationKit is an open-source framework designed to moderate and filter inappropriate content.

EasyModerationKit is a public transparency statement. It declares any repositories and legalities used in the EasyModeration system. It allows for implementing EasyModeration into an advanced charact

Aarav 1 Jan 16, 2022
Python 3 wrapper for the Vultr API v2.0

Vultr Python Python wrapper for the Vultr API. https://www.vultr.com https://www.vultr.com/api This is currently a WIP and not complete, but has some

CSSNR 6 Apr 28, 2022
Pydocstringformatter - A tool to automatically format Python docstrings that tries to follow recommendations from PEP 8 and PEP 257.

Pydocstringformatter A tool to automatically format Python docstrings that tries to follow recommendations from PEP 8 and PEP 257. See What it does fo

Daniël van Noord 31 Dec 29, 2022
learn python in 100 days, a simple step could be follow from beginner to master of every aspect of python programming and project also include side project which you can use as demo project for your personal portfolio

learn python in 100 days, a simple step could be follow from beginner to master of every aspect of python programming and project also include side project which you can use as demo project for your

BDFD 6 Nov 05, 2022
Python solutions to solve practical business problems.

Python Business Analytics Also instead of "watching" you can join the link-letter, it's already being sent out to about 90 people and you are free to

Derek Snow 357 Dec 26, 2022
This is a repository for "100 days of code challenge" projects. You can reach all projects from beginner to professional which are written in Python.

100 Days of Code It's a challenge that aims to gain code practice and enhance programming knowledge. Day #1 Create a Band Name Generator It's actually

SelenNB 2 May 12, 2022
level2-data-annotation_cv-level2-cv-15 created by GitHub Classroom

[AI Tech 3기 Level2 P Stage] 글자 검출 대회 팀원 소개 김규리_T3016 박정현_T3094 석진혁_T3109 손정균_T3111 이현진_T3174 임종현_T3182 Overview OCR (Optimal Character Recognition) 기술

6 Jun 10, 2022
Markdown documentation generator from Google docstrings

mkgendocs A Python package for automatically generating documentation pages in markdown for Python source files by parsing Google style docstring. The

Davide Nunes 44 Dec 18, 2022
advance python series: Data Classes, OOPs, python

Working With Pydantic - Built-in Data Process ========================== Normal way to process data (reading json file): the normal princiople, it's f

Phung Hưng Binh 1 Nov 08, 2021
freeCodeCamp Scientific Computing with Python Project for Certification.

Polygon_Area_Calculator freeCodeCamp Python Project freeCodeCamp Scientific Computing with Python Project for Certification. In this project you will

Rajdeep Mondal 1 Dec 23, 2021
Showing potential issues with merge strategies

Showing potential issues with merge strategies Context There are two branches in this repo: main and a feature branch feat/inverting-method (not the b

Rubén 2 Dec 20, 2021
Variable Transformer Calculator

✠ VASCO - VAriable tranSformer CalculatOr Software que calcula informações de transformadores feita para a matéria de "Conversão Eletromecânica de Ene

Arthur Cordeiro Andrade 2 Feb 12, 2022
Preview title and other information about links sent to chats.

Link Preview A small plugin for Nicotine+ to display preview information like title and description about links sent in chats. Plugin created with Nic

Nick 0 Sep 05, 2021
Mkdocs obsidian publish - Publish your obsidian vault through a python script

Mkdocs Obsidian Mkdocs Obsidian is an association between a python script and a

Mara 49 Jan 09, 2023
This is the data scrapped of all the pitches made up potential startup's to established bussiness tycoons of India with all the details of Investments made, equity share, Name of investor etc.

SharkTankInvestor This is the data scrapped of all the pitches made up potential startup's to established bussiness tycoons of India with all the deta

Subradip Poddar 2 Aug 02, 2022
An interview engine for businesses, interview those who are actually qualified and are worth your time!

easyInterview V0.8B An interview engine for businesses, interview those who are actually qualified and are worth your time! Quick Overview You/the com

Vatsal Shukla 1 Nov 19, 2021