0

I am trying to translate the program below to Python. In the end the Python code should produce the same passphrase output as the Perl variant.

#!/usr/bin/env perl
use Crypt::CBC;

my $key = 'key to the gates'; 
my $cipher = Crypt::CBC->new(
    -key    => $key,
    -cipher => 'Blowfish',
    -salt => '12341234'  
);
my $pass_phrase = "secret text";
print $cipher->encrypt_hex($pass_phrase),"\n";
print unpack('H*', $cipher->key()), "\n";
print unpack('H*', $cipher->iv()), "\n";
print unpack('H*', $cipher->salt()), "\n";
print unpack('H*', $cipher->keysize()), "\n";

#output:
#pass:53616c7465645f5f31323334313233344c0ad60f0eb9fdffc46b5cc02d76d473 <- hex enc "Salted__12341234<gibberish>"
#key:031f2cc96d063cf836ce42c77a8a3d25bdd959659d00a892a02b13930e92f47c82a7054256be4a0f1b3771bd36c07fe3ea4f6900f8ddebe5
#iv:f4d50b2385a2a996
#salt:3132333431323334
#keysize:3536

Below is my python code than that decrypts successfully, but encrypts unsuccessfully. The successfull decryption of the perl passphrase was mostly for verify input params. (Taking IV straight from perl and removing Crypt::CBC's added 16 char of salt before decrypting made it work, various posts on SO helped me..).

Then is the unsuccessful attempt to encryption passhphrase and generate the same output as perl. I think i just need to use the right combination of the verified input params to get it working...maybe the salt should be padded? Or padding in general is wrong? Or iv input should not be hexlified? (it need to be 8 chars..)

Any input is appreciated!

!/usr/bin/env python
from Crypto.Cipher import Blowfish
from binascii import hexlify, unhexlify
from struct import pack
import base64

# working decryption
passphrase =  unhexlify("53616c7465645f5f31323334313233344c0ad60f0eb9fdffc46b5cc02d76d473"[32:])
key = unhexlify("031f2cc96d063cf836ce42c77a8a3d25bdd959659d00a892a02b13930e92f47c82a7054256be4a0f1b3771bd36c07fe3ea4f6900f8ddebe5")
iv  = unhexlify('f4d50b2385a2a996')
num_padding = ord(Blowfish.new(key, Blowfish.MODE_CBC, iv).decrypt(passphrase)[-1])
print Blowfish.new(key, Blowfish.MODE_CBC, iv).decrypt(passphrase)[:(-1*num_padding)]

# --- non working encryption!
passphrase2 = "secret text"
key2 = 'key to the gates'
iv2  = unhexlify('f4d50b2385a2a996')
plength = Blowfish.block_size - len(passphrase2) % Blowfish.block_size
padding = [plength] * plength
pad_str = passphrase2 + pack('b' * plength, *padding)
cipher = Blowfish.new(key2, Blowfish.MODE_CBC, iv2)
print hexlify("Salted__12341234"+cipher.encrypt(pad_str))

#output:
#secret text
#53616c7465645f5f31323334313233346aa3f2169677cbf282b1330b46da3114

1 Answers1

0

I guess you are not supposed to answer your own question, but i leave it here anyway:) I think maybe padding was off in the original code, not really sure. This time i used the nice "Padding" lib https://pypi.python.org/pypi/Padding

from Crypto.Cipher import Blowfish
from binascii import hexlify, unhexlify
import Padding 

class BlowFishCipher:
    def __init__( self, key,iv,salt ):
    self.key = unhexlify(key)
    self.iv = unhexlify(iv)
    self.salt = unhexlify(salt)
def encrypt( self, raw ):
    raw = Padding.appendPadding(raw, BS)
    cipher = Blowfish.new( self.key, Blowfish.MODE_CBC, self.iv )
    return hexlify("Salted__"+self.salt+cipher.encrypt(raw))
def decrypt( self, enc):
    enc = unhexlify(enc)
    cipher = Blowfish.new(self.key, Blowfish.MODE_CBC, self.iv )
    return Padding.removePadding(cipher.decrypt( enc), BS)

if __name__== "__main__":
    BS = Blowfish.block_size
    key_perl = "031f2cc96d063cf836ce42c77a8a3d25bdd959659d00a892a02b13930e92f47c82a7054256be4a0f1b3771bd36c07fe3ea4f6900f8ddebe5"
    iv_perl = "f4d50b2385a2a996"
    salt_perl= "3132333431323334"
    passphrase_perl = "53616c7465645f5f31323334313233344c0ad60f0eb9fdffc46b5cc02d76d473"
    # remove "Salted__12341234" from passhphrase_perl by [32:]  
    passphrase = passphrase_perl[32:]
    decryptor = BlowFishCipher(key_perl,iv_perl,salt_perl)
    plaintext = decryptor.decrypt(passphrase)
    print "decrypted        {:>70}".format(plaintext)
    ciphertext = "secret text"
    encodedtext = decryptor.encrypt(ciphertext)
    print "encrypted pyhton {:>70}".format(encodedtext)
    print "encrypted perl   {:>70}".format(passphrase_perl)

decrypted secret text

encrypted pyhton 53616c7465645f5f31323334313233344c0ad60f0eb9fdffc46b5cc02d76d473

encrypted perl 53616c7465645f5f31323334313233344c0ad60f0eb9fdffc46b5cc02d76d473