将C++函数转换为C#

5

我正在尝试将以下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);

我发现在C#中,(int)strtol(tmp, NULL, 16)等同于int.Parse(tmp, "x"),并且snprintf相当于String.Format,但是对于其余的部分我不确定。如何将这个片段移植到C#?

已更新我的回答,并添加了一些有用的信息。 - sehe
我假设QString是QT类?我添加了标签。 - morechilli
2个回答

4

编辑 我怀疑你的代码实际上是对输入数据进行MD5摘要。请参见下面基于这个假设的代码片段。

翻译步骤

以下是一些应该很好用的提示1

问: 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);

将(v * m) % 0x10的结果转换为十六进制字符串,并将其存储在tmp中。

{
    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 此处未明确优化,只是提供一些快速提示;根据需要进行优化。


我使用了 System.Security 添加了一个 MD5 实现,因为我怀疑(在查找原始代码后)它可能是 MD5。注意:这只是一种怀疑(我不太认识散列函数的代码)。 - sehe
肯定不是MD5,因为在使用这个函数之前我已经计算了MD5,并且这个函数的输入是MD5哈希值。但还是谢谢您给出的一些提示。 - Cfaniak
我们能否请把这个小字体去掉? - Security Hound

0
一些更多的提示: t是一个两个字节的缓冲区,你只写入第一个字节,留下一个尾随的nul。所以t始终是一个仅包含一个字符的字符串,并且您正在逐个字符处理十六进制数。所以我认为
tmp[0] = input[i].toAscii();
t = a + (int)(strtol(tmp, NULL, 16));

这大致相当于 int t = a + Convert.ToInt32(input.substring(i, 1), 16); - 从输入中取出一个数字并将其十六进制值加到已从表格中查找的a上。(我假设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");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接