目前我正在尝试完成这个挑战 (http://cryptopals.com/sets/1/challenges/1),但我在用 C# 完成任务时遇到了一些问题。我似乎无法将数字解析为一个大整数。
所以代码如下所示:
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:
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.
这不是您想要的 - 因为这意味着原始字符串的 last 部分是字节数组的 first 部分,等等。
完全避免 BigInteger
相反,将数据直接 解析为字节数组,如 this question 或 this one 或其他各种形式。我不会在这里重现代码,但它足够简单,根据您是要创建简单的源代码还是要创建高效的程序,有不同的选项。
关于转化的一般建议
一般来说,避免数据的中间表示是个好主意,除非您绝对确信您不会在此过程中丢失信息 - 就像您在这里那样。在将结果转换为 base64 之前将十六进制字符串转换为字节数组很好,因为这不是有损转换。
因此您的转化是:
String
(十六进制)到BigInteger
:有损(在前导 0 很重要的情况下,因为它们在这种情况下)BigInteger
到byte[]
:无损byte[]
到String
(base64):无损
我推荐:
String
(十六进制)到byte[]
:无损(假设您有偶数个字节要转换,这通常是一个合理的假设)byte[]
到String
(base64):无损
关于c# - BigInteger.Parse() 无法读取大量数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49719699/