Пример #1
0
        public CngKey GetOrGenerateKey(int keySize, CngAlgorithm algorithm)
        {
            ThrowIfDisposed();

            // If our key size was changed, we need to generate a new key.
            if (_lazyKey != null)
            {
                if (_lazyKey.KeySize != keySize)
                {
                    DisposeKey();
                }
            }

            // If we don't have a key yet, we need to generate one now.
            if (_lazyKey == null)
            {
                CngKeyCreationParameters creationParameters = new CngKeyCreationParameters()
                {
                    ExportPolicy = CngExportPolicies.AllowPlaintextExport,
                };

                CngProperty keySizeProperty = new CngProperty(KeyPropertyName.Length, BitConverter.GetBytes(keySize), CngPropertyOptions.None);
                creationParameters.Parameters.Add(keySizeProperty);

                _lazyKey = CngKey.Create(algorithm, null, creationParameters);
            }

            return(_lazyKey);
        }
        private CngKey GetKey()
        {
            CngKey?key = null;

            if (_core.IsKeyGeneratedNamedCurve())
            {
                // Curve was previously created, so use that
                key = _core.GetOrGenerateKey(null);
            }
            else
            {
                CngAlgorithm?algorithm = null;
                int          keySize   = 0;

                // Map the current key size to a CNG algorithm name
                keySize = KeySize;
                switch (keySize)
                {
                case 256: algorithm = CngAlgorithm.ECDsaP256; break;

                case 384: algorithm = CngAlgorithm.ECDsaP384; break;

                case 521: algorithm = CngAlgorithm.ECDsaP521; break;

                default:
                    Debug.Fail("Should not have invalid key size");
                    throw new ArgumentException(SR.Cryptography_InvalidKeySize);
                }
                key = _core.GetOrGenerateKey(keySize, algorithm);
            }

            return(key);
        }
Пример #3
0
        public CngKey GetOrGenerateKey(int keySize, CngAlgorithm algorithm)
        {
            ThrowIfDisposed();

            // If our key size was changed, we need to generate a new key.
            if (_lazyKey != null)
            {
                if (_lazyKey.KeySize != keySize)
                {
                    DisposeKey();
                }
            }

            // If we don't have a key yet, we need to generate one now.
            if (_lazyKey == null)
            {
                CngKeyCreationParameters creationParameters = new CngKeyCreationParameters()
                {
                    ExportPolicy = CngExportPolicies.AllowPlaintextExport,
                };

                Span <byte> keySizeBuffer = stackalloc byte[sizeof(int)];
                bool        success       = BitConverter.TryWriteBytes(keySizeBuffer, keySize);
                Debug.Assert(success);

                CngProperty keySizeProperty = new CngProperty(KeyPropertyName.Length, keySizeBuffer, CngPropertyOptions.None);
                creationParameters.Parameters.Add(keySizeProperty);

                _lazyKey = CngKey.Create(algorithm, null, creationParameters);
            }

            return(_lazyKey);
        }
Пример #4
0
 public void DisposeKey()
 {
     if (_lazyKey != null)
     {
         _lazyKey.Dispose();
         _lazyKey = null;
     }
 }
Пример #5
0
        public void SetKey(CngKey key)
        {
            Debug.Assert(key != null);
            ThrowIfDisposed();

            // If we already have a key, clear it out.
            DisposeKey();

            _lazyKey = key;
        }
Пример #6
0
        public CngKey GetOrGenerateKey(ECCurve?curve)
        {
            ThrowIfDisposed();

            if (_lazyKey != null)
            {
                return(_lazyKey);
            }

            // We don't have a key yet so generate
            Debug.Assert(curve.HasValue);

            CngKeyCreationParameters creationParameters = new CngKeyCreationParameters()
            {
                ExportPolicy = CngExportPolicies.AllowPlaintextExport,
            };

            if (curve.Value.IsNamed)
            {
                creationParameters.Parameters.Add(CngKey.GetPropertyFromNamedCurve(curve.Value));
            }
            else if (curve.Value.IsPrime)
            {
                ECCurve     eccurve        = curve.Value;
                byte[]      parametersBlob = ECCng.GetPrimeCurveParameterBlob(ref eccurve);
                CngProperty prop           = new CngProperty(
                    Interop.BCrypt.BCryptPropertyStrings.BCRYPT_ECC_PARAMETERS,
                    parametersBlob,
                    CngPropertyOptions.None);
                creationParameters.Parameters.Add(prop);
            }
            else
            {
                throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CurveNotSupported, curve.Value.CurveType.ToString()));
            }

            try
            {
                _lazyKey = CngKey.Create(DefaultKeyType ?? CngAlgorithm.ECDsa, null, creationParameters);
            }
            catch (CryptographicException e)
            {
                // Map to PlatformNotSupportedException if appropriate
                ErrorCode errorCode = (ErrorCode)e.HResult;

                if (curve.Value.IsNamed &&
                    errorCode == ErrorCode.NTE_INVALID_PARAMETER || errorCode == ErrorCode.NTE_NOT_SUPPORTED)
                {
                    throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CurveNotSupported, curve.Value.Oid.FriendlyName), e);
                }
                throw;
            }

            return(_lazyKey);
        }
Пример #7
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(nameof(keyHandle));
            }
            if (keyHandle.IsClosed || keyHandle.IsInvalid)
            {
                throw new ArgumentException(SR.Cryptography_OpenInvalidHandle, nameof(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, nameof(keyHandleOpenOptions));
                }
            }
            catch
            {
                // Make sure that we don't leak the handle the CngKey duplicated
                if (key != null)
                {
                    key.Dispose();
                }

                throw;
            }

            return(key);
        }