1
votes

On one side I have a texts encrypted/decrypted with Perl's Crypt::CBC

my $key = 'key to the gates'; 
my $cipher = Crypt::CBC->new(
    -key    => $key,
    -cipher => 'Blowfish',
    -salt   => '12341234'  
);

On the other side I have Python's PyCrypto that I need to decode the data from Perl, but also send text that the Perl cipher can read given the encryption.

I have the key from the Perl program, and encrypt_hex:ed passphrases from Perl sent to the Python system.

But Python seems to absolutely want to have the IV to do its job

cipher = Blowfish.new( self.key, Blowfish.MODE_CBC, self.iv )
        return hexlify(cipher.encrypt(raw))

However, the Crypt::CBC documnetation seems to indicate that the IV is there already

"salt" -- Combine the passphrase with an 8-byte random value to generate both the block cipher key and the IV from the provided passphrase. The salt will be appended to the beginning of the data stream allowing decryption to regenerate both the key and IV given the correct passphrase.

Is there any way to extract the IV from the key/passphrase via PyCrypto? Or does IV have to be sent separately in some way?

This might be a naive question but I don't work with this every day.

I know I can get the IV from the Perl side, but I really want to extract it on Python side if possible.

1
I'm sorry you didn't like my edit, but remember that the primary purpose of your question and any solutions you may be offered is to help other people with a similar problem, which means the subject line should help to guide those people towards this page.Borodin
Oops! I am new here and did not know other persons could edit your posts, so i thought i had done something and tried to rollback. Now that i know, you are most welcome to re-edit if you like ;)Göran Ström

1 Answers

2
votes

Crypt::CBC claims OpenSSL compatibility. This means that it performs an OpenSSL specific BytesToKey password-based key derivation function (PBKDF). During this derivation the IV is calculated as well. So the key you've provided for Crypt::CBC is actually treated as a password.

You have to lookup an implementation of EVP_BytesToKey and integrate that into your program. You can start with this code from GitHub:

def bytes_to_key(data, salt="12345678"):
    # Simplified version of M2Crypto.m2.bytes_to_key(). Based on:
    # https://github.com/ajmirsky/M2Crypto/blob/master/M2Crypto/EVP.py#L105
    # http://stackoverflow.com/questions/8008253/c-sharp-version-of-openssl-evp-bytestokey-method
    assert len(salt) == 8, len(salt)
    data += salt
    key = md5(data).digest()
    key += md5(key + data).digest()
    return key

Then take the first bytes for the key, and the next 8 bytes for the IV. But note the following statement for Crypt:CBC:

If -keysize is not specified, then Crypt::CBC will use the maximum length Blowfish key size of 56 bytes (448 bits).

So you may need a few more key += md5(key + data).digest() calls as the md5 output is only 128 bits.