Конвертировать функцию C ++ в C # - PullRequest
5 голосов
/ 08 ноября 2011

Я пытаюсь перенести следующую функцию C ++ на C #:

QString Engine::FDigest(const QString & input)
{
    if(input.size() != 32) return "";

    int idx[] = {0xe, 0x3, 0x6, 0x8, 0x2},
        mul[] = {2, 2, 5, 4, 3},
        add[] = {0x0, 0xd, 0x10, 0xb, 0x5},
        a, m, i, t, v;

    QString b;
    char tmp[2] = { 0, 0 };

    for(int j = 0; j <= 4; j++)
    {
        a = add[j];
        m = mul[j];
        i = idx[j];

        tmp[0] = input[i].toAscii();
        t = a + (int)(strtol(tmp, NULL, 16));
        v = (int)(strtol(input.mid(t, 2).toLocal8Bit(), NULL, 16));

        snprintf(tmp, 2, "%x", (v * m) % 0x10);
        b += tmp;
    }

    return b;
}

Часть этого кода легко портировать, но у меня проблемы с этой частью:

tmp[0] = input[i].toAscii();
t = a + (int)(strtol(tmp, NULL, 16));
v = (int)(strtol(input.mid(t, 2).toLocal8Bit(), NULL, 16));

snprintf(tmp, 2, "%x", (v * m) % 0x10);

Я обнаружил, что (int)strtol(tmp, NULL, 16) равно int.Parse(tmp, "x") в C # и snprintf равно String.Format, однако я не уверен в остальном.

Как я могу портировать этот фрагмент на C #?

Ответы [ 2 ]

5 голосов
/ 08 ноября 2011

Редактировать У меня есть подозрение, что ваш код на самом деле выполняет дайджест MD5 входных данных. Ниже приведен фрагмент кода, основанный на этом предположении.

шаги перевода

Несколько советов, которые должны хорошо работать 1

Q: tmp[0] = input[i].toAscii();

bytes[] ascii = ASCIIEncoding.GetBytes(input);
tmp[0] = ascii[i];

Q: t = a + (int)(strtol(tmp, NULL, 16));

t = a + int.Parse(string.Format("{0}{1}", tmp[0], tmp[1]),
               System.Globalization.NumberStyles.HexNumber);

Q: v = (int)(strtol(input.mid(t, 2).toLocal8Bit(), NULL, 16));

Понятия не имею о toLocal8bit, нужно будет прочитать документацию Qt ...

Q: snprintf(tmp, 2, "%x", (v * m) % 0x10);

{
    string tmptext = ((v*m % 16)).ToString("X2");
    tmp[0] = tmptext[0];
    tmp[1] = tmptext[1];
}

Что если ... это просто MD5?

Вы можете попробовать это напрямую, чтобы увидеть, достигает ли он того, что вам нужно:

using System;

public string FDigest(string input)
{
   MD5 md5 = System.Security.Cryptography.MD5.Create();
   byte[] ascii = System.Text.Encoding.ASCII.GetBytes (input);
   byte[] hash  = md5.ComputeHash (ascii);

   // Convert the byte array to hexadecimal string
   StringBuilder sb = new StringBuilder();
   for (int i = 0; i < hash.Length; i++)
       sb.Append (hash[i].ToString ("X2")); // "x2" for lowercase
   return sb.ToString();
}

1 явно не оптимизирован, предназначен для быстрых подсказок; при необходимости оптимизировать

0 голосов
/ 08 ноября 2011

Еще несколько подсказок:

t - это двухбайтовый буфер, и вы всегда записываете только первый байт, оставляя завершающий ноль.Таким образом, t всегда является строкой ровно одного символа, и вы обрабатываете шестнадцатеричное число по одному символу за раз.Поэтому я думаю

tmp[0] = input[i].toAscii();
t = a + (int)(strtol(tmp, NULL, 16));

это примерно int t = a + Convert.ToInt32(input.substring(i, 1), 16); - возьмите одну цифру из ввода и добавьте ее шестнадцатеричное значение к значению, которое вы посмотрели из таблицы.(Я предполагаю, что toAscii просто отображает символ QString, который уже является шестнадцатеричной цифрой, в ASCII для strtol, поэтому, если у вас уже есть строка шестнадцатеричных цифр, это нормально.)

Далее

v = (int)(strtol(input.mid(t, 2).toLocal8Bit(), NULL, 16));

это означает, что нужно найти два символа из ввода со смещением t, то есть input.substring(t, 2), а затем снова преобразовать их в шестнадцатеричное целое число.v = Convert.ToInt32(input.substring(t, 2), 16); Теперь, как это бывает, я думаю, что вы все равно будете использовать здесь вторую цифру, так как вычисление (v * a) % 0x10, но эй.Если снова мы работаем с QString из шестнадцатеричных цифр, то toLocal8Bit должно быть тем же преобразованием, что и toAscii - я не понимаю, почему ваш код имеет две разные функции здесь.

Наконец, преобразуйте эти значения в однуцифра в tmp, затем добавьте это к b

snprintf(tmp, 2, "%x", (v * m) % 0x10);
b += tmp;

(2 - длина буфера, и так как нам нужен завершающий nul, записывается только 1), т.е.

int digit = (v * m) % 0x10;
b += digit.ToString("x");

следует сделать.Я лично написал мод 16 как логическое и, & 0xf, поскольку он предназначен для сокращения значения до одной цифры.

Обратите внимание, что в вашем коде i никогда не устанавливается - яугадайте, что это цикл или что-то, что вы пропустили для краткости?

Итак, в итоге

int t = a + Convert.ToInt32(input.substring(i, 1), 16);
int v = Convert.ToInt32(input.substring(t, 2), 16);
int nextDigit = (v * m) & 0xf;
b += nextDigit.ToString("x");
...