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.

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

报告相同问题?

悬赏问题

  • ¥50 易语言把MYSQL数据库中的数据添加至组合框
  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况