/// <summary>
 /// Method take BCrypt handle as input and returns the CNGKey
 /// </summary>
 /// <param name="bcryptKeyHandle">Accepts BCrypt Handle</param>
 /// <returns>Returns CNG key with NCrypt Handle</returns>
 private static CngKey BCryptHandleToNCryptHandle(SafeBCryptKeyHandle bcryptKeyHandle)
 {            
     byte[] keyBlob = BCryptNative.ExportBCryptKey(bcryptKeyHandle, BCryptNative.BCRYPT_ECCPUBLIC_BLOB);
     //Now Import the key blob as NCRYPT_KEY_HANDLE            
     CngKey Key = CngKey.Import(keyBlob, CngKeyBlobFormat.EccPublicBlob);
     return Key;
 }
        private static byte[]? GetProperty(SafeBCryptKeyHandle cryptHandle, string propertyName)
        {
            Debug.Assert(!cryptHandle.IsInvalid);
            unsafe
            {
                int      numBytesNeeded;
                NTSTATUS errorCode = Interop.BCrypt.BCryptGetProperty(cryptHandle, propertyName, null, 0, out numBytesNeeded, 0);
                if (errorCode != NTSTATUS.STATUS_SUCCESS)
                {
                    return(null);
                }

                byte[] propertyValue = new byte[numBytesNeeded];
                fixed(byte *pPropertyValue = propertyValue)
                {
                    errorCode = Interop.BCrypt.BCryptGetProperty(cryptHandle, propertyName, pPropertyValue, propertyValue.Length, out numBytesNeeded, 0);
                }

                if (errorCode != NTSTATUS.STATUS_SUCCESS)
                {
                    return(null);
                }

                Array.Resize(ref propertyValue, numBytesNeeded);
                return(propertyValue);
            }
        }
        private static TAlgorithm DecodeECPublicKey <TAlgorithm>(
            CertificatePal certificatePal,
            Func <CngKey, TAlgorithm> factory,
            Action <TAlgorithm, ECParameters> import,
            CryptImportPublicKeyInfoFlags importFlags = CryptImportPublicKeyInfoFlags.NONE)
            where TAlgorithm : AsymmetricAlgorithm, new()
        {
            TAlgorithm key;

            using (SafeBCryptKeyHandle bCryptKeyHandle = ImportPublicKeyInfo(certificatePal.CertContext, importFlags))
            {
                CngKeyBlobFormat blobFormat;
                byte[]           keyBlob;
                string?          curveName = GetCurveName(bCryptKeyHandle);

                if (curveName == null)
                {
                    if (HasExplicitParameters(bCryptKeyHandle))
                    {
                        blobFormat = CngKeyBlobFormat.EccFullPublicBlob;
                    }
                    else
                    {
                        blobFormat = CngKeyBlobFormat.EccPublicBlob;
                    }

                    keyBlob = ExportKeyBlob(bCryptKeyHandle, blobFormat);
                    using (CngKey cngKey = CngKey.Import(keyBlob, blobFormat))
                    {
                        key = factory(cngKey);
                    }
                }
                else
                {
                    blobFormat = CngKeyBlobFormat.EccPublicBlob;
                    keyBlob    = ExportKeyBlob(bCryptKeyHandle, blobFormat);
                    ECParameters ecparams = default;
                    ExportNamedCurveParameters(ref ecparams, keyBlob, false);
                    ecparams.Curve = ECCurve.CreateFromFriendlyName(curveName);
                    key            = new TAlgorithm();
                    import(key, ecparams);
                }
            }

            return(key);
        }
        private static string?GetPropertyAsString(SafeBCryptKeyHandle cryptHandle, string propertyName)
        {
            Debug.Assert(!cryptHandle.IsInvalid);
            byte[]? value = GetProperty(cryptHandle, propertyName);
            if (value == null || value.Length == 0)
            {
                return(null);
            }

            unsafe
            {
                fixed(byte *pValue = &value[0])
                {
                    string?valueAsString = Marshal.PtrToStringUni((IntPtr)pValue);

                    return(valueAsString);
                }
            }
        }
        private static byte[] ExportKeyBlob(SafeBCryptKeyHandle bCryptKeyHandle, CngKeyBlobFormat blobFormat)
        {
            string blobFormatString = blobFormat.Format;

            int      numBytesNeeded = 0;
            NTSTATUS ntStatus       = Interop.BCrypt.BCryptExportKey(bCryptKeyHandle, IntPtr.Zero, blobFormatString, null, 0, out numBytesNeeded, 0);

            if (ntStatus != NTSTATUS.STATUS_SUCCESS)
            {
                throw new CryptographicException(Interop.Kernel32.GetMessage((int)ntStatus));
            }

            byte[] keyBlob = new byte[numBytesNeeded];
            ntStatus = Interop.BCrypt.BCryptExportKey(bCryptKeyHandle, IntPtr.Zero, blobFormatString, keyBlob, keyBlob.Length, out numBytesNeeded, 0);
            if (ntStatus != NTSTATUS.STATUS_SUCCESS)
            {
                throw new CryptographicException(Interop.Kernel32.GetMessage((int)ntStatus));
            }

            Array.Resize(ref keyBlob, numBytesNeeded);
            return(keyBlob);
        }
 private static string?GetCurveName(SafeBCryptKeyHandle bcryptHandle)
 {
     return(GetPropertyAsString(bcryptHandle, BCRYPT_ECC_CURVE_NAME_PROPERTY));
 }
 private static bool HasExplicitParameters(SafeBCryptKeyHandle bcryptHandle)
 {
     byte[]? explicitParams = GetProperty(bcryptHandle, BCRYPT_ECC_PARAMETERS_PROPERTY);
     return(explicitParams != null && explicitParams.Length > 0);
 }
Exemple #8
0
 public static unsafe partial bool CryptImportPublicKeyInfoEx2(CertEncodingType dwCertEncodingType, CERT_PUBLIC_KEY_INFO *pInfo, CryptImportPublicKeyInfoFlags dwFlags, void *pvAuxInfo, out SafeBCryptKeyHandle phKey);
Exemple #9
0
 public static unsafe extern bool CryptImportPublicKeyInfoEx2(CertEncodingType dwCertEncodingType, CERT_PUBLIC_KEY_INFO* pInfo, int dwFlags, void* pvAuxInfo, out SafeBCryptKeyHandle phKey);
 internal static extern NTSTATUS BCryptExportKey(SafeBCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, [Out] byte[] pbOutput, int cbOutput, out int pcbResult, int dwFlags);