2017-05-10 3 views
0

.NET標準のRSAParameters構造体のプライベートパラメータを計算しようとしています。私は私の計算をテストするためのユニットテストをした:プライベートパラメータを計算する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()でアサーションはまた、一貫し、私は間違って何かをやっているのいずれかを意味し、失敗、またはこれらの値は、単純ではありません私は彼らがだと思います。繰り返しますが、なぜこれが起こっていますか?

答えて

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); 
} 
関連する問題