Esempio n. 1
0
        private static SafeHashHandleCP SetupHashAlgorithm(SafeProvHandleCP prov, byte[] rgbHash, int algId)
        {
            SafeHashHandleCP invalidHandle = SafeHashHandleCP.InvalidHandle;

            CreateHash(prov, algId, ref invalidHandle);

            uint num = 0;

            if (!CApiExtWin.CryptGetHashParam(invalidHandle, 2, null, ref num, 0))
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }

            if ((ulong)((int)rgbHash.Length) != (ulong)num)
            {
                throw new CryptographicException(-2146893822);
            }

            if (!CApiExtWin.CryptSetHashParam(invalidHandle, 2, rgbHash, 0))
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }

            return(invalidHandle);
        }
Esempio n. 2
0
        /// <summary>
        /// Метод получения алгоритма хэширования
        /// </summary>
        /// <param name="signatureAlgOid"></param>
        /// <returns></returns>
        internal static CRYPT_OID_INFO GetHashAlg(string signatureAlgOid)
        {
            IntPtr sigId = CApiExtWin.CryptFindOIDInfo(OidKeyType.Oid, signatureAlgOid, OidGroup.SignatureAlgorithm);

            CRYPT_OID_INFO CertInfo = Marshal.PtrToStructure <CRYPT_OID_INFO>(sigId);

            uint alg = CertInfo.Algid;

            IntPtr int_addr = Marshal.AllocHGlobal(Marshal.SizeOf(alg));

            Marshal.WriteInt32(int_addr, (int)alg);

            IntPtr sigs = CApiExtWin.CryptFindOIDInfo(OidKeyType.AlgorithmID, int_addr, OidGroup.SignatureAlgorithm);

            CRYPT_OID_INFO sigsInfo = Marshal.PtrToStructure <CRYPT_OID_INFO>(sigs);

            if (sigs == IntPtr.Zero)
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }

            IntPtr hass = CApiExtWin.CryptFindOIDInfo(OidKeyType.AlgorithmID, int_addr, OidGroup.HashAlgorithm);

            CRYPT_OID_INFO hassInfo = Marshal.PtrToStructure <CRYPT_OID_INFO>(hass);

            if (hass == IntPtr.Zero)
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }

            return(hassInfo);
        }
Esempio n. 3
0
        internal static IntPtr GetHandler(IntPtr certHandle, out uint keySpec)
        {
            bool   bResult = false;
            IntPtr phProv  = IntPtr.Zero;

            keySpec = CApiExtConst.AT_SIGNATURE;
            bool isNeedCleenup = true;

            // Get CSP handle
            bResult = CApiExtWin.CryptAcquireCertificatePrivateKey(
                certHandle,
                0,
                IntPtr.Zero,
                ref phProv,
                ref keySpec,
                ref isNeedCleenup
                );

            if (!bResult)
            {
                throw new Exception("CryptAcquireContext error #" + Marshal.GetLastWin32Error().ToString());
            }

            return(phProv);
        }
Esempio n. 4
0
        internal SafeProvHandleCP(IntPtr handle, bool addref)
            : base(true)
        {
            if (!addref)
            {
                this.SetHandle(handle);
                return;
            }
            bool flag           = false;
            int  lastWin32Error = 0;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
            }
            finally
            {
                flag           = CApiExtWin.CryptContextAddRef(handle, null, 0);
                lastWin32Error = Marshal.GetLastWin32Error();
                if (flag)
                {
                    this.SetHandle(handle);
                }
            }
            if (!flag)
            {
                throw new CryptographicException(lastWin32Error);
            }
        }
Esempio n. 5
0
 internal static void CreateHash(SafeProvHandleCP hProv, int algid, ref SafeHashHandleCP hHash)
 {
     if (!CApiExtWin.CryptCreateHash(hProv, (uint)algid, SafeKeyHandleCP.InvalidHandle, (uint)0, ref hHash))
     {
         throw new CryptographicException(Marshal.GetLastWin32Error());
     }
 }
 internal static void FreeHandleCertificate(IntPtr certHandle)
 {
     if (IsUnix)
     {
         CApiExtUnix.CertFreeCertificateContext(certHandle);
     }
     else
     {
         CApiExtWin.CertFreeCertificateContext(certHandle);
     }
 }
 internal static void ReleaseProvHandle(IntPtr provHandle)
 {
     if (SignServiceUtils.IsUnix)
     {
         CApiExtUnix.CryptReleaseContext(provHandle, 0);
     }
     else
     {
         CApiExtWin.CryptReleaseContext(provHandle, 0);
     }
 }
Esempio n. 8
0
 protected override bool ReleaseHandle()
 {
     if (!this.DeleteOnClose)
     {
         CApiExtWin.CryptReleaseContext(this.handle, 0);
     }
     else
     {
         CApiExtWin.CryptSetProvParam2(this.handle, 125, null, 0);
     }
     return(true);
 }
Esempio n. 9
0
        internal static void AcquireCSP(CspParameters param, ref SafeProvHandleCP hProv)
        {
            uint num = (uint)CRYPT_VERIFYCONTEXT;            // uint.MaxValue; // CRYPT_DEFAULT_CONTAINER_OPTIONAL

            if ((param.Flags & CspProviderFlags.UseMachineKeyStore) != CspProviderFlags.NoFlags)
            {
                num = num | 32;
            }

            if (!CApiExtWin.CryptAcquireContext(ref hProv, param.KeyContainerName, param.ProviderName, (uint)param.ProviderType, num))
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }
        }
Esempio n. 10
0
        internal static byte[] EndHash(SafeHashHandleCP hHash)
        {
            uint num = 0;

            if (!CApiExtWin.CryptGetHashParam(hHash, 2, null, ref num, 0))
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }

            byte[] numArray = new byte[num];
            if (!CApiExtWin.CryptGetHashParam(hHash, 2, numArray, ref num, 0))
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }

            return(numArray);
        }
Esempio n. 11
0
        /// <summary>
        /// Метод проверки открепленной подписи
        /// </summary>
        /// <param name="signatureData"></param>
        /// <param name="messageData"></param>
        /// <returns></returns>
        internal static bool VerifySignDetachedMessage(byte[] signatureData, byte[] messageData)
        {
            IntPtr messagePtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(byte)) * messageData.Length);

            Marshal.Copy(messageData, 0, messagePtr, messageData.Length);
            IntPtr[] rgpbToBeSigned = new IntPtr[1] {
                messagePtr
            };
            int[] rgcbToBeSigned = new int[1] {
                messageData.Length
            };
            GCHandle pCertContext = GCHandle.Alloc(IntPtr.Zero, GCHandleType.Pinned);

            CRYPT_VERIFY_MESSAGE_PARA verifyParams = new CRYPT_VERIFY_MESSAGE_PARA()
            {
                cbSize = (int)Marshal.SizeOf(typeof(CRYPT_VERIFY_MESSAGE_PARA)),
                dwMsgAndCertEncodingType = PKCS_7_OR_X509_ASN_ENCODING,
                hCryptProv = 0,
                pfnGetSignerCertificate = IntPtr.Zero,
                pvGetArg = IntPtr.Zero
            };

            try
            {
                bool result = CApiExtWin.CryptVerifyDetachedMessageSignature(
                    ref verifyParams,      // Verify parameters.
                    0,                     // Signer index.
                    signatureData,         // Buffer for decoded message.
                    signatureData.Length,  // Size of buffer.
                    1,
                    rgpbToBeSigned,        // Pointer to signed BLOB.
                    rgcbToBeSigned,        // Size of signed BLOB.
                    pCertContext.AddrOfPinnedObject()
                    );

                return(result);
            }
            catch (Exception ex)
            {
                throw new CryptographicException($"Ошибка при попытке выполнить проверку открепленной подписи. {ex.Message}.");
            }
            finally
            {
                pCertContext.Free();
            }
        }
Esempio n. 12
0
        internal static void HashData(SafeHashHandleCP hHash, byte[] data, int idStart, int cbSize)
        {
            try
            {
                byte[] temp = data;
                Array.Copy(data, idStart, temp, 0, cbSize);

                if (!CApiExtWin.CryptHashData(hHash, temp, (uint)cbSize, 0))
                {
                    throw new CryptographicException(Marshal.GetLastWin32Error());
                }

                temp = null;
            }
            catch (Exception ex)
            {
                throw new Exception("Ошибка в методе HashData. " + ex.Message);
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Метод подписи хэш
        /// </summary>
        /// <param name="hProv"></param>
        /// <param name="keyNumber"></param>
        /// <param name="rgbHash"></param>
        /// <param name="dwFlags"></param>
        /// <param name="algId"></param>
        /// <returns></returns>
        internal static byte[] SignValue(IntPtr hProv, int keyNumber, byte[] rgbHash, int dwFlags, int algId)
        {
            byte[] signArray     = null;
            uint   signArraySize = 0;

            var prov             = new SafeProvHandleCP(hProv);
            var safeHashHandleCP = SetupHashAlgorithm(prov, rgbHash, algId);

            if (!CApiExtWin.CryptSignHash(safeHashHandleCP, (uint)keyNumber, null, (uint)dwFlags, signArray, ref signArraySize))
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }

            signArray = new byte[signArraySize];

            if (!CApiExtWin.CryptSignHash(safeHashHandleCP, (uint)keyNumber, null, (uint)dwFlags, signArray, ref signArraySize))
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }

            return(signArray);
        }
Esempio n. 14
0
 protected override bool ReleaseHandle()
 {
     CApiExtWin.CryptMsgClose(handle);
     return(true);
 }
Esempio n. 15
0
 protected override bool ReleaseHandle()
 {
     CApiExtWin.CryptDestroyHash(handle);
     return(true);
 }
Esempio n. 16
0
        internal static byte[] Sign(byte[] data, IntPtr hCert)
        {
            // Структура содержит информацию для подписания сообщений с использованием указанного контекста сертификата подписи
            CApiExtConst.CRYPT_SIGN_MESSAGE_PARA pParams = new CApiExtConst.CRYPT_SIGN_MESSAGE_PARA
            {
                // Размер этой структуры в байтах
                cbSize = (uint)Marshal.SizeOf(typeof(CApiExtConst.CRYPT_SIGN_MESSAGE_PARA)),
                // Используемый тип кодирования
                dwMsgEncodingType = CApiExtConst.PKCS_7_OR_X509_ASN_ENCODING,
                // Указатель на CERT_CONTEXT, который будет использоваться при подписании.
                // Для того чтобы контекст предоставил доступ к закрытому сигнатурному ключу,
                // необходимо установить свойство CERT_KEY_PROV_INFO_PROP_ID или CERT_KEY_CONTEXT_PROP_ID
                pSigningCert = hCert,

                // Количество элементов в rgpMsgCert массиве CERT_CONTEXT структур.Если установлено ноль,
                // в подписанное сообщение не включаются сертификаты.
                cMsgCert = 1
            };

            CApiExtConst.CERT_CONTEXT contextCert = Marshal.PtrToStructure <CApiExtConst.CERT_CONTEXT>(hCert);
            CApiExtConst.CERT_INFO    certInfo    = Marshal.PtrToStructure <CApiExtConst.CERT_INFO>(contextCert.pCertInfo);

            var signatureAlg = SignServiceUtils.GetSignatureAlg(certInfo.SubjectPublicKeyInfo.Algorithm.pszObjId);
            var cryptOidInfo = GetHashAlg(signatureAlg);

            //Содержащий алгоритм хеширования, используемый для хеширования данных, подлежащих подписке.
            pParams.HashAlgorithm.pszObjId = cryptOidInfo.pszOID;

            // Массив указателей на буферы, содержащие содержимое, подлежащее подписке.
            IntPtr rgpbToBeSigned = Marshal.AllocHGlobal(data.Length);

            // Выделяем память под хранение сертификата
            GCHandle pGC = GCHandle.Alloc(hCert, GCHandleType.Pinned);

            try
            {
                // Массив указателей на контексты сертификатов для включения в подписанное сообщение.
                // Если хотим использовать сертификат для подписания, указатель на него должен быть в массиве rgpMsgCert.
                pParams.rgpMsgCert = pGC.AddrOfPinnedObject();
                Marshal.Copy(data, 0, rgpbToBeSigned, data.Length);

                // Указатель, определяющий размер в байтах буфера signArray .
                // Когда функция возвращается, эта переменная содержит размер в байтах подписанного и закодированного сообщения.
                uint signArrayLength = 0;

                // Указатель на буфер , для получения кодированного подписанного хэш, если detached является значение TRUE ,
                // или как кодированного контента и подписанного хэша , если detached является FALSE.
                byte[] signArray = null;

                // TRUE, если это должна быть отдельная подпись, Если для этого параметра установлено значение TRUE , в pbSignedBlob кодируется только подписанный хеш .
                // В противном случае кодируются как rgpbToBeSigned, так и подписанный хеш.
                bool detached = true;

                // Количество элементов массива в rgpbToBeSigned.
                // Этот параметр должен быть установлен в единицу, если для параметра fDetachedSignature установлено значение TRUE
                uint cToBeSigned = 1;

                // Подписываем данные
                // new uint[1] { (uint)data.Length } - Массив размеров в байтах буферов содержимого, на которые указывает rgpbToBeSigned
                if (!CApiExtWin.CryptSignMessage(ref pParams, detached, cToBeSigned, new IntPtr[1] {
                    rgpbToBeSigned
                }, new uint[1] {
                    (uint)data.Length
                }, signArray, ref signArrayLength))
                {
                    throw new CryptographicException($"Ошибка при подписании данных. Первый вызов CryptSignMessage вернул false. Код ошибки: {Marshal.GetLastWin32Error()}.");
                }

                signArray = new byte[signArrayLength];

                if (!CApiExtWin.CryptSignMessage(ref pParams, detached, cToBeSigned, new IntPtr[1] {
                    rgpbToBeSigned
                }, new uint[1] {
                    (uint)data.Length
                }, signArray, ref signArrayLength))
                {
                    throw new CryptographicException($"Ошибка при подписании данных. Второй вызов CryptSignMessage вернул false. Код ошибки: {Marshal.GetLastWin32Error()}.");
                }

                return(signArray);
            }
            finally
            {
                Marshal.FreeHGlobal(rgpbToBeSigned);
                pGC.Free();
            }
        }
Esempio n. 17
0
 protected override bool ReleaseHandle()
 {
     CApiExtWin.CryptReleaseContext(handle, 0);
     return(true);
 }
Esempio n. 18
0
        internal IntPtr FindCertificate(string thumbprint)
        {
            IntPtr handleSysStore = IntPtr.Zero;
            IntPtr handleCert     = IntPtr.Zero;

            // Формируем параметр для метода поиска
            CApiExtConst.CRYPT_HASH_BLOB hashb = new CApiExtConst.CRYPT_HASH_BLOB();

            try
            {
                log.LogDebug($"Пытаемся открыть 'MY' хранилище сертификатов для Текущего пользователя.");

                // Открываем хранилище сертификатов
                handleSysStore = CApiExtWin.CertOpenStore(CApiExtConst.CERT_STORE_PROV_SYSTEM, 0, IntPtr.Zero, CApiExtConst.CURRENT_USER, "MY");

                if (handleSysStore == IntPtr.Zero || handleSysStore == null)
                {
                    log.LogError("Не удалось открыть хранилище 'MY' для текущего пользователя.");
                    throw new CryptographicException("Ошибка, не удалось открыть хранилище 'MY' для текущего пользователя.");
                }

                log.LogDebug($"Личное хранилище сертификатов для Текущего пользователя успешно открыто.");
                log.LogDebug($"Пытаемся преобразовать значение Thumbprint в массив байт.");

                // Получаем значение thumbprint в виде массива байт
                byte[] sha1Hash = SignServiceUtils.HexStringToBinary(thumbprint);

                log.LogDebug("Значение Thumbprint успешно преобразовано в массив байт.");
                log.LogDebug("Пытаемся разместить бинарное значение Thumbprint в неуправляемой памяти.");

                try
                {
                    hashb.pbData = Marshal.AllocHGlobal(thumbprint.Length);
                    Marshal.Copy(sha1Hash, 0, hashb.pbData, sha1Hash.Length);
                    hashb.cbData = sha1Hash.Length;
                }
                catch (Exception ex)
                {
                    log.LogError($"Ошибка при попытке разместить значение Thumbprint в неуправляемой памяти. {ex.Message}.");
                    Marshal.FreeHGlobal(hashb.pbData);
                    throw new CryptographicException($"Ошибка при попытке разместить значение Thumbprint в неуправляемой памяти. {ex.Message}.");
                }

                log.LogDebug("Бинарное значение Thumbprint успешно размещено в неуправляемой памяти.");
                log.LogDebug("Пытаемся найти сертификат по Thumbprint данным в неуправляемой памяти.");

                // Ищем сертификат в хранилище
                handleCert = CApiExtWin.CertFindCertificateInStore(handleSysStore, CApiExtConst.PKCS_7_OR_X509_ASN_ENCODING, 0, CApiExtConst.CERT_FIND_SHA1_HASH, ref hashb, IntPtr.Zero);

                if (handleCert == IntPtr.Zero || handleCert == null)
                {
                    log.LogError("Ошибка при получении дескриптора сертификата из хранилища 'MY', для текущего пользователя.");
                    throw new CryptographicException("Ошибка при получении дескриптора сертификата из хранилища 'MY', для текущего пользователя.");
                }

                return(handleCert);
            }
            finally
            {
                Marshal.FreeHGlobal(hashb.pbData);
                CApiExtWin.CertCloseStore(handleSysStore, 0);
            }
        }
Esempio n. 19
0
        internal bool VerifyDetachedMessage(byte[] signatureData, byte[] messageData, bool isCheckTrusted, ref X509Certificate2 certFromSign)
        {
            log.LogDebug("Запущен метод проверки открепленной подписи под Windows платформой.");

            // Заполняем буфер с информацией о данных на основе которых получена подпись
            IntPtr messagePtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(byte)) * messageData.Length);

            Marshal.Copy(messageData, 0, messagePtr, messageData.Length);
            IntPtr[] rgpbToBeSigned = new IntPtr[1] {
                messagePtr
            };
            int[] rgcbToBeSigned = new int[1] {
                messageData.Length
            };
            GCHandle pCertContext = GCHandle.Alloc(IntPtr.Zero, GCHandleType.Pinned);

            CRYPT_VERIFY_MESSAGE_PARA verifyParams = new CRYPT_VERIFY_MESSAGE_PARA()
            {
                cbSize = (int)Marshal.SizeOf(typeof(CRYPT_VERIFY_MESSAGE_PARA)),
                dwMsgAndCertEncodingType = PKCS_7_OR_X509_ASN_ENCODING,
                hCryptProv = 0,
                pfnGetSignerCertificate = IntPtr.Zero,
                pvGetArg = IntPtr.Zero
            };

            try
            {
                log.LogDebug("Выполняем проверку открепленной подписи используя метод CryptVerifyDetachedMessageSignature.");

                bool result = CApiExtWin.CryptVerifyDetachedMessageSignature(
                    ref verifyParams,      // Verify parameters.
                    0,                     // Signer index.
                    signatureData,         // Buffer for decoded message.
                    signatureData.Length,  // Size of buffer.
                    1,
                    rgpbToBeSigned,        // Pointer to signed BLOB.
                    rgcbToBeSigned,        // Size of signed BLOB.
                    pCertContext.AddrOfPinnedObject()
                    );

                if (!result)
                {
                    log.LogError($"Метод проверки подписи CryptVerifyDetachedMessageSignature вернул ошибку. Статус код ошибки: {Marshal.GetLastWin32Error()}.");
                    return(result);
                }

                log.LogDebug($"Метод CryptVerifyDetachedMessageSignature вернул true. Пытаемся получить сертификат из подписи.");

                try
                {
                    log.LogDebug($"Флаг проверки сертификата в списке доверенных издателей {(isCheckTrusted ? "установлен" : "не установлен")}");

                    // Информацию о сертификате из подписи можно получить только если проверка вернула true, иначе возникнет исключение
                    certFromSign = new X509Certificate2((IntPtr)pCertContext.Target);

                    if (isCheckTrusted)
                    {
                        log.LogDebug("Сертификат из подписи успешно получен. Проверяем наличие сертификата в списке доверенных издателей.");

                        var trustedCerts = GetTrustedCertificates();

                        if (trustedCerts.Count <= 0)
                        {
                            log.LogError("Список доверенных издателей пуст. Отсутствует доверие к сертификату.");
                            return(false);
                        }

                        if (!trustedCerts.Contains(certFromSign))
                        {
                            log.LogError("Сертификат указанный в подписи не найден среди доверенных издателей.");
                            return(false);
                        }
                    }
                }
                catch (Exception ex)
                {
                    log.LogError($"Необработанная ошибка при попытке проверить сертификат из подписи на наличие в списке доверенных. {ex.Message}.");
                    return(false);
                }
                finally
                {
                    CApiExtWin.CertFreeCertificateContext((IntPtr)pCertContext.Target);
                }

                log.LogDebug("Проверка выполнена. Подпись корректна.");

                return(result);
            }
            finally
            {
                pCertContext.Free();
            }
        }
Esempio n. 20
0
 protected override bool ReleaseHandle()
 {
     CApiExtWin.CertCloseStore(handle, CApiExtConst.CERT_CLOSE_STORE_FORCE_FLAG);
     return(true);
 }
Esempio n. 21
0
 protected override bool ReleaseHandle()
 {
     CApiExtWin.CertFreeCertificateContext(handle);
     return(true);
 }