donglu5612 2017-02-14 02:37
浏览 55
已采纳

PHP mcrypt - mcrypt在连接字符串中分别隐藏每个字符串

I have currently started to work with PHP with a Java background and came accross some issues. I am using mcrypt for a basic encryption using mcrypt_encrypt ( string $cipher , string $key , string $data , string $mode [, string $iv ] ) the encryption works successfully but there is a case where I need to concatenate 2 strings and then encrypt them but when I do this the output is just as if I had encrypted each string separately then concatenated them afterwards and not before the encryption. What I am doing is this :

function base64url_encode($data) {
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

function base64url_decode($data) {
    return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
}

function encryptCode($data){
    return mcrypt_encrypt( MCRYPT_DES , '12345678' , $data , 'cbc' ,'87654321'); 
}

function decryptCode($data){
    return mcrypt_decrypt( MCRYPT_DES , '12345678' , $data , 'cbc' ,'87654321'); 
}

$id = 'Q2JmDpmqjNmGT4FJ2EkXXITOgc31ZA52';
$toAdd = 'hellothere';
$base64Decoded = base64url_decode($id);
$decrypted = decryptCode($base64Decoded);
$decrypted = $decrypted.$toAdd;
$encryptedID = encryptCode($decrypted);
$base64Encoded = base64url_encode($encryptedID);
print_r($base64Encoded);

and then the output is : Q2JmDpmqjNmGT4FJ2EkXXITOgc31ZA52DG4cvxVuJVnkcrINN0Zt9g

I am aware of the weakness of DES but I need it in this case so please no comments about that. Thanks to all for your help.

  • 写回答

1条回答 默认 最新

  • dongyimeng3764 2017-02-14 03:02
    关注

    I can't say why mcrypt_encrypt is not respecting the CBC mode of operation (without seeing actual input and output, I'm assuming it's acting as ECB). Perhaps mcrypt's default null padding algorithm (0x00) is causing issues? I can say that mcrypt is abandonware for ~10 years now, so I wouldn't spend the energy trying to figure that out. Use libsodium, or, failing that, at least openssl.

    This post by Scott Arciszewski explains the issues with mcrypt in PHP.

    Update

    I ran your provided code and made some additional modifications to demonstrate that CBC mode was working as expected. Here is the code I ran:

    function base64url_encode($data) {
        return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
    }
    
    function base64url_decode($data) {
        return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
    }
    
    function encryptCode($data){
        return mcrypt_encrypt( MCRYPT_DES , '12345678' , $data , 'cbc' ,'87654321'); 
    }
    
    function decryptCode($data){
        return mcrypt_decrypt( MCRYPT_DES , '12345678' , $data , 'cbc' ,'87654321'); 
    }
    
    $id = 'Q2JmDpmqjNmGT4FJ2EkXXITOgc31ZA52';
    $base64Decoded = base64url_decode($id);
    $decrypted = decryptCode($base64Decoded);
    print_r($decrypted."
    ");
    print_r("
    
    ");
    
    # Make the new plaintext string
    $toAdd = 'hellothere';
    $additionalCipherText = encryptCode($toAdd);
    $additionalEncoded = base64url_encode($additionalCipherText);
    print_r("Additional cipher text: ".$additionalEncoded."
    ");
    print_r("
    
    ");
    
    # Concatenate the plaintext and encrypt
    $plaintext = $decrypted.$toAdd;
    $cipherText = encryptCode($plaintext);
    $base64Encoded = base64url_encode($cipherText);
    print_r("     New cipher text: ".$base64Encoded."
    ");
    print_r("Original cipher text: ".$id.$additionalEncoded."
    ");
    print_r("
    
    ");
    
    # Try the reverse order
    $plaintext = $toAdd.$decrypted;
    $cipherText = encryptCode($plaintext);
    $base64Encoded = base64url_encode($cipherText);
    print_r("     New cipher text: ".$base64Encoded."
    ");
    print_r("Original cipher text: ".$additionalEncoded.$id."
    ");
    

    I received the following output:

    ��t
    anEncryptedId
    
    
    Additional cipher text: paTJPP5mr-65c1OKybvB1A
    
    
         New cipher text: Q2JmDpmqjNmGT4FJ2EkXXITOgc31ZA52DG4cvxVuJVnkcrINN0Zt9g
    Original cipher text: Q2JmDpmqjNmGT4FJ2EkXXITOgc31ZA52paTJPP5mr-65c1OKybvB1A
    
    
         New cipher text: paTJPP5mr-69piYC2Ep0BM1tiph63ZFqdg_whovwRh0-4AD37H2JPQ
    Original cipher text: paTJPP5mr-65c1OKybvB1AQ2JmDpmqjNmGT4FJ2EkXXITOgc31ZA52
    

    As you can see, encrypting just $toAdd by itself and concatenating with the provided cipher text is not the same as concatenating the plaintexts and encrypting. You can see that the 33rd character of the Base64-encoded output is where the differences start, which makes sense: the 33rd character of Base64 is the start of the 25th byte of the cipher text. In DES, the block size is 64 bits / 8 bytes, so the first three blocks will be encrypted identically. The following block would be modified by the ^ operation of the previous block's cipher text where the IV would otherwise be used.

    I repeated this operation with the opposite order of the two plaintext inputs. Again, I saw that the first 12 characters of the Base64 output (12 chars -> 8 bytes) are identical, and then there are differences. This is expected, as the original plaintext does not end on a full block boundary, so the new "second block" is not identical to the original "second block". The CBC operation works successfully here to "jumble" the second block.

    I would double check the code around the handling of this data and ensure that you are performing the operations (and in the order) you think you are.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器