Skip to content

Instantly share code, notes, and snippets.

@adamb70
Created April 15, 2015 22:59
Show Gist options
  • Save adamb70/1f140573b37939e78eb5 to your computer and use it in GitHub Desktop.
Save adamb70/1f140573b37939e78eb5 to your computer and use it in GitHub Desktop.
Decrypt and encrypt Blowfish-Compat format files in Python 2.7
import os
from Crypto.Cipher import _Blowfish
from struct import pack
def encrypt(infilepath, outfilepath, key):
""" Encrypt the specified file with the specified
key and output to the chosen output file."""
size = os.path.getsize(infilepath)
infile = open(infilepath, 'rb')
outfile = open(outfilepath, 'wb')
data = infile.read()
infile.close()
if size % 8 > 0: # Add padding if size if not divisible by 8
extra = 8-(size % 8)
padding = [0]*extra
padding = pack('b'*extra, *padding)
data += padding
revdata = reversebytes(data)
encrypted_data = encryptbytes(revdata, key)
finaldata = reversebytes(encrypted_data)
outfile.write(finaldata)
outfile.close()
def encryptbytes(data, key):
cipher = _Blowfish.new(key, _Blowfish.MODE_ECB)
return cipher.encrypt(data)
def decrypt(infilepath, outfilepath, key):
""" Decrypt the specified file with the specified
key and output to the chosen output file"""
infile = open(infilepath, 'rb')
outfile = open(outfilepath, 'wb')
data = infile.read()
infile.close()
revdata = reversebytes(data)
decrypted_data = decryptbytes(revdata, key)
finaldata = reversebytes(decrypted_data)
end = len(finaldata) - 1
while str(finaldata[end]).encode('hex') == '00':
end -= 1
finaldata = finaldata[0:end]
outfile.write(finaldata)
outfile.close()
def decryptbytes(data, key):
cipher = _Blowfish.new(key, _Blowfish.MODE_ECB)
return cipher.decrypt(data)
def reversebytes(data):
""" Takes data and reverses byte order to fit
blowfish-compat format. For example, using
reversebytes('12345678') will return 43218765."""
data_size = 0
for n in data:
data_size += 1
reversedbytes = bytearray()
i = 0
for x in range(0, data_size/4):
a = (data[i:i+4])
i += 4
z = 0
n0 = a[z]
n1 = a[z+1]
n2 = a[z+2]
n3 = a[z+3]
reversedbytes.append(n3)
reversedbytes.append(n2)
reversedbytes.append(n1)
reversedbytes.append(n0)
return buffer(reversedbytes)
'''
############# USES #############
infilepath = 'input.txt'
outfilepath = 'output.txt'
key = "mykey"
encrypt(infilepath, outfilepath, key)
decrypt(infilepath, outfilepath, key)
'''
@marius-dr
Copy link

Thanks for the code, this was a life-saver.

@fengyu05
Copy link

fengyu05 commented Aug 2, 2017

I got this exception. Does it mean I need to pad my input file to 8 even first?

return cipher.decrypt(data)

ValueError: Input strings must be a multiple of 8 in length

@motapaolla
Copy link

Do you know how to make this encryption using mode CBC instead?

@awarmanf
Copy link

awarmanf commented Mar 14, 2018

When I encrypt the text file (file.txt) and decrypt again the unencrypted file (file.txt.unencrypted) is not same with the original one. Actually the last character is truncated.

[yudi@~]$ diff file.txt file.txt.unencrypted
109c109
<                 break
---
>                 break
\ No newline at end of file

@EliasMartinMouescaUTN
Copy link

Thanks!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment