【问题标题】:How to calculate RSA's additional private key parameters from P and Q?如何从 P 和 Q 计算 RSA 的附加私钥参数?
【发布时间】:2016-02-07 14:42:52
【问题描述】:

在读取缺少多个 RSA 参数(DP、DQ、InverseQ、D)的 RSA 私钥 blob 时,我如何从 提供的参数中计算这些缺少的参数?我已经读到可以根据提供的 P 和 Q 计算这些值,但我不知道如何计算它们。

导入此密钥时,我在尝试使用声称数据不存在的私钥时遇到错误(当然提供了 P 和 Q)。

我需要能够在多个平台上执行此操作,所以恐怕这会让我陷入需要拥有实际代码来计算它们的阵营。

在 C# 中

【问题讨论】:

  • Wikipedia article on RSA 显示了如何计算它们中的每一个。
  • 谢谢。我希望有更接近 C# 的东西,因为我对自己的 BigInteger 数学技能没有信心,也不想自己弄清楚。
  • this question的答案和this question的答案结合起来,你就有答案了。
  • 那么你有 P、Q 和 e,就这些了吗?
  • 我有 P、Q、publicExponent、模数。我没有 DP、DQ、InverseQ 或 D。

标签: c# cryptography rsa


【解决方案1】:

这是可以从 P、Q 和公钥数据构造一整套RSAParameters 的 C# 代码。我们假设这个方法的参数是大端的(就像 RSAParameters 一样)。

private static RSAParameters Create(byte[] p, byte[] q, byte[] exponent, byte[] modulus)
{
    var addlParameters = GetFullPrivateParameters(
        p: new BigInteger(CopyAndReverse(p)),
        q: new BigInteger(CopyAndReverse(q)),
        e: new BigInteger(CopyAndReverse(exponent)),
        modulus: new BigInteger(CopyAndReverse(modulus)));

    return new RSAParameters
    {
        P = p,
        Q = q,
        Exponent = exponent,
        Modulus = modulus,
        D = addlParameters.D,
        DP = addlParameters.DP,
        DQ = addlParameters.DQ,
        InverseQ = addlParameters.InverseQ,
    };
}

private static RSAParameters GetFullPrivateParameters(BigInteger p, BigInteger q, BigInteger e, BigInteger modulus)
{
    var n = p * q;
    var phiOfN = n - p - q + 1; // OR: (p - 1) * (q - 1);

    var d = ModInverse(e, phiOfN);
    Assert.Equal(1, (d * e) % phiOfN);

    var dp = d % (p - 1);
    var dq = d % (q - 1);

    var qInv = ModInverse(q, p);
    //Assert.Equal(1, (qInv * q) % p);

    return new RSAParameters
    {
        D = CopyAndReverse(d.ToByteArray()),
        DP = CopyAndReverse(dp.ToByteArray()),
        DQ = CopyAndReverse(dq.ToByteArray()),
        InverseQ = CopyAndReverse(qInv.ToByteArray()),
    };
}


/// <summary>
/// Calculates the modular multiplicative inverse of <paramref name="a"/> modulo <paramref name="m"/>
/// using the extended Euclidean algorithm.
/// </summary>
/// <remarks>
/// This implementation comes from the pseudocode defining the inverse(a, n) function at
/// https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
/// </remarks>
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;
}

private static byte[] CopyAndReverse(byte[] data)
{
    byte[] reversed = new byte[data.Length];
    Array.Copy(data, 0, reversed, 0, data.Length);
    Array.Reverse(reversed);
    return reversed;
}

【讨论】:

  • 这种模块化逆方法对我不起作用。它总是返回一个不正确的结果,并且对其执行Assert.AreEqual(1, (iq * q) % p); 的断言总是失败。
猜你喜欢
  • 1970-01-01
  • 2014-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-08
相关资源
最近更新 更多