Should I Trim the Decrypted String after mcrypt_decrypt?

后端 未结 4 739
一整个雨季
一整个雨季 2021-02-07 20:40

I have a code that goes something like:

$cipher_alg = MCRYPT_RIJNDAEL_128;
$decrypted_string = mcrypt_decrypt($cipher_alg, $key, 
$encrypted_string , MCRYPT_MODE         


        
相关标签:
4条回答
  • 2021-02-07 20:46

    I had to encrypt/decrypt binary data. Unfortunately trim can break the binary data and trim legitimate bits that equate to a null character.

    To ensure the size of the binary data is the same before and after encryption, Rocket Hazmat posted a great answer here: How can I decrypt binary data that ended with NUL characters in PHP?

    Summary:

    // PKCS7 Padding
    $blocksize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
    $pad = $blocksize - (strlen($data) % $blocksize);
    $data .= str_repeat(chr($pad), $pad);
    
    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_ECB);
    
    
    /*  Then somewhere else in your code */
    $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted, MCRYPT_MODE_ECB);
    
    // PKCS7 Padding
    $strPad = ord($decrypted[strlen($decrypted)-1]);
    $newData = substr($decrypted, 0, -$strPad);
    

    I am not sure about the use of ECB versus CBC...

    0 讨论(0)
  • 2021-02-07 20:51

    After 24 hours of research, finally this worked for me:

    function removePadding($decryptedText){
        $strPad = ord($decryptedText[strlen($decryptedText)-1]);
        $decryptedText= substr($decryptedText, 0, -$strPad);
        return $decryptedText;
    }
    
    0 讨论(0)
  • 2021-02-07 21:03

    In my implementation of TripleDES, I found the decrypted string was padded with \5 or \6 characters. This wasn't the expected \0 or \4 characters mentioned above or in the PHP.net examples. To determine the ASCII value of the padding character use the ord() function. ord() works on a single character so use str_split() to break up a string or access the character directly with array notation - $string[5].

    Final trim result - trim($decrypt, "\0..\32");

    Final code result -

        $key        = "encryption key";
        $encrypt    = base64_decode($encrypt);
        $iv_size    = mcrypt_get_iv_size(MCRYPT_3DES, MCRYPT_MODE_ECB);
        $iv         = mcrypt_create_iv($iv_size, MCRYPT_RAND);
        $decrypt    = mcrypt_decrypt(MCRYPT_3DES, $key, $encrypt, MCRYPT_MODE_ECB, $iv);
        $final      = trim($decrypt, "\0..\32"); // removes potential null padding
    
    0 讨论(0)
  • 2021-02-07 21:08

    Actually both mcrypt_encrypt() and mcrypt_decrypt() as well as the other en-/decryption functons (like mcrypt_generic() or mdecrypt_generic()) do pad the $data parameter to a length of n * <<blocksize>>. The padding character is the NUL character (\x0 or \0) whereas the <<blocksize>> depends on the cipher and the block cipher modes used. You should have a look at Block cipher modes of operation and Padding (cryptography).

    The following is the output of mcrypt_get_block_size() for each of the available ciphers and modes on my machine. Obviously the function does not take into account that modes such as CFB, OFB and CTR do not require any special measures to handle messages whose lengths are not multiples of the block size, since they all work by XORing the plaintext with the output of the block cipher (quote from Wikipedia). CBC which is used in your example always requires that the final block is padded before encryption.

    cast-128
        cbc: 8 bytes
        cfb: 8 bytes
        ctr: 8 bytes
        ecb: 8 bytes
        ncfb: 8 bytes
        nofb: 8 bytes
        ofb: 8 bytes
        stream: not supported
    gost
        cbc: 8 bytes
        cfb: 8 bytes
        ctr: 8 bytes
        ecb: 8 bytes
        ncfb: 8 bytes
        nofb: 8 bytes
        ofb: 8 bytes
        stream: not supported
    rijndael-128
        cbc: 16 bytes
        cfb: 16 bytes
        ctr: 16 bytes
        ecb: 16 bytes
        ncfb: 16 bytes
        nofb: 16 bytes
        ofb: 16 bytes
        stream: not supported
    twofish
        cbc: 16 bytes
        cfb: 16 bytes
        ctr: 16 bytes
        ecb: 16 bytes
        ncfb: 16 bytes
        nofb: 16 bytes
        ofb: 16 bytes
        stream: not supported
    arcfour
        cbc: not supported
        cfb: not supported
        ctr: not supported
        ecb: not supported
        ncfb: not supported
        nofb: not supported
        ofb: not supported
        stream: 1 bytes
    cast-256
        cbc: 16 bytes
        cfb: 16 bytes
        ctr: 16 bytes
        ecb: 16 bytes
        ncfb: 16 bytes
        nofb: 16 bytes
        ofb: 16 bytes
        stream: not supported
    loki97
        cbc: 16 bytes
        cfb: 16 bytes
        ctr: 16 bytes
        ecb: 16 bytes
        ncfb: 16 bytes
        nofb: 16 bytes
        ofb: 16 bytes
        stream: not supported
    rijndael-192
        cbc: 24 bytes
        cfb: 24 bytes
        ctr: 24 bytes
        ecb: 24 bytes
        ncfb: 24 bytes
        nofb: 24 bytes
        ofb: 24 bytes
        stream: not supported
    saferplus
        cbc: 16 bytes
        cfb: 16 bytes
        ctr: 16 bytes
        ecb: 16 bytes
        ncfb: 16 bytes
        nofb: 16 bytes
        ofb: 16 bytes
        stream: not supported
    wake
        cbc: not supported
        cfb: not supported
        ctr: not supported
        ecb: not supported
        ncfb: not supported
        nofb: not supported
        ofb: not supported
        stream: 1 bytes
    blowfish-compat
        cbc: 8 bytes
        cfb: 8 bytes
        ctr: 8 bytes
        ecb: 8 bytes
        ncfb: 8 bytes
        nofb: 8 bytes
        ofb: 8 bytes
        stream: not supported
    des
        cbc: 8 bytes
        cfb: 8 bytes
        ctr: 8 bytes
        ecb: 8 bytes
        ncfb: 8 bytes
        nofb: 8 bytes
        ofb: 8 bytes
        stream: not supported
    rijndael-256
        cbc: 32 bytes
        cfb: 32 bytes
        ctr: 32 bytes
        ecb: 32 bytes
        ncfb: 32 bytes
        nofb: 32 bytes
        ofb: 32 bytes
        stream: not supported
    serpent
        cbc: 16 bytes
        cfb: 16 bytes
        ctr: 16 bytes
        ecb: 16 bytes
        ncfb: 16 bytes
        nofb: 16 bytes
        ofb: 16 bytes
        stream: not supported
    xtea
        cbc: 8 bytes
        cfb: 8 bytes
        ctr: 8 bytes
        ecb: 8 bytes
        ncfb: 8 bytes
        nofb: 8 bytes
        ofb: 8 bytes
        stream: not supported
    blowfish
        cbc: 8 bytes
        cfb: 8 bytes
        ctr: 8 bytes
        ecb: 8 bytes
        ncfb: 8 bytes
        nofb: 8 bytes
        ofb: 8 bytes
        stream: not supported
    enigma
        cbc: not supported
        cfb: not supported
        ctr: not supported
        ecb: not supported
        ncfb: not supported
        nofb: not supported
        ofb: not supported
        stream: 1 bytes
    rc2
        cbc: 8 bytes
        cfb: 8 bytes
        ctr: 8 bytes
        ecb: 8 bytes
        ncfb: 8 bytes
        nofb: 8 bytes
        ofb: 8 bytes
        stream: not supported
    tripledes
        cbc: 8 bytes
        cfb: 8 bytes
        ctr: 8 bytes
        ecb: 8 bytes
        ncfb: 8 bytes
        nofb: 8 bytes
        ofb: 8 bytes
        stream: not supported
    

    Therefore you have to rtrim() the output of the decryption functions to get the original string if your cipher operates on fixed length blocks:

    $output = rtrim($decrypted, "\0");
    
    0 讨论(0)
提交回复
热议问题