目前我正在尝试进行此挑战(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:'无法解析该值。' 并且我不完全确定原因。
那么,从字符串中获取大整数到BigInt的适当方法是什么?
答案 0 :(得分:7)
最初的问题
BigInteger.Parse
方法期望值为十进制,而不是十六进制。您可以通过传入NumberStyles.HexNumber
来“修复”。
使用BigInteger
进行此
如果您只是尝试将十六进制数字字符串转换为字节,我将完全避免使用BigInteger
。首先,如果原始字节数组以零开头,则可能会出现问题。零将不在结果字节数组中。 (示例输入:“0001” - 您希望获得两个字节,但在说服它解析十六进制后,您将只获得一个。)
即使您没有丢失任何信息,您从byte[]
收到的BigInteger.ToByteArray()
也不是您可能期望的。例如,请考虑此代码,该代码仅将数据转换为byte[]
并通过BitConverter
转换为十六进制:
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
以小端顺序返回数据:
此方法返回的数组中的各个字节以little-endian顺序显示。也就是说,该值的低位字节位于高位字节之前。
这不是你想要的 - 因为它意味着原始字符串的 last 部分是字节数组的 first 部分等。
完全避免BigInteger
而是将数据直接解析为字节数组,如this question或this one或其他各种数据。我不会在这里重现代码,但它很简单,具有不同的选项取决于您是否尝试创建简单的源代码或有效的程序。
有关转化的一般建议
一般来说,避免数据的中间表示是个好主意,除非你绝对相信你不会在这个过程中丢失信息 - 就像你在这里一样。在将结果转换为base64之前将十六进制字符串转换为字节数组是很好的,因为这不是有损转换。
所以你的转换是:
String
(十六进制)到BigInteger
:有损(在前导0的情况下是重要的,因为它们处于这种情况下)BigInteger
至byte[]
:没有损失byte[]
至String
(base64):not lossy 我建议:
String
(十六进制)到byte[]
:没有损失(假设你有一个偶数个nybbles要转换,这通常是一个合理的假设)byte[]
至String
(base64):not lossy 答案 1 :(得分:4)
使用NumberStyles.HexNumber
:
BigInteger.Parse("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6",
NumberStyles.HexNumber,
CultureInfo.InvariantCulture);
如果您的号码应该始终为正数,请在字符串中添加前导零。
答案 2 :(得分:3)
问题是输入不是十进制而是十六进制,因此您需要传递一个额外的参数进行解析:
BigInteger number = BigInteger.Parse(
hexString,
NumberStyles.AllowHexSpecifier);