How to decrypt using Blowfish in Pycrypto?

Manuj Mittal picture Manuj Mittal · Jan 27, 2016 · Viewed 12.7k times · Source

I found one example to encrypt the data but I am unable to find any example on how to decrypt it.

Encryption Example:

>>> from Crypto.Cipher import Blowfish
>>> from Crypto import Random
>>> from struct import pack
>>>
>>> bs = Blowfish.block_size
>>> key = b'An arbitrarily long key'
>>> iv = Random.new().read(bs)
>>> cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv)
>>> plaintext = b'docendo discimus '
>>> plen = bs - divmod(len(plaintext),bs)[1]
>>> padding = [plen]*plen
>>> padding = pack('b'*plen, *padding)
>>> msg = iv + cipher.encrypt(plaintext + padding)

I did not find any example on how to decrypt.

Answer

Artjom B. picture Artjom B. · Jan 27, 2016

Let's make some observations:

  • CBC mode needs an Initialization Vector (IV) that has the same length as the block size
  • the full plaintext is the actual message including padding (PKCS#5 padding in RFC 2898 Sec. 6.1.1 Step 4)
  • the IV is prepended to the ciphertext

What needs to be done:

  • Use the same key
  • Read the IV before creating the decryptor
  • Remove padding after decryption by looking at the last byte, evaluate that as an integer and remove as many bytes from the end of the plaintext

Code:

from Crypto.Cipher import Blowfish
from struct import pack

bs = Blowfish.block_size
key = b'An arbitrarily long key'
ciphertext = b'\xe2:\x141vp\x05\x92\xd7\xfa\xb5@\xda\x05w.\xaaRG+U+\xc5G\x08\xdf\xf4Xua\x88\x1b'
iv = ciphertext[:bs]
ciphertext = ciphertext[bs:]

cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv)
msg = cipher.decrypt(ciphertext)

last_byte = msg[-1]
msg = msg[:- (last_byte if type(last_byte) is int else ord(last_byte))]
print(repr(msg))