【问题标题】:Processing BigInteger issues处理 BigInteger 问题
【发布时间】:2015-09-14 14:33:30
【问题描述】:

假设以下 Diffie-Hellman 信息也可以在 page 上找到

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

有什么想法吗?我一定错过了很明显的东西,但我不确定那可能是什么。

附:添加正在使用的函数:

 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();

    }

【问题讨论】:

  • 这与 Diffie Hellman 有什么关系?您是否遇到过您认为是由执行按位运算的某些问题引起的错误?为什么不使用 .NET 的内置密码学或 OpenSSL.Net 库?
  • 使用的算法是 Diffie Hellman 算法。由于缺乏在线示例,这是我最简单的方法。
  • 该问题仅显示 Hex2Byte 转换和返回,这与 DH 无关。例如,谷歌搜索“Diffie Hellman c#”会返回 ECDiffieHellmanCng Class,并在备注部分提供各种示例。

标签: c# .net biginteger diffie-hellman


【解决方案1】:

这是一个字节序问题。

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

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 字符或字节以避免这种情况。

【讨论】:

  • 这确实很好用,但只有当我在创建 BigInteger 时附加一个 0 字节,比如 BigInteger p = new BigInteger(HexToBytesv2(givenp).Concat(new byte[] { 0 }).ToArray( ));生成的公钥当然以“00”开头,但除此之外它是正确的。如果我不包括零字节,那么它根本不起作用。如果没有更好的结果,我会将您的答案标记为正确
  • 当我删除.Concat(new byte[] { 0 }).ToArray()(你最初在你的问题中提到的)时,它对我来说同样有效。
  • 确实,这个例子也可以,可能是因为生成的公钥已经以“00”开头。知道为什么它不用于此输入:pastebin.com/Ry18dQF5
  • 您期待什么?我得到049cc92b93214bbf3785b2391f164b6a4a194c419d2299ca14eb1ac7c026827788e008a3a6dc9aa5a9520d39963ccb23fb173fdca8f93b0b507d2cdb1d6b22c912e861f55b6ec8b5d733563957ecb7daee8f8cde4cacf285d204dd72307db9b8a75481574ce8e0eecfd8c8e75e37c17d19ac8606882b4e983f46d7127967a0b2
  • 现在没有时间进一步研究它,但使用 LukeH 的代码,但使用来自 pastebin 的数字,00 仅在 givenp 前面加上我得到你期望的数字。我还没有研究 BigInteger 对其字节的期望,但var p = BigInteger.Parse(givenp, NumberStyles.HexNumber); var pdash = BigInteger.Parse("00"+givenp, NumberStyles.HexNumber); var q=pdash/p; var r=pdash%p;rq 产生一个非零值是-8(对于来自pastebin 的givenp)!
【解决方案2】:

您正在进行许多不必要的转换,并且它们在某处引入了错误。

如果您删除损坏的string-byte[]-BigInteger-byte[]-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...

【讨论】:

  • 虽然您对不必要的转换是正确的,但它们并不是导致问题的原因。建议的更改后仍然存在问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-24
  • 2020-05-24
  • 2016-06-22
  • 1970-01-01
相关资源
最近更新 更多