Search code examples
pythonpycryptoblowfish

How to decrypt using Blowfish in Pycrypto?


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.


Solution

  • Let's make some observations:

    • CBC mode needs an Initialization Vector (IV) that has the same length as the block size (64bit for Blowfish)
    • 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))