public override void ImportParameters (RSAParameters parameters)
{
if (m_disposed)
throw new ObjectDisposedException (Locale.GetText ("Keypair was disposed"));
// if missing "mandatory" parameters
if (parameters.Exponent == null)
throw new CryptographicException (Locale.GetText ("Missing Exponent"));
if (parameters.Modulus == null)
throw new CryptographicException (Locale.GetText ("Missing Modulus"));
e = new BigInteger (parameters.Exponent);
n = new BigInteger (parameters.Modulus);
// only if the private key is present
if (parameters.D != null)
d = new BigInteger (parameters.D);
if (parameters.DP != null)
dp = new BigInteger (parameters.DP);
if (parameters.DQ != null)
dq = new BigInteger (parameters.DQ);
if (parameters.InverseQ != null)
qInv = new BigInteger (parameters.InverseQ);
if (parameters.P != null)
p = new BigInteger (parameters.P);
if (parameters.Q != null)
q = new BigInteger (parameters.Q);
// we now have a keypair
keypairGenerated = true;
bool privateKey = ((p != null) && (q != null) && (dp != null));
isCRTpossible = (privateKey && (dq != null) && (qInv != null));
// check if the public/private keys match
// the way the check is made allows a bad D to work if CRT is available (like MS does, see unit tests)
if (!privateKey)
return;
// always check n == p * q
bool ok = (n == (p * q));
if (ok) {
// we now know that p and q are correct, so (p - 1), (q - 1) and phi will be ok too
BigInteger pSub1 = (p - 1);
BigInteger qSub1 = (q - 1);
BigInteger phi = pSub1 * qSub1;
// e is fairly static but anyway we can ensure it makes sense by recomputing d
BigInteger dcheck = e.ModInverse (phi);
// now if our new d(check) is different than the d we're provided then we cannot
// be sure if 'd' or 'e' is invalid... (note that, from experience, 'd' is more
// likely to be invalid since it's twice as large as DP (or DQ) and sits at the
// end of the structure (e.g. truncation).
ok = (d == dcheck);
// ... unless we have the pre-computed CRT parameters
if (!ok && isCRTpossible) {
// we can override the previous decision since Mono always prefer, for
// performance reasons, using the CRT algorithm
ok = (dp == (dcheck % pSub1)) && (dq == (dcheck % qSub1)) &&
(qInv == q.ModInverse (p));
}
}
if (!ok)
throw new CryptographicException (Locale.GetText ("Private/public key mismatch"));
}