Search code examples
pythonphpmcryptblowfish

Why does blowfish code written in php give different results in Python?


I am not very skilled in encrypting and I have been using the php code I mentioned below for encrypting for a long time. Now I want to program the same code with python, but I couldn't find a solution.

<?PHP
  $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
  $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
  $encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, "secret", 
  utf8_encode('changeme'), MCRYPT_MODE_ECB, $iv);
  echo $encrypted_string;
?>

results: c811f6fe09f61abcf57623fc43554a17

I expected the code I specified below to give the same result, but the results are not the same, what could be the reason for this?

def PKCS5Padding(string):
    byteNum = len(string)
    packingLength = 8 - byteNum % 8
    appendage = chr(packingLength) * packingLength
    return string + appendage

def enc(string):
    key = b'secret'
    c1 = Blowfish.new(key, Blowfish.MODE_ECB)
    packedString = PKCS5Padding(string)
    return c1.decrypt(packedString.encode())
print(hashlib.md5(enc('changeme')).hexdigest())

results: 08c74df87caf3ed8456f0e01a4b7234b


Solution

  • You call c1.decrypt() in the Python code instead of c1.encrypt(), and the PHP code (inside mcrypt_encrypt()) just pads the plaintext to a multiple of 8 bytes with null bytes. The following gives the same result as the PHP code: md5(0x9da1192c5d3b3072) == 0xe3b3884a2e3986a01b8d750f9d724ff8

    def enc(plaintext):
        key = b'secret'
        c1 = Blowfish.new(key, Blowfish.MODE_ECB)
        encoded = plaintext.encode()
        padded = encoded.ljust((len(encoded) + 7) // 8 * 8, b'\0')
        return c1.encrypt(padded)