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 乌班图ip地址配置及远程SSH
  • ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
  • ¥15 PSPICE制作一个加法器
  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?