RSAParameters计算私有参数

时间:2017-05-10 05:34:15

标签: c# rsa .net-standard

我正在尝试计算.NET Standard上RSAParameters结构的私有参数。我做了一个单元测试来测试我的计算:

[TestMethod]
public void DQDPTest()
{
    RSA rsa = RSA.Create();
    RSAParameters rsaParams = rsa.ExportParameters(true);

    BigInteger p = new BigInteger(rsaParams.P.Reverse().ToArray());
    BigInteger q = new BigInteger(rsaParams.Q.Reverse().ToArray());
    BigInteger d = new BigInteger(rsaParams.D.Reverse().ToArray());
    BigInteger dq = new BigInteger(rsaParams.DQ.Reverse().ToArray());
    BigInteger dp = new BigInteger(rsaParams.DP.Reverse().ToArray());
    Assert.AreEqual(dq, d % (q - 1));
    Assert.AreEqual(dp, d % (p - 1));
}

但是,断言始终失败,我无法弄清楚原因,因为DQDP应该包含这些值。为什么会这样?

我有一个类似的方法来计算InverseQ,这也不起作用:

[TestMethod]
public void ModInverseTest()
{
    RSA rsa = RSA.Create();
    RSAParameters rsaParams = rsa.ExportParameters(true);

    BigInteger p = new BigInteger(rsaParams.P.Reverse().ToArray());
    BigInteger q = new BigInteger(rsaParams.Q.Reverse().ToArray());
    BigInteger iq = new BigInteger(rsaParams.InverseQ.Reverse().ToArray());
    BigInteger ciq = Extensions.ModInverse(q, p);
    Assert.AreEqual(1, (iq * q) % p);
    Assert.AreEqual(1, (ciq * q) % p);
    Assert.AreEqual(iq, ciq);
}

public static BigInteger ModInverse(BigInteger a, BigInteger n)
{
    BigInteger t = 0, nt = 1, r = n, nr = a;

    if (n < 0)
    {
        n = -n;
    }

    if (a < 0)
    {
        a = n - (-a % n);
    }

    while (nr != 0)
    {
        var quot = r / nr;

        var tmp = nt; nt = t - quot * nt; t = tmp;
        tmp = nr; nr = r - quot * nr; r = tmp;
    }

    if (r > 1) throw new ArgumentException(nameof(a) + " is not convertible.");
    if (t < 0) t = t + n;
    return t;
}

ModInverseTest()中的断言也一直失败,这意味着要么我做错了,要么这些值根本不是我认为的。再次,为什么会发生这种情况?

1 个答案:

答案 0 :(得分:4)

你对P和Q的价值几乎肯定是负面的,这很可能会抛弃其他一切。这是因为C#BigInteger构造函数不允许您指定正/负,因此具有最重要位设置的最重要字节意味着它是负数。解决方案是添加一个填充字节(0x00),使符号位保持清晰。

private static System.Numerics.BigInteger GetBigInteger(byte[] parameter)
{
    byte[] signPadded = new byte[parameter.Length + 1];
    Buffer.BlockCopy(parameter, 0, signPadded, 1, parameter.Length);
    Array.Reverse(signPadded);
    return new System.Numerics.BigInteger(signPadded);
}
相关问题