Example #1
0
        /// <summary>
        ///     Wrap an existing key handle with a CngKey object
        /// </summary>
        public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions)
        {
            if (keyHandle == null)
                throw new ArgumentNullException("keyHandle");
            if (keyHandle.IsClosed || keyHandle.IsInvalid)
                throw new ArgumentException(SR.Cryptography_OpenInvalidHandle, "keyHandle");

            SafeNCryptKeyHandle keyHandleCopy = keyHandle.Duplicate();

            // Get a handle to the key's provider.
            SafeNCryptProviderHandle providerHandle = new SafeNCryptProviderHandle();
            IntPtr rawProviderHandle = keyHandle.GetPropertyAsIntPtr(KeyPropertyName.ProviderHandle, CngPropertyOptions.None);
            providerHandle.SetHandleValue(rawProviderHandle);

            // Set up a key object wrapping the handle
            CngKey key = null;
            try
            {
                key = new CngKey(providerHandle, keyHandleCopy);
                bool openingEphemeralKey = (keyHandleOpenOptions & CngKeyHandleOpenOptions.EphemeralKey) == CngKeyHandleOpenOptions.EphemeralKey;

                //
                // If we're wrapping a handle to an ephemeral key, we need to make sure that IsEphemeral is
                // set up to return true.  In the case that the handle is for an ephemeral key that was created
                // by the CLR, then we don't have anything to do as the IsEphemeral CLR property will already
                // be setup.  However, if the key was created outside of the CLR we will need to setup our
                // ephemeral detection property.
                // 
                // This enables consumers of CngKey objects to always be able to rely on the result of
                // calling IsEphemeral, and also allows them to safely access the Name property.
                // 
                // Finally, if we detect that this is an ephemeral key that the CLR created but we were not
                // told that it was an ephemeral key we'll throw an exception.  This prevents us from having
                // to decide who to believe -- the key property or the caller of the API.  Since other code
                // relies on the ephemeral flag being set properly to avoid tripping over bugs in CNG, we
                // need to reject the case that we suspect that the flag is incorrect.
                // 

                if (!key.IsEphemeral && openingEphemeralKey)
                {
                    key.IsEphemeral = true;
                }
                else if (key.IsEphemeral && !openingEphemeralKey)
                {
                    throw new ArgumentException(SR.Cryptography_OpenEphemeralKeyHandleWithoutEphemeralFlag, "keyHandleOpenOptions");
                }
            }
            catch
            {
                // Make sure that we don't leak the handle the CngKey duplicated
                if (key != null)
                    key.Dispose();

                throw;
            }

            return key;
        }
Example #2
0
        public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions)
        {
            ArgumentNullException.ThrowIfNull(keyHandle);

            if (keyHandle.IsClosed || keyHandle.IsInvalid)
            {
                throw new ArgumentException(SR.Cryptography_OpenInvalidHandle, nameof(keyHandle));
            }

            return(OpenNoDuplicate(keyHandle.Duplicate(), keyHandleOpenOptions));
        }
Example #3
0
        internal static CngKey OpenNoDuplicate(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions)
        {
            SafeNCryptProviderHandle?providerHandle = null;

            try
            {
                // Get a handle to the key's provider.
                providerHandle = new SafeNCryptProviderHandle();
                IntPtr rawProviderHandle = keyHandle.GetPropertyAsIntPtr(KeyPropertyName.ProviderHandle, CngPropertyOptions.None);
                Marshal.InitHandle(providerHandle, rawProviderHandle);

                // If we're wrapping a handle to an ephemeral key, we need to make sure that IsEphemeral is
                // set up to return true.  In the case that the handle is for an ephemeral key that was created
                // by the CLR, then we don't have anything to do as the IsEphemeral CLR property will already
                // be setup.  However, if the key was created outside of the CLR we will need to setup our
                // ephemeral detection property.
                //
                // This enables consumers of CngKey objects to always be able to rely on the result of
                // calling IsEphemeral, and also allows them to safely access the Name property.
                //
                // Finally, if we detect that this is an ephemeral key that the CLR created but we were not
                // told that it was an ephemeral key we'll throw an exception.  This prevents us from having
                // to decide who to believe -- the key property or the caller of the API.  Since other code
                // relies on the ephemeral flag being set properly to avoid tripping over bugs in CNG, we
                // need to reject the case that we suspect that the flag is incorrect.

                var key = new CngKey(providerHandle, keyHandle);

                bool openingEphemeralKey = (keyHandleOpenOptions & CngKeyHandleOpenOptions.EphemeralKey) == CngKeyHandleOpenOptions.EphemeralKey;
                if (!key.IsEphemeral)
                {
                    if (openingEphemeralKey)
                    {
                        key.IsEphemeral = true;
                    }
                }
                else if (!openingEphemeralKey)
                {
                    throw new ArgumentException(SR.Cryptography_OpenEphemeralKeyHandleWithoutEphemeralFlag, nameof(keyHandleOpenOptions));
                }

                return(key);
            }
            catch
            {
                // Make sure that we don't leak the handles
                providerHandle?.Dispose();
                keyHandle.Dispose();
                throw;
            }
        }
Example #4
0
        public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions)
        {
            if (keyHandle == null)
            {
                throw new ArgumentNullException("keyHandle");
            }
            if (keyHandle.IsClosed || keyHandle.IsInvalid)
            {
                throw new ArgumentException(System.SR.GetString("Cryptography_OpenInvalidHandle"), "keyHandle");
            }
            SafeNCryptKeyHandle      handle    = keyHandle.Duplicate();
            SafeNCryptProviderHandle kspHandle = new SafeNCryptProviderHandle();

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
            }
            finally
            {
                IntPtr newHandleValue = NCryptNative.GetPropertyAsIntPtr(keyHandle, "Provider Handle", CngPropertyOptions.None);
                kspHandle.SetHandleValue(newHandleValue);
            }
            CngKey key  = null;
            bool   flag = false;

            try
            {
                key = new CngKey(kspHandle, handle);
                bool flag2 = (keyHandleOpenOptions & CngKeyHandleOpenOptions.EphemeralKey) == CngKeyHandleOpenOptions.EphemeralKey;
                if (!key.IsEphemeral && flag2)
                {
                    key.IsEphemeral = true;
                }
                else if (key.IsEphemeral && !flag2)
                {
                    throw new ArgumentException(System.SR.GetString("Cryptography_OpenEphemeralKeyHandleWithoutEphemeralFlag"), "keyHandleOpenOptions");
                }
                flag = true;
            }
            finally
            {
                if (!flag && (key != null))
                {
                    key.Dispose();
                }
            }
            return(key);
        }
Example #5
0
        private static SafeNCryptKeyHandle TryAcquireCngPrivateKey(
            SafeCertContextHandle certificateContext,
            out CngKeyHandleOpenOptions handleOptions)
        {
            Debug.Assert(certificateContext != null, "certificateContext != null");
            Debug.Assert(!certificateContext.IsClosed && !certificateContext.IsInvalid,
                         "!certificateContext.IsClosed && !certificateContext.IsInvalid");

            IntPtr privateKeyPtr;

            // If the certificate has a key handle instead of a key prov info, return the
            // ephemeral key
            {
                int cbData = IntPtr.Size;

                if (Interop.crypt32.CertGetCertificateContextProperty(
                        certificateContext,
                        CertContextPropId.CERT_NCRYPT_KEY_HANDLE_PROP_ID,
                        out privateKeyPtr,
                        ref cbData))
                {
                    handleOptions = CngKeyHandleOpenOptions.EphemeralKey;
                    return(new SafeNCryptKeyHandle(privateKeyPtr, certificateContext));
                }
            }

            bool freeKey = true;
            SafeNCryptKeyHandle privateKey = null;

            handleOptions = CngKeyHandleOpenOptions.None;
            try
            {
                int keySpec = 0;
                if (!Interop.crypt32.CryptAcquireCertificatePrivateKey(
                        certificateContext,
                        CryptAcquireFlags.CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG,
                        IntPtr.Zero,
                        out privateKey,
                        out keySpec,
                        out freeKey))
                {
                    int dwErrorCode = Marshal.GetLastWin32Error();

                    // The documentation for CryptAcquireCertificatePrivateKey says that freeKey
                    // should already be false if "key acquisition fails", and it can be presumed
                    // that privateKey was set to 0.  But, just in case:
                    freeKey = false;
                    privateKey?.SetHandleAsInvalid();
                    return(null);
                }

                // It is very unlikely that Windows will tell us !freeKey other than when reporting failure,
                // because we set neither CRYPT_ACQUIRE_CACHE_FLAG nor CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, which are
                // currently the only two success situations documented. However, any !freeKey response means the
                // key's lifetime is tied to that of the certificate, so re-register the handle as a child handle
                // of the certificate.
                if (!freeKey && privateKey != null && !privateKey.IsInvalid)
                {
                    var newKeyHandle = new SafeNCryptKeyHandle(privateKey.DangerousGetHandle(), certificateContext);
                    privateKey.SetHandleAsInvalid();
                    privateKey = newKeyHandle;
                    freeKey    = true;
                }

                return(privateKey);
            }
            catch
            {
                // If we aren't supposed to free the key, and we're not returning it,
                // just tell the SafeHandle to not free itself.
                if (privateKey != null && !freeKey)
                {
                    privateKey.SetHandleAsInvalid();
                }

                throw;
            }
        }
Example #6
0
 public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions)
 {
     throw new NotImplementedException();
 }
    public static CngKey Open(Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions)
    {
      Contract.Ensures(Contract.Result<System.Security.Cryptography.CngKey>() != null);

      return default(CngKey);
    }
Example #8
0
 public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) {
     throw new NotImplementedException ();
 }
Example #9
0
        private T GetPrivateKey <T>(X509Certificate2 certificate, bool silent, bool preferNCrypt) where T : AsymmetricAlgorithm
        {
            if (!certificate.HasPrivateKey)
            {
                return(null);
            }

            SafeProvOrNCryptKeyHandle handle = GetCertificatePrivateKey(
                certificate,
                silent,
                preferNCrypt,
                out CryptKeySpec keySpec,
                out Exception exception);

            using (handle)
            {
                if (handle == null || handle.IsInvalid)
                {
                    if (exception != null)
                    {
                        throw exception;
                    }

                    return(null);
                }

                if (keySpec == CryptKeySpec.CERT_NCRYPT_KEY_SPEC)
                {
                    using (SafeNCryptKeyHandle keyHandle = new SafeNCryptKeyHandle(handle.DangerousGetHandle(), handle))
                    {
                        CngKeyHandleOpenOptions options    = CngKeyHandleOpenOptions.None;
                        byte clrIsEphemeral                = 0;
                        Interop.NCrypt.ErrorCode errorCode = Interop.NCrypt.NCryptGetByteProperty(keyHandle, "CLR IsEphemeral", ref clrIsEphemeral, CngPropertyOptions.CustomProperty);

                        if (errorCode == Interop.NCrypt.ErrorCode.ERROR_SUCCESS && clrIsEphemeral == 1)
                        {
                            options |= CngKeyHandleOpenOptions.EphemeralKey;
                        }

                        using (CngKey cngKey = CngKey.Open(keyHandle, options))
                        {
                            if (typeof(T) == typeof(RSA))
                            {
                                return((T)(object)new RSACng(cngKey));
                            }
                            if (typeof(T) == typeof(ECDsa))
                            {
                                return((T)(object)new ECDsaCng(cngKey));
                            }
                            if (typeof(T) == typeof(DSA))
                            {
                                return((T)(object)new DSACng(cngKey));
                            }

                            Debug.Fail($"Unknown CNG key type request: {typeof(T).FullName}");
                            return(null);
                        }
                    }
                }

                // The key handle is for CAPI.
                // Our CAPI types don't allow usage from a handle, so we have a few choices:
                // 1) Extract the information we need to re-open the key handle.
                // 2) Re-implement {R|D}SACryptoServiceProvider
                // 3) PNSE.
                // 4) Defer to cert.Get{R|D}SAPrivateKey if not silent, throw otherwise.
                CspParameters cspParams = handle.GetProvParameters();
                Debug.Assert((cspParams.Flags & CspProviderFlags.UseExistingKey) != 0);
                cspParams.KeyNumber = (int)keySpec;

                if (silent)
                {
                    cspParams.Flags |= CspProviderFlags.NoPrompt;
                }

                if (typeof(T) == typeof(RSA))
                {
                    return((T)(object)new RSACryptoServiceProvider(cspParams));
                }
                if (typeof(T) == typeof(DSA))
                {
                    return((T)(object)new DSACryptoServiceProvider(cspParams));
                }

                Debug.Fail($"Unknown CAPI key type request: {typeof(T).FullName}");
                return(null);
            }
        }
Example #10
0
        public static CngKey Open(Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions)
        {
            Contract.Ensures(Contract.Result <System.Security.Cryptography.CngKey>() != null);

            return(default(CngKey));
        }
Example #11
0
        public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions)
        {
            if (keyHandle == null)
            {
                throw new ArgumentNullException("keyHandle");
            }
            if (keyHandle.IsClosed || keyHandle.IsInvalid)
            {
                throw new ArgumentException(SR.GetString(SR.Cryptography_OpenInvalidHandle), "keyHandle");
            }

            SafeNCryptKeyHandle keyHandleCopy = keyHandle.Duplicate();

            // Get a handle to the key's KSP
            SafeNCryptProviderHandle kspHandle = new SafeNCryptProviderHandle();

            RuntimeHelpers.PrepareConstrainedRegions();
            try { }
            finally {
                IntPtr rawHandle = NCryptNative.GetPropertyAsIntPtr(keyHandle,
                                                                    NCryptNative.KeyPropertyName.ProviderHandle,
                                                                    CngPropertyOptions.None);
                kspHandle.SetHandleValue(rawHandle);
            }

            // Setup a key object wrapping the handle
            CngKey key           = null;
            bool   keyFullySetup = false;

            try {
                key = new CngKey(kspHandle, keyHandleCopy);

                bool openingEphemeralKey = (keyHandleOpenOptions & CngKeyHandleOpenOptions.EphemeralKey) == CngKeyHandleOpenOptions.EphemeralKey;

                //
                // If we're wrapping a handle to an ephemeral key, we need to make sure that IsEphemeral is
                // setup to return true.  In the case that the handle is for an ephemeral key that was created
                // by the CLR, then we don't have anything to do as the IsEphemeral CLR property will already
                // be setup.  However, if the key was created outside of the CLR we will need to setup our
                // ephemeral detection property.
                //
                // This enables consumers of CngKey objects to always be able to rely on the result of
                // calling IsEphemeral, and also allows them to safely access the Name property.
                //
                // Finally, if we detect that this is an ephemeral key that the CLR created but we were not
                // told that it was an ephemeral key we'll throw an exception.  This prevents us from having
                // to decide who to believe -- the key property or the caller of the API.  Since other code
                // relies on the ephemeral flag being set properly to avoid tripping over bugs in CNG, we
                // need to reject the case that we suspect that the flag is incorrect.
                //

                if (!key.IsEphemeral && openingEphemeralKey)
                {
                    key.IsEphemeral = true;
                }
                else if (key.IsEphemeral && !openingEphemeralKey)
                {
                    throw new ArgumentException(SR.GetString(SR.Cryptography_OpenEphemeralKeyHandleWithoutEphemeralFlag), "keyHandleOpenOptions");
                }

                keyFullySetup = true;
            }
            finally {
                // Make sure that we don't leak the handle the CngKey duplicated
                if (!keyFullySetup && key != null)
                {
                    key.Dispose();
                }
            }

            return(key);
        }
Example #12
0
#pragma warning disable CA2000  // Dispose objects before losing scope
#pragma warning disable IDE0068 // Use recommended dispose pattern
        internal static SafeNCryptKeyHandle?TryAcquireCngPrivateKey(
            SafeCertContextHandle certificateContext,
            out CngKeyHandleOpenOptions openOptions)
        {
            Debug.Assert(certificateContext != null, "certificateContext != null");

            Debug.Assert(!certificateContext.IsClosed && !certificateContext.IsInvalid,
                         "!certificateContext.IsClosed && !certificateContext.IsInvalid");

            // If the certificate has a key handle instead of a key prov info, return the
            // ephemeral key
            {
                int cbData = IntPtr.Size;

                if (CertGetCertificateContextProperty(
                        certificateContext,
                        CertificateProperty.NCryptKeyHandle,
                        out IntPtr privateKeyPtr,
                        ref cbData))
                {
                    openOptions = CngKeyHandleOpenOptions.EphemeralKey;
                    return(new SafeNCryptKeyHandle(privateKeyPtr, certificateContext));
                }
            }

            openOptions = CngKeyHandleOpenOptions.None;

            bool freeKey = true;
            SafeNCryptKeyHandle?privateKey = null;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                if (!CryptAcquireCertificatePrivateKey(
                        certificateContext,
                        AcquireCertificateKeyOptions.AcquireOnlyNCryptKeys,
                        IntPtr.Zero,
                        out privateKey,
                        out int keySpec,
                        out freeKey))
                {
                    // The documentation for CryptAcquireCertificatePrivateKey says that freeKey
                    // should already be false if "key acquisition fails", and it can be presumed
                    // that privateKey was set to 0.  But, just in case:
                    freeKey = false;
                    privateKey?.SetHandleAsInvalid();
                    return(null);
                }
            }
            finally
            {
                // It is very unlikely that Windows will tell us !freeKey other than when reporting failure,
                // because we set neither CRYPT_ACQUIRE_CACHE_FLAG nor CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, which are
                // currently the only two success situations documented. However, any !freeKey response means the
                // key's lifetime is tied to that of the certificate, so re-register the handle as a child handle
                // of the certificate.
                if (!freeKey && privateKey != null && !privateKey.IsInvalid)
                {
                    SafeNCryptKeyHandle newKeyHandle = new SafeNCryptKeyHandle(privateKey.DangerousGetHandle(), certificateContext);
                    privateKey.SetHandleAsInvalid();
                    privateKey = newKeyHandle;
                }
            }

            return(privateKey);
        }
Example #13
0
        ///  this process runs in its own thread for the the full time of the hosting process.
        private void RunProcess(string keyName)
        {
            int    threadID = Thread.GetCurrentProcessorId();
            string whoami   = Thread.CurrentPrincipal?.Identity?.ToString();

            if (String.IsNullOrEmpty(whoami))
            {
                whoami = Environment.GetEnvironmentVariable("USERNAME");
            }

            _logger.LogInformation("Process Cred Store Service is runing on processor {0} and user {1}.", threadID, whoami);
            Thread.Sleep(200);   // ensure the rest of the web server starts up

            bool   bExists = CngKey.Exists(keyName);
            RSACng rsaKey;

            if (bExists)
            {
                CngKeyHandleOpenOptions ckhoo = new CngKeyHandleOpenOptions {
                };
                cngKey = CngKey.Open(keyName);
                _logger.LogInformation("Found Key {0}.", keyName);
                X509Store certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
                certStore.Open(OpenFlags.ReadOnly);
                X509Certificate2Collection certRes = certStore.Certificates.Find(X509FindType.FindBySubjectName, "Trustregistry", false);
                //                    X509Certificate2Enumerator certEnum = certRes.GetEnumerator();
                foreach (X509Certificate2 x2 in certRes)
                {
                    if (cert1 == null)
                    {
                        cert1 = x2;  // TODO see if there are better choices than the first when i have some criteria
                    }
                }
                certStore.Close();
            }
            else
            {
                try
                {
                    rsaKey = new RSACng(CngKey.Create(CngAlgorithm.Rsa, keyName, new CngKeyCreationParameters {
                        ExportPolicy = CngExportPolicies.AllowExport
                    }));
                    cngKey = rsaKey.Key;
                    RSAParameters         rsaP = rsaKey.ExportParameters(true);
                    X500DistinguishedName dn   = new X500DistinguishedName("CN=Trustregistry.US", new X500DistinguishedNameFlags {
                    });
                    CertificateRequest cr      = new CertificateRequest(dn, rsaKey, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                    _logger.LogInformation("Need to create a new Key named {0}.", keyName);
                }
                catch (Exception ex)
                {
                    _logger.LogInformation("Exception trying to create a new Key named {0}, exception {1}.", keyName, ex.Message);
                }
            }
            if (cngKey != null)
            {
                try
                {
                    keyType = cngKey.Algorithm;
                    rsaKey  = new RSACng(cngKey);
                    X500DistinguishedName dnx = new X500DistinguishedName("CN=Trustregistry.US", new X500DistinguishedNameFlags {
                    });
                    CertificateRequest crx    = new CertificateRequest(dnx, rsaKey, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                    X509Certificate2   cert2  = crx.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow + TimeSpan.FromHours(24 * 365.2 * 5)); // TODO get value from config IN HOURS
                                                                                                                                                         // put that sert in the store
                    X509Store certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
                    certStore.Open(OpenFlags.ReadOnly);
                    X509Certificate2Collection certRes = certStore.Certificates.Find(X509FindType.FindBySubjectName, "Trustregistry", false);
//                    X509Certificate2Enumerator certEnum = certRes.GetEnumerator();
                    foreach (X509Certificate2 x2 in certRes)
                    {
                        if (cert1 == null)
                        {
                            cert1 = x2;  // TODO see if there are better choices than the first when i have some criteria
                        }
                    }
//                    certStore.Add(cert2);
                    certStore.Close();
                }
                catch (Exception ex)
                {
                    _logger.LogInformation("Exception trying to create a new cert for key named {0}, exception {1}.", keyName, ex.Message);
                }
            }
            while (true)
            {
                if (busy)
                {
                }
                Thread.Sleep(60000);  // TODO make this event driven

                _logger.LogInformation("Process Cred Store Service still runing.");
            }
        }
 public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions)
 {
     if (keyHandle == null)
     {
         throw new ArgumentNullException("keyHandle");
     }
     if (keyHandle.IsClosed || keyHandle.IsInvalid)
     {
         throw new ArgumentException(System.SR.GetString("Cryptography_OpenInvalidHandle"), "keyHandle");
     }
     SafeNCryptKeyHandle handle = keyHandle.Duplicate();
     SafeNCryptProviderHandle kspHandle = new SafeNCryptProviderHandle();
     RuntimeHelpers.PrepareConstrainedRegions();
     try
     {
     }
     finally
     {
         IntPtr newHandleValue = NCryptNative.GetPropertyAsIntPtr(keyHandle, "Provider Handle", CngPropertyOptions.None);
         kspHandle.SetHandleValue(newHandleValue);
     }
     CngKey key = null;
     bool flag = false;
     try
     {
         key = new CngKey(kspHandle, handle);
         bool flag2 = (keyHandleOpenOptions & CngKeyHandleOpenOptions.EphemeralKey) == CngKeyHandleOpenOptions.EphemeralKey;
         if (!key.IsEphemeral && flag2)
         {
             key.IsEphemeral = true;
         }
         else if (key.IsEphemeral && !flag2)
         {
             throw new ArgumentException(System.SR.GetString("Cryptography_OpenEphemeralKeyHandleWithoutEphemeralFlag"), "keyHandleOpenOptions");
         }
         flag = true;
     }
     finally
     {
         if (!flag && (key != null))
         {
             key.Dispose();
         }
     }
     return key;
 }