тройное шифрование не дает одинаковых результатов в PHP и C # - PullRequest
6 голосов
/ 18 марта 2010

Когда я шифрую с помощью C #, я получаю arTdPqWOg6VppOqUD6mGITjb24+x5vJjfAufNQ4DN7rVEtpDmhFnMeJGg4n5y1BN

static void Main(string[] args)
{
    Encoding byteEncoder = Encoding.Default;

    String key = "ShHhd8a08JhJiho98ayslcjh";
    String message = "Let us meet at 9 o'clock at the secret place.";

    String encryption = Encrypt(message, key, false);
    String decryption = Decrypt(encryption , key, false);

    Console.WriteLine("Message: {0}", message);
    Console.WriteLine("Encryption: {0}", encryption);
    Console.WriteLine("Decryption: {0}", decryption);
}

public static string Encrypt(string toEncrypt, string key, bool useHashing)
{
    byte[] keyArray;
    byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

    if (useHashing)
    {
        MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
        keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
    }
    else
        keyArray = UTF8Encoding.UTF8.GetBytes(key);

    TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
    tdes.Key = keyArray;
    tdes.Mode = CipherMode.ECB;
    tdes.Padding = PaddingMode.PKCS7;

    ICryptoTransform cTransform = tdes.CreateEncryptor();
    byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

    return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}

public static string Decrypt(string toDecrypt, string key, bool useHashing)
{
    byte[] keyArray;
    byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);

    if (useHashing)
    {
        MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
        keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
    }
    else
        keyArray = UTF8Encoding.UTF8.GetBytes(key);

    TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
    tdes.Key = keyArray;
    tdes.Mode = CipherMode.ECB;
    tdes.Padding = PaddingMode.PKCS7;

    ICryptoTransform cTransform = tdes.CreateDecryptor();
    byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

    return UTF8Encoding.UTF8.GetString(resultArray);
}

Когда я шифрую с помощью PHP, я получаю: arTdPqWOg6VppOqUD6mGITjb24+x5vJjfAufNQ4DN7rVEtpDmhFnMVM+W/WFlksR

    <?php
        $key = "ShHhd8a08JhJiho98ayslcjh";
        $input = "Let us meet at 9 o'clock at the secret place.";

        $td = mcrypt_module_open('tripledes', '', 'ecb', '');
        $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        mcrypt_generic_init($td, $key, $iv);
        $encrypted_data = mcrypt_generic($td, $input);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);

        echo base64_encode($encrypted_data);
    ?>

Я недостаточно разбираюсь в криптографии, чтобы понять, почему. Есть идеи? Спасибо.

Ответы [ 3 ]

7 голосов
/ 18 марта 2010

Питер прав. PHP просто дополняется нулями, а вы используете PKCS # 7 в коде C #. Вот код, который должен сделать это правильно:

function pkcs7_pad($text, $blocksize)
{
    $pad = $blocksize - (strlen($text) % $blocksize);
    return $text . str_repeat(chr($pad), $pad);
}

$input = pkcs7_pad("Let us meet at 9 o'clock at the secret place.", 16);

В качестве альтернативы, вы можете добавить это в свой код C #:

tdes.Padding = PaddingMode.Zeros;

и заставить его работать (хотя и немного менее надежно).

2 голосов
/ 18 марта 2010

Я не знаю PHP, и при этом я не анализировал ваш код C #, но, поскольку большая часть зашифрованной строки одинакова, может быть разница в заполнении данных? Может быть, PHP использует другой режим, чем PaddingMode.PKCS7, используемый в коде C #? (Это был бы комментарий, если бы я мог комментировать ...)

0 голосов
/ 18 марта 2010

В качестве дополнительного примечания: если вы используете ECB, вам не нужен IV. На самом деле, использование ECB в большинстве случаев является угрозой безопасности, поэтому вам действительно нужно использовать что-то другое, например, CBC, который использует IV. IV - это случайное, не секретное значение с тем же размером, что и размер блока шифрования (8 байтов для 3DES). Новый IV должен быть создан для каждого сообщения, и расшифровывающая сторона должна знать IV, который использовала шифрующая сторона. На практике IV отправляется вместе с зашифрованным сообщением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...