Как этот криптографический код C # будет выглядеть в NodeJS? - PullRequest
1 голос
/ 17 января 2012

тройное шифрование, не дающее одинаковых результатов в PHP и C #

    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); 
    }  

В приведенном выше посте и коде есть довольно прямолинейная (или я так думал) логика для шифрования /расшифровать строку, используя 3DES и закрытый ключ.

Я нашел несколько примеров того, как реализовать нечто подобное в nodejs с использованием библиотеки crypt, но все, что я до сих пор пробовал, приводило к мусору (и по праву так).

Мысли?

ОБНОВЛЕНИЕ1:

Вот фрагмент кода C # для генерации данных, с которыми я работаю:

    String key = "abcdefghijklmnop";
    String text = "12345";
    String encrypted = Encrypt(text, key, false);
    //Returns "QI3I65+aWSk="

А вот последняя версия кода nodejs, с которым я работал:

    var crypto = require('crypto');
    var key = 'abcdefghijklmnop';
    var encrypted = 'QI3I65+aWSk=';
    var expected = '12345';

    var algs = [ 'des3', 'des-ede', 'des-ede3', 'des-ecb', 'aes-128-ecb'];
    for(var i in algs)
    {
      var decipher = crypto.createDecipher(algs[i], key);
      var result = ''
      result += decipher.update(encrypted, 'hex', 'binary');
      result += decipher.final('binary');

      console.log('Algorithm: ' + algs[i] 
        + ', Matched Expected: ' + (result === expected));
    }

.., который возвращает

    Algorithm: des3, Matched Expected: false
    Algorithm: des-ede, Matched Expected: false
    Algorithm: des-ede3, Matched Expected: false
    Algorithm: des-ecb, Matched Expected: false
    Algorithm: aes-128-ecb, Matched Expected: false

Я не совсем точно понял, что именнокакой алгоритм использовать (мой список был значительно длиннее в предыдущих попытках) теперь я был уверен относительно того, какую кодировку (двоичное / шестнадцатеричное) использовать.

Еще раз спасибо.

UPDATE2: Скопировано по методу Encrypt из указанного сообщения:

тройное шифрование, не дающее одинаковых результатов в PHP и C #

Ответы [ 2 ]

1 голос
/ 14 ноября 2012

Ну, мне потребовалось некоторое время, чтобы разобраться с этим.

Сначала о алгоритме DES, алгоритму DES требуется IV (начальный вектор) для шифрования, а также ключ .Алгоритм DES в System.Security.Cryptography будет генерировать IV случайным образом , если он не указан.А при дешифровании вам нужны и ключ и IV .

Вот почему ваш код никогда не будет работать, потому что ваша программа дешифрования просто не знает, что использовала IVшифрование, и сам сгенерирует другой IV, который не совпадает со случайным.

Во-вторых, во многих местах ваш код JavaScript неверен:

decipher.update(encrypted, 'hex', 'binary')

, где encrypted не закодированв шестнадцатеричном, но в base64, и вам нужно вывести результат как base64 вместо двоичного. читать документ .

['des3', 'des-ede', 'des-ede3', 'des-ecb', 'aes-128-ecb ']

, где все эти алгоритмы не совпадают с алгоритмом шифрования, который вы используете.Как вы указали для использования CipherMode.ECB, что не рекомендуется и openssh вообще не поддерживает, поэтому невозможно расшифровать.

Все складывается, ваш код не будет работать.

Вот правильная практика:

using System;
using System.Text;
using System.Security.Cryptography;

public class Test
{
    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);      

        var tdes = new TripleDESCryptoServiceProvider();
        tdes.Key = keyArray;     
        // tdes.Mode = CipherMode.CBC;  // which is default     
        // tdes.Padding = PaddingMode.PKCS7;  // which is default

        Console.WriteLine("iv: {0}", Convert.ToBase64String(tdes.IV));

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

    public static void Main()
    {
        Console.WriteLine("encrypted as: {0}", Encrypt("12345", "abcdefghijklmnop", false));
    }
}

, которая выводит

iv: pdMBMjdeFdo=
encrypted as: 3uDkdT6aQ3c=

и использует правильный алгоритм des-ede-cbc в узле.js:

var crypto = require('crypto');

var alg = 'des-ede-cbc';

var key = new Buffer('abcdefghijklmnop', 'utf-8');
var iv = new Buffer('pdMBMjdeFdo=', 'base64');

var encrypted = new Buffer('3uDkdT6aQ3c=', 'base64');
var source = '12345';

var cipher = crypto.createCipheriv(alg, key, iv);
var encoded = cipher.update(source, 'ascii', 'base64');
encoded += cipher.final('base64');

console.log(encoded, encrypted.toString('base64'));

var decipher = crypto.createDecipheriv(alg, key, iv);
var decoded = decipher.update(encrypted, 'binary', 'ascii');
decoded += decipher.final('ascii');

console.log(decoded, source);

который выводит

3uDkdT6aQ3c= 3uDkdT6aQ3c=
12345 12345

Теперь проблема решена.

0 голосов
/ 14 ноября 2012

Ваша входная кодировка выглядит так, как будто она должна быть 'base64' ... Стоит отметить, как уже упоминалось в вашем связанном вопросе, что также может быть разница в технике заполнения.

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