Search code examples
phpc++crypto++3des

Crypto++ equivalent to PHP mcrypt_encrypt MCRYPT_3DES/MCRYPT_MODE_CBC


I have the following PHP code to encrypt a text using a key:

function des_ed3_crypt($msg, $key) {
   $bytes = array(0,0,0,0,0,0,0,0);
   $iv=implode(array_map('chr', $bytes));

   return mcrypt_encrypt(MCRYPT_3DES, $key, $msg, MCRYPT_MODE_CBC, $iv);
}

And my corresponding C++ function, using Crypto++ is:

std::string des_ed3_crypt(std::string const& msg, std::string const& key)
{
    unsigned char iv[8] = { 0 }; // 0-filled

    CryptoPP::CBC_Mode<CryptoPP::DES_EDE3>::Encryption e;
    e.SetKeyWithIV(reinterpret_cast<unsigned char const*>(key.c_str()),
                   key.size(), iv);

    std::string ret;

    CryptoPP::StringSource(msg, true,
            new CryptoPP::StreamTransformationFilter
                 (e, new CryptoPP::StringSink(ret)));

    return ret;
}

But they don't return the same encrypted text. I want the change the C++ code to make equivalent to the PHP code, and not the opposite.

For the following key and message:

$key = "keykeykeykeykeykeykeykey";
$msg = $key;

The PHP code returns a cyphertext of 24 bytes (base64 encoded as):

a78URfI6EV8m3sTaDDDrntI8VbjWHiwm

But C++ returns a cyphertext of 32 bytes, but with a matching prefix of 24-bytes (base64 encoded as):

a78URfI6EV8m3sTaDDDrntI8VbjWHiwm9M15+pzUnuM=

So, there's some extra bytes in the C++ version which I don't know where do they come from. I think it can be related with the padding scheme, but I don't know the padding scheme used by PHP.


Solution

  • Effectively, it was the padding. The PHP mcrypt_crypto function applies a zero-padding, so, I only have to specify to cryptopp that I want to apply a zero-padding to the encryption:

    std::string des_ed3_crypt(std::string const& msg, std::string const& key)
    {
        unsigned char iv[8] = { 0 }; // 0-filled
    
        CryptoPP::CBC_Mode<CryptoPP::DES_EDE3>::Encryption e;
        e.SetKeyWithIV(reinterpret_cast<unsigned char const*>(key.c_str()),
                       key.size(), iv);
    
        std::string ret;
    
        CryptoPP::StringSource(msg, true,
            new CryptoPP::StreamTransformationFilter
                (e, new CryptoPP::StringSink(ret),
                 CryptoPP::BlockPaddingSchemeDef::BlockPaddingScheme::ZEROS_PADDING));
    
        return ret;
    }