public RSA GetRSAPrivateKey() { if (_privateKey == null || _privateKey.IsInvalid) { return(null); } using (SafeRsaHandle rsaHandle = Interop.libcrypto.EVP_PKEY_get1_RSA(_privateKey)) { return(new RSAOpenSsl(rsaHandle.DangerousGetHandle())); } }
internal static unsafe RSAParameters ExportRsaParameters(SafeRsaHandle key, bool includePrivateParameters) { Debug.Assert( key != null && !key.IsInvalid, "Callers should check the key is invalid and throw an exception with a message"); if (key == null || key.IsInvalid) { throw new CryptographicException(); } RSAParameters rsaParameters; bool addedRef = false; try { key.DangerousAddRef(ref addedRef); RSA_ST *rsaStructure = (RSA_ST *)key.DangerousGetHandle(); int modulusSize = RSA_size(key); // RSACryptoServiceProvider expects P, DP, Q, DQ, and InverseQ to all // be padded up to half the modulus size. int halfModulus = modulusSize / 2; rsaParameters = new RSAParameters { Modulus = Crypto.ExtractBignum(rsaStructure->n, modulusSize), Exponent = Crypto.ExtractBignum(rsaStructure->e, 0), }; if (includePrivateParameters) { rsaParameters.D = Crypto.ExtractBignum(rsaStructure->d, modulusSize); rsaParameters.P = Crypto.ExtractBignum(rsaStructure->p, halfModulus); rsaParameters.DP = Crypto.ExtractBignum(rsaStructure->dmp1, halfModulus); rsaParameters.Q = Crypto.ExtractBignum(rsaStructure->q, halfModulus); rsaParameters.DQ = Crypto.ExtractBignum(rsaStructure->dmq1, halfModulus); rsaParameters.InverseQ = Crypto.ExtractBignum(rsaStructure->iqmp, halfModulus); } } finally { if (addedRef) { key.DangerousRelease(); } } return(rsaParameters); }
public override unsafe void ImportParameters(RSAParameters parameters) { ValidateParameters(ref parameters); SafeRsaHandle key = Interop.libcrypto.RSA_new(); bool imported = false; CheckInvalidNewKey(key); try { Interop.libcrypto.RSA_ST *rsaStructure = (Interop.libcrypto.RSA_ST *)key.DangerousGetHandle(); // RSA_free is going to take care of freeing any of these as long as they successfully // get assigned. // CreateBignumPtr returns IntPtr.Zero for null input, so this just does the right thing // on a public-key-only set of RSAParameters. rsaStructure->n = Interop.libcrypto.CreateBignumPtr(parameters.Modulus); rsaStructure->e = Interop.libcrypto.CreateBignumPtr(parameters.Exponent); rsaStructure->d = Interop.libcrypto.CreateBignumPtr(parameters.D); rsaStructure->p = Interop.libcrypto.CreateBignumPtr(parameters.P); rsaStructure->dmp1 = Interop.libcrypto.CreateBignumPtr(parameters.DP); rsaStructure->q = Interop.libcrypto.CreateBignumPtr(parameters.Q); rsaStructure->dmq1 = Interop.libcrypto.CreateBignumPtr(parameters.DQ); rsaStructure->iqmp = Interop.libcrypto.CreateBignumPtr(parameters.InverseQ); imported = true; } finally { if (!imported) { key.Dispose(); } } FreeKey(); _key = new Lazy <SafeRsaHandle>(() => key, LazyThreadSafetyMode.None); // Set base.KeySize directly, since we don't want to free the key // (which we would do if the keysize changed on import) base.KeySize = 8 * Interop.libcrypto.RSA_size(key); }