Почему модуль RSAParameters не равен произведению P и Q?
значения P и Q не соответствуют значению модуля .NET RSAParameters. Согласно алгоритму RSA и документации MSDN, он должен быть: P * Q = Modulus
Я создал 512-битную пару ключей RSA и экспортировал ее в XML, вызвав:
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(512);
rsa.ToXmlString(true);
это дало мне следующий XML-код:
<RSAKeyValue>
<Modulus>rcLI1XTfmXtX05zq67d1wujnUvevBu8dZ5Q5uBUi2mKndH1FZLYCKrjFaDTB/mXW1l5C74YycVLS6msY2NNJYw==</Modulus>
<Exponent>AQAB</Exponent>
<P>1dwGkK5POlcGCjQ96Se5NSPu/hCm8F5EYwyqRpLVzgk=</P>
<Q>0AAEMHBj7CP2XHfCG/RzGldw1GdsW13rTo3uEE9Dtws=</Q>
<DP>PO4jMLV4/TYuElowCW235twGC3zTE0jIUzAYk2LiZ4E=</DP>
<DQ>ELJ/o5fSHanBZCjk9zOHbezpDNQEmc0PT64LF1oVmIM=</DQ>
<InverseQ>NyCDwTra3LiUin05ZCGkdKLwReFC9L8Zf01ZfYabSfQ=</InverseQ>
<D>EWwFTPmx7aajULFcEJRNd2R4xSXWY8CX1ynSe7WK0BCH42wf/REOS9l8Oiyjf587BhGa3y8jGKhUD7fXANDxcQ==</D>
</RSAKeyValue>
теперь я успешно написал тестовую программу litte для шифрования, дешифрования, подписи и проверки данных.
в конце я добавил небольшой тест код:
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(512);
rsa.FromXmlString(key); // key = string with XML above
RSAParameters param = rsa.ExportParameters(true);
BigInteger p = new BigInteger(param.P);
BigInteger q = new BigInteger(param.Q);
BigInteger n = new BigInteger(param.Modulus);
BigInteger myN = BigInteger.Multiply(p, q);
Console.WriteLine("n = " + n.ToString());
Console.WriteLine("myN = " + myN.ToString());
, который дал нам следующий результат:
n = 5200154866521200075264779234483365112866265806746380532891861717388028374942014660490111623133775661411009378522295439774347383363048751390839618325234349
myN = 23508802329434377088477386089844302414021121047189424894399694701810500376591071843028984420422297770783276119852460021668188142735325512873796040092944
почему умножение P и Q не равно модулю?
Я уже проверил много вещей, таких как endian, encoding, BigInteger class, успешно зашифрованный, дешифрованный, подписанный, проверенный с помощью вышеуказанных ключей XML, но не могу найти никакого объяснения, почему P и Q умножаются не равно модулю...
может ли кто-нибудь помочь мне объяснить, почему P*Q не является модулем ?
все значения в удобочитаемом формате:
Modulus = 5200154866521200075264779234483365112866265806746380532891861717388028374942014660490111623133775661411009378522295439774347383363048751390839618325234349
Exponent = 65537
P = 4436260148159638728185416185189716006279182659244174640493183003717504785621
Q = 5299238895894527538601438806093945941831432623367272568173893997325464109264
DP = -57260184070162652127728137041376572684067529466727954512100856352006444159428
DQ = -56270397953566513533764063103154348713259844205844432469862161942601135050224
InverseQ = -5297700950752995201824767053303055736360972826004414985336436365496709603273
D = 5967761894604968266284398550464653556930604493620355473531132912985865955601309375321441883258487907574824598936524238049397825498463180877735939967118353
обновление:
в соответствии с ответом я написал небольшой метод расширения для класса .Net BigInteger для правильной работы с RSAParameters:
public static class BigIntegerExtension
{
public static BigInteger FromBase64(this BigInteger i, string base64)
{
byte[] p = Convert.FromBase64String(base64).Reverse().ToArray();
if (p[p.Length - 1] > 127)
{
Array.Resize(ref p, p.Length + 1);
p[p.Length - 1] = 0;
}
return new BigInteger(p);
}
public static BigInteger FromBigEndian(this BigInteger i, byte[] p)
{
p = p.Reverse().ToArray();
if (p[p.Length - 1] > 127)
{
Array.Resize(ref p, p.Length + 1);
p[p.Length - 1] = 0;
}
return new BigInteger(p);
}
}
пример использования:
BigInteger modulus1 = new BigInteger().FromBase64("rcLI1XTfmXtX05zq67d1wujnUvevBu8dZ5Q5uBUi2mKndH1FZLYCKrjFaDTB/mXW1l5C74YycVLS6msY2NNJYw==");
BigInteger modulus2 = new BigInteger().FromBigEndian(param.Modulus);
надеюсь, что это поможет другим с той же проблемой: -)
2 ответов
вот мой анализ параметров XML, которые вы предоставили:
N = 9100595563660672087698322262735024483609782000266155222822537546670463733453350686171384417480667378838400923087358115007100900745853538273602044437940579
P = 96731388413554317303099785843734797692955743043844132225634400270674214374921
Q = 94081101418218318334927154927633016498744568046568114230258529096538660255499
Как вы можете убедиться, N действительно равен P * Q.
вы не можете использовать конструктор BigInteger(byte []) так, как вы есть, потому что он ожидает, что массив байтов будет в little-endian, и потому, что Microsoft сделала вещи bass ackwards. Вместо этого измените порядок байтов. И, наконец, потому что массивы байтов должны быть дополнением двоек, и ваши числа гарантированно будут положительными необходимо добавить нулевой байт в байт высокого порядка массива если в противном случае байт высокого порядка будет больше или равен 128.
BigInteger
анализирует массивы как подписанные значения little-endian. RSAParameters
использует беззнаковый big-endian.
Так i = new BigInteger(bytes.Reverse().Concat(new byte[]{0}).ToArray()))
должны работать.