关于c#:BigInteger.Parse()大量读取麻烦

BigInteger.Parse() trouble reading in large numbers

目前,我正在尝试进行这项挑战(http://cryptopals.com/sets/1/challenges/1),在C_中完成任务时遇到了一些困难。我似乎无法将数字解析为大整数。

所以代码如下:

1
2
3
4
5
6
7
8
        string output ="";
        BigInteger hexValue = BigInteger.Parse("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6");

        output = Convert.ToBase64String(hexValue.ToByteArray());
        Console.WriteLine(hexValue);
        Console.WriteLine(output);
        Console.ReadKey();
        return"";

目前我遇到的问题是,当我运行程序时,它会因错误而失败。

System.FormatException: 'The value could not be parsed.' and I am not entirely sure why.

那么,将一个大整数从一个字符串转换成一个bigint的合适方法是什么呢?


最初的问题

BigInteger.Parse方法要求值为十进制,而不是十六进制。你可以通过传入NumberStyles.HexNumber来"修复"这个问题。

使用BigInteger解决这个更大的问题

如果你只是想把一个十六进制数字串转换成字节,我就完全避免使用BigInteger。例如,首先,如果原始字节数组以零开头,则可能会出现问题。零不会出现在结果字节数组中。(示例输入:"0001"-您希望得到两个字节,但在说服它解析十六进制之后,您只能得到一个字节。)

即使你没有丢失任何信息,你从BigInteger.ToByteArray()收到的byte[]也不是你所期望的。例如,考虑这个代码,它只是将数据转换为byte[]并通过BitConverter返回到hex:

1
2
3
BigInteger bigInt = BigInteger.Parse("1234567890ABCDEF", NumberStyles.HexNumber);
byte[] bytes = bigInt.ToByteArray();
Console.WriteLine(BitConverter.ToString(bytes));

其输出是"ef-cd-ab-90-78-56-34-12",因为BigInteger.ToByteArray以小尾数顺序返回数据:

The individual bytes in the array returned by this method appear in little-endian order. That is, the lower-order bytes of the value precede the higher-order bytes.

这不是您想要的-因为它意味着原始字符串的最后一部分是字节数组的第一部分,等等。

完全避开BigInteger

相反,将数据直接解析为字节数组,如本问题、本问题或其他各种问题。我不会在这里重现代码,但它非常简单,根据您是要创建简单的源代码还是高效的程序,有不同的选项。

转换的一般建议

一般来说,最好避免数据的中间表示,除非您确信在这个过程中不会丢失信息——就像这里所说的那样。在将结果转换为base64之前,可以将十六进制字符串转换为字节数组,因为这不是有损转换。

所以你的转换是:

  • EDOCX1(hex)到BigInteger:有损性(在前导0非常重要的情况下,正如在这种情况下一样)
  • BigIntegerbyte[]无损耗
  • byte[]String的(base64):无损耗

我建议:

  • String(hex)to byte[]:无损耗(假设你有偶数个要转换的nybble,这通常是一个合理的假设)
  • byte[]String的(base64):无损耗


使用NumberStyles.HexNumber

1
2
3
BigInteger.Parse("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6",
                 NumberStyles.HexNumber,
                 CultureInfo.InvariantCulture);

如果您的数字应该总是正数,请在字符串中添加一个前导零。


问题是输入不是十进制而是十六进制,因此需要传递一个附加的参数进行解析:

1
2
3
BigInteger number = BigInteger.Parse(
            hexString,
            NumberStyles.AllowHexSpecifier);