处理BigInteger问题

假设以下Diffie-Hellman信息也可以在此页面上找到

1)p

string givenp = "00e655cc9e04f3bebae76ecca77143ef5c4451876615a9f8b4f712b8f3bdf47ee7f717c09bb5b2b66450831367d9dcf85f9f0528bcd5318fb1dab2f23ce77c48b6b7381eed13e80a14cca6b30b5e37ffe53db15e2d6b727a2efcee51893678d50e9a89166a359e574c4c3ca5e59fae79924fe6f186b36a2ebde9bf09fe4de50453"; BigInteger p = new BigInteger(HexToBytesv2(givenp)); 

2)G

 BigInteger g = new BigInteger(2); 

3)商家私钥

 string merchantPrivateKeyHEX = "48887dfd090d175e33beea29e7b38334299289069f9ab492b67807905faa98d96d22d79205bef03f14af093f1797b904734132c34a388fdc79e20497bfa1465fec2aac4fabdf3bb0c9be8685d20f7bfe0346a9abdf7fa89838c3fa9ca6abdb70bea66795ab6699cc154db59490e4159f142f7bddff603c1d3d6c4fff8177e11d"; BigInteger a = new BigInteger(HexToBytesv2(merchantPrivateKeyHEX)); 

使用公式publickey = g ^ a mod p我应该获得初始链接中提供的公钥,但是在执行时

 BigInteger A = BigInteger.ModPow(g, a, p); ToHex(A.ToByteArray()) 

我得到的结果是

 00f85c41e84446ecfe43c9911df31d3cf60d83642afd496b741363290139badf75f8b8c5c010dda2446dd483dc553b6c2698c16c9d082391677785f81d54bc9c7c45f8b6d5bdb3e49fec7f5522b880c8c753fb7d3ff2c81e47dcb27d52842def40a812dc95cc679575baf237a955ee9944bd0797326f2a0a58c6c087f9b0b9e82c 

代替

 00d9abd78c93dfddeb920d57d6513126d8f1118c9237a45101408dbffe6cfd95b011a016e4e0ab8aef0601e836a452b8bb88be7ca71e4f22f97aa65f8358ee69348d1227d65db6e53641d1a6542aa4be4b4adc75fac816af79a8e3f5097f8313e7b725df37eadc8c774e2033dfa99c95ccef333bf402b066198c30481e2a83875c 

有任何想法吗? 我一定很遗憾,但我不确定那可能是什么。

PS添加正在使用的function:

  public static byte[] HexToBytesv2(this string hex) { if (hex.Length % 2 == 1) hex = '0' + hex; byte[] ret = new byte[hex.Length / 2]; for (int i = 0; i < ret.Length; i++) ret[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16); return ret; } public static string ToHex(byte[] ba) { StringBuilder hex = new StringBuilder(ba.Length * 2); foreach (byte b in ba) hex.AppendFormat("{0:x2}", b); return hex.ToString(); } 

这是一个endian问题。

我已经调整了你的编码和解码,现在得到你正在寻找的答案:

 public static byte[] HexToBytesv2(string hex) { if (hex.Length % 2 == 1) hex = '0' + hex; byte[] ret = new byte[hex.Length / 2]; for (int i = 0; i < ret.Length; i++) ret[i] = Convert.ToByte(hex.Substring(hex.Length - (i+1) * 2, 2), 16); return ret; } public static string ToHex( byte[] bytes) { var sb = new StringBuilder(); foreach (var b in bytes.Reverse()) { sb.AppendFormat("{0:x2}", b); } return sb.ToString(); } 

仅供我使用LinqPad,主要方法是来自问题的代码(经过调整),检查数据在途中没有丢失任何内容:

 void Main() { string givenp = "00e655cc9e04f3bebae76ecca77143ef5c4451876615a9f8b4f712b8f3bdf47ee7f717c09bb5b2b66450831367d9dcf85f9f0528bcd5318fb1dab2f23ce77c48b6b7381eed13e80a14cca6b30b5e37ffe53db15e2d6b727a2efcee51893678d50e9a89166a359e574c4c3ca5e59fae79924fe6f186b36a2ebde9bf09fe4de50453"; BigInteger p = new BigInteger(HexToBytesv2(givenp)); (ToHex(p.ToByteArray()) == "00e655cc9e04f3bebae76ecca77143ef5c4451876615a9f8b4f712b8f3bdf47ee7f717c09bb5b2b66450831367d9dcf85f9f0528bcd5318fb1dab2f23ce77c48b6b7381eed13e80a14cca6b30b5e37ffe53db15e2d6b727a2efcee51893678d50e9a89166a359e574c4c3ca5e59fae79924fe6f186b36a2ebde9bf09fe4de50453").Dump(); BigInteger g = new BigInteger(2); string merchantPrivateKeyHEX = "48887dfd090d175e33beea29e7b38334299289069f9ab492b67807905faa98d96d22d79205bef03f14af093f1797b904734132c34a388fdc79e20497bfa1465fec2aac4fabdf3bb0c9be8685d20f7bfe0346a9abdf7fa89838c3fa9ca6abdb70bea66795ab6699cc154db59490e4159f142f7bddff603c1d3d6c4fff8177e11d"; BigInteger a = new BigInteger(HexToBytesv2(merchantPrivateKeyHEX)); (ToHex(a.ToByteArray()) == "48887dfd090d175e33beea29e7b38334299289069f9ab492b67807905faa98d96d22d79205bef03f14af093f1797b904734132c34a388fdc79e20497bfa1465fec2aac4fabdf3bb0c9be8685d20f7bfe0346a9abdf7fa89838c3fa9ca6abdb70bea66795ab6699cc154db59490e4159f142f7bddff603c1d3d6c4fff8177e11d").Dump(); BigInteger A = BigInteger.ModPow(g, a, p); (ToHex(A.ToByteArray()) == "00f85c41e84446ecfe43c9911df31d3cf60d83642afd496b741363290139badf75f8b8c5c010dda2446dd483dc553b6c2698c16c9d082391677785f81d54bc9c7c45f8b6d5bdb3e49fec7f5522b880c8c753fb7d3ff2c81e47dcb27d52842def40a812dc95cc679575baf237a955ee9944bd0797326f2a0a58c6c087f9b0b9e82c").Dump(); (ToHex(A.ToByteArray()) == "00d9abd78c93dfddeb920d57d6513126d8f1118c9237a45101408dbffe6cfd95b011a016e4e0ab8aef0601e836a452b8bb88be7ca71e4f22f97aa65f8358ee69348d1227d65db6e53641d1a6542aa4be4b4adc75fac816af79a8e3f5097f8313e7b725df37eadc8c774e2033dfa99c95ccef333bf402b066198c30481e2a83875c").Dump(); } 

在我交换排序之前,并且从原始问题中包含.Concat(new byte[] { 0 }).ToArray() ,输出为:

 True True True False 

而现在它是:

 True True False True 

您看到的另一个问题是BigInteger.ParseByte[]构造函数总是期望第一个半字节或最后一个字节的最高位分别为符号位。 因此,您需要分别包含额外的0字符或字节以避免这种情况。

你正在做一些不必要的转换,他们在某处引入了一个错误。

如果删除断开的stringbyte[]BigIntegerbyte[]string步骤并让BigInteger本身为您完成工作,那么您将生成预期的结果:

 string givenp = "00e655cc9e04f3bebae76ecca77143ef5c4451876615a9f8b4f712b8f3bdf47ee7f717c09bb5b2b66450831367d9dcf85f9f0528bcd5318fb1dab2f23ce77c48b6b7381eed13e80a14cca6b30b5e37ffe53db15e2d6b727a2efcee51893678d50e9a89166a359e574c4c3ca5e59fae79924fe6f186b36a2ebde9bf09fe4de50453"; var p = BigInteger.Parse(givenp, NumberStyles.HexNumber); var g = new BigInteger(2); var merchantPrivateKeyHEX = "48887dfd090d175e33beea29e7b38334299289069f9ab492b67807905faa98d96d22d79205bef03f14af093f1797b904734132c34a388fdc79e20497bfa1465fec2aac4fabdf3bb0c9be8685d20f7bfe0346a9abdf7fa89838c3fa9ca6abdb70bea66795ab6699cc154db59490e4159f142f7bddff603c1d3d6c4fff8177e11d"; var a = BigInteger.Parse(merchantPrivateKeyHEX, NumberStyles.HexNumber); var publicKey = BigInteger.ModPow(g, a, p); Console.WriteLine(publicKey.ToString("x")); // displays 0d9abd7...