コード例 #1
0
        /// <summary>
        /// Метод вычисления подписи без использования закрытого ключа
        /// </summary>
        /// <param name="prefix"></param>
        /// <param name="certificate"></param>
        public void ComputeSignatureWithoutPrivateKey(string prefix, IntPtr certificate)
        {
            if (SignServiceUtils.IsUnix)
            {
                CryptoConfig.AddAlgorithm(typeof(HashAlgGost2001Unix), new string[1] {
                    "http://www.w3.org/2001/04/xmldsig-more#gostr3411"
                });
                CryptoConfig.AddAlgorithm(typeof(HashAlgGost2012_256Unix), new string[1] {
                    "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-256"
                });
                CryptoConfig.AddAlgorithm(typeof(HashAlgGost2012_512Unix), new string[1] {
                    "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-512"
                });
            }
            else
            {
                CryptoConfig.AddAlgorithm(typeof(HashAlgGost2001Win), new string[1] {
                    "http://www.w3.org/2001/04/xmldsig-more#gostr3411"
                });
                CryptoConfig.AddAlgorithm(typeof(HashAlgGost2012_256Win), new string[1] {
                    "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-256"
                });
                CryptoConfig.AddAlgorithm(typeof(HashAlgGost2012_512Win), new string[1] {
                    "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-512"
                });
            }

            CryptoConfig.AddAlgorithm(typeof(SmevTransformAlg), new string[1] {
                SmevTransformAlg.ALGORITHM_URI
            });

            BuildDigestedReferences();

            int           algId = 0;
            HashAlgorithm hash  = SignServiceUtils.GetHashAlgObject(certificate, ref algId);

            GetDigest(hash, prefix);

            uint   keySpec  = CApiExtConst.AT_SIGNATURE;
            IntPtr cpHandle = (SignServiceUtils.IsUnix) ? UnixExtUtil.GetHandler(certificate, out keySpec) : Win32ExtUtil.GetHandler(certificate, out keySpec);

            byte[] sign = (SignServiceUtils.IsUnix) ? UnixExtUtil.SignValue(cpHandle, (int)keySpec, hash.Hash, (int)0, algId) :
                          Win32ExtUtil.SignValue(cpHandle, (int)keySpec, hash.Hash, (int)0, algId);

            Array.Reverse(sign);
            m_signature.SignatureValue = sign;

            SignServiceUtils.ReleaseProvHandle(cpHandle);
        }
コード例 #2
0
        /// <summary>
        /// Метод рассчета хэш
        /// </summary>
        /// <param name="data"></param>
        /// <param name="publicKeyAlg"></param>
        /// <param name="pluginHashAlg"></param>
        /// <returns></returns>
        private string ComputeHash(Stream data, string publicKeyAlg, ref int pluginHashAlg)
        {
            log.LogDebug($"Определяем алгоритм хэширования по значению алгоритма публичного ключа: {publicKeyAlg}.");
            // Определение алгоритма.
            var algId = GetHashAlg(publicKeyAlg);

            log.LogDebug("Определяем идентификатор алгоритма для использования в плагине КриптоПро.");
            // Определение идентификатора алгоритма для использование в плагине КриптоПро.
            var hashAlgForPlugin = SignServiceUtils.GetHashCodeForPlugin(algId);

            pluginHashAlg = hashAlgForPlugin;

            log.LogDebug("Вычисляем хэш.");
            // Вычисление хэш.
            var base64Hash = GetHashBySigAlgId(data, algId);

            return(base64Hash);
        }
コード例 #3
0
        /// <summary>
        /// Метод получения хэш
        /// </summary>
        /// <param name="data"></param>
        /// <param name="algId"></param>
        /// <returns></returns>
        internal string GetHashBySigAlgId(Stream data, uint algId)
        {
            log.LogDebug("Запущен метод получения хэш под Windows платформой.");

            byte[] hashResult = null;

            if (algId == CApiExtConst.GOST341194)
            {
                log.LogDebug($"Полученный алгоритм хэширования {algId} соответствует ГОСТ-2001");
                HashAlgorithm hash = new HashAlgGost2001Win();
                hashResult = hash.ComputeHash(data);
            }
            else if (algId == CApiExtConst.GOST2012_256)
            {
                log.LogDebug($"Полученный алгоритм хэширования {algId} соответствует ГОСТ-2012-256");
                var hash = new HashAlgGost2012_256Win();
                hashResult = hash.ComputeHash(data);
            }
            else if (algId == CApiExtConst.GOST2012_512)
            {
                log.LogDebug($"Полученный алгоритм хэширования {algId} соответствует ГОСТ-2012-512");
                var hash = new HashAlgGost2012_512Win();
                hashResult = hash.ComputeHash(data);
            }
            else
            {
                log.LogError($"Полученный алгоритм хэширования {algId} не соответствует поддерживаемым ГОСТ алгоритмам.");
                throw new Exception($"Полученный алгоритм хэширования {algId} не соответствует поддерживаемым ГОСТ алгоритмам.");
            }

            if (hashResult == null || hashResult.Length <= 0)
            {
                log.LogError("Не удалось вычислить хэш. Отсутствует значение.");
                throw new CryptographicException("Ошибка при получении хэш.");
            }

            log.LogDebug($"Хэш получен. Преобразуем в Hex строку.");

            var hexStr = SignServiceUtils.ConvertByteToHex(hashResult);

            log.LogDebug("Преобразование выполнено успешно.");

            return(hexStr);
        }
コード例 #4
0
        /// <summary>
        /// Метод получения алгоритма хэширования
        /// </summary>
        /// <param name="signatureAlgOid"></param>
        /// <returns></returns>
        private uint GetHashAlg(string publicKeyAlg)
        {
            string signatureAlgOid = SignServiceUtils.GetSignatureAlg(publicKeyAlg);

            if (SignServiceUtils.IsUnix)
            {
                log.LogDebug("Получаем алгоритм хэширования под Unix платформой.");

                var cryptOidInfo = SignServiceUnix.GetHashAlg(signatureAlgOid);
                return(cryptOidInfo.Algid);
            }
            else
            {
                log.LogDebug("Получаем алгоритм хэширования под Windows платформой.");

                var cryptOidInfo = SignServiceWin.GetHashAlg(signatureAlgOid);
                return(cryptOidInfo.Algid);
            }
        }
コード例 #5
0
        internal X509Certificate2Collection GetTrustedCertificates()
        {
            log.LogDebug("Пытаемся получить доступ к хранилищу доверенных сертификатов текущего пользователя.");
            IntPtr handleSysStore = IntPtr.Zero;

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

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

                IntPtr currentCertContext = CApiExtUnix.CertEnumCertificatesInStore(handleSysStore, IntPtr.Zero);
                X509Certificate2Collection trustedList = new X509Certificate2Collection();

                while (currentCertContext != IntPtr.Zero)
                {
                    // Формируем X509Certificate2 из IntPtr
                    var x509Certificate2 = SignServiceUtils.GetX509Certificate2(currentCertContext);
                    trustedList.Add(x509Certificate2);

                    currentCertContext = CApiExtUnix.CertEnumCertificatesInStore(handleSysStore, currentCertContext);
                }

                return(trustedList);
            }
            finally
            {
                // Закрываем хранилище сертификатов
                CApiExtUnix.CertCloseStore(handleSysStore, 0);
            }
        }
コード例 #6
0
        /// <summary>
        /// Метод добавляет в XML тэг <ds:Reference></Reference>
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="signedXml"></param>
        /// <param name="customTag"></param>
        /// <param name="customNamespace"></param>
        /// <param name="precedingSibling"></param>
        /// <returns></returns>
        internal static SignedXml AddReference(XmlDocument doc, SignedXml signedXml, IntPtr certificate, bool signWithId, Mr mr,
                                               SignedTag elemForSign,
                                               ref int idCounter,
                                               string tagForSign,
                                               string tagForSignNamespaceUri,
                                               string namespaceIdAttr = "",
                                               string customTag       = "",
                                               string customNamespace = ""
                                               )
        {
            Reference reference = new Reference();
            string    id        = string.Empty;

            if (elemForSign == SignedTag.CustomTag && string.IsNullOrEmpty(customTag) != true)
            {
                id = SmevXmlHelper.GetElemId(doc, customTag, customNamespace, signWithId);

                if (string.IsNullOrEmpty(id) && signWithId)
                {
                    if (mr == Mr.MR300)
                    {
                        SmevXmlHelper.SetElemId(doc, customTag, NamespaceUri.WSSoap11, signWithId, mr, ref idCounter);
                    }
                    else
                    {
                        id = "#" + SmevXmlHelper.SetElemId(doc, customTag, tagForSignNamespaceUri, signWithId, mr, ref idCounter, "", namespaceIdAttr);
                    }
                }
            }
            else
            {
                id = SmevXmlHelper.GetElemId(doc, tagForSign, tagForSignNamespaceUri, signWithId);

                if (string.IsNullOrEmpty(id) && signWithId)
                {
                    if (mr == Mr.MR300)
                    {
                        id = SmevXmlHelper.SetElemId(doc, tagForSign, tagForSignNamespaceUri, signWithId, mr, ref idCounter);
                    }
                    else
                    {
                        id = "#" + SmevXmlHelper.SetElemId(doc, tagForSign, tagForSignNamespaceUri, signWithId, mr, ref idCounter, "", namespaceIdAttr);
                    }
                }
            }

            reference.Uri          = (signWithId) ? id : string.Empty;
            reference.DigestMethod = SignServiceUtils.GetDigestMethod(SignServiceUtils.GetAlgId(certificate));

            if (string.IsNullOrEmpty(customTag) != true && elemForSign == SignedTag.CustomTag)
            {
                XmlDsigEnvelopedSignatureTransform envelop = new XmlDsigEnvelopedSignatureTransform();
                reference.AddTransform(envelop);
            }

            XmlDsigExcC14NTransform c14 = new XmlDsigExcC14NTransform();

            reference.AddTransform(c14);

            if (mr == Mr.MR300)
            {
                SmevTransformAlg smevTransform = new SmevTransformAlg();
                reference.AddTransform(smevTransform);
            }

            signedXml.AddReference(reference);

            return(signedXml);
        }
コード例 #7
0
        /// <summary>
        /// Метод подписи XML подписью органа власти
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="certificate"></param>
        /// <returns></returns>
        public XmlDocument SignMessageAsOv(XmlDocument doc, IntPtr certificate)
        {
            try
            {
                // Подписываем вложения
                log.LogDebug("Пытаемся подписать вложения.");
                doc = SignAttachmentsOv(doc, certificate);
            }
            catch (Exception ex)
            {
                log.LogError($"Ошибка при попытке проверить и подписать вложения в методе. {ex.Message}.");
                throw new CryptographicException($"Ошибка при попытке проверить и подписать вложения. {ex.Message}");
            }

            try
            {
                // Подписываем XML
                log.LogDebug("Пытаемся подписать XML.");
                Smev3xxSignedXml signedXml = new Smev3xxSignedXml(doc);

                ElemForSign = SignedTag.Smev3TagType;

                try
                {
                    log.LogDebug($"Пытаемся найти тэг для подписи.");
                    tagForSign = FindSmevTagForSign(doc);
                    log.LogDebug($"Тэг для подписи: {tagForSign}.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке определить тэг для подписи. {ex.Message}.");
                }

                try
                {
                    log.LogDebug("Пытаемся удалить информацию о подписи, если есть.");
                    RemoveCallerInformationSystemSignature(doc.DocumentElement);
                    log.LogDebug("Удаление выполнено успешно.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке удалить информацию о подписи. {ex.Message}.");
                }

                try
                {
                    log.LogDebug($"Пытаемся установить значение идентификатора элемента. Флаг SignWithId: {SignWithId}.");
                    SmevXmlHelper.SetElemId(doc, tagForSign, tagForSignNamespaceUri, SignWithId, MrVersion, ref idCounter, SmevMr3xxTags.InformationSystemSignatureId);
                    log.LogDebug($"Установка значения идентификатора элемента выполнена успешно.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке установить идентификатор элемента. {ex.Message}.");
                }

                try
                {
                    log.LogDebug($"Пытаемся добавить в XML тэг Reference.");
                    signedXml = (Smev3xxSignedXml)SmevXmlHelper.AddReference(doc, signedXml, certificate,
                                                                             SignWithId, MrVersion, ElemForSign, ref idCounter, tagForSign, tagForSignNamespaceUri
                                                                             );
                    log.LogDebug($"Тэг Reference успешно добавлен.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при добавлении тэга Reference. {ex.Message}.");
                }

                signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;

                try
                {
                    log.LogDebug($"Пытаемся получить значение SignatureMethod.");
                    signedXml.SignedInfo.SignatureMethod = SignServiceUtils.GetSignatureMethod(SignServiceUtils.GetAlgId(certificate));
                    log.LogDebug($"Значение SignatureMethod успешно получено: {signedXml.SignedInfo.SignatureMethod}.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при получении значения алгоритма подписи. {ex.Message}.");
                }

                try
                {
                    KeyInfo          keyInfo = new KeyInfo();
                    X509Certificate2 cert    = SignServiceUtils.GetX509Certificate2(certificate);
                    keyInfo.AddClause(new KeyInfoX509Data(cert));
                    signedXml.KeyInfo = keyInfo;
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при формировании элемента KeyInfo. {ex.Message}.");
                }

                try
                {
                    log.LogDebug($"Пытаемся вычислить подпись.");
                    signedXml.ComputeSignatureWithoutPrivateKey(xmldsigPrefix, certificate);
                    log.LogDebug($"Вычисление подписи выполнено успешно.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке вычислить подпись для XML. {ex.Message}.");
                }

                XmlElement signatureElem = null;
                XmlElement sysSignature  = null;

                try
                {
                    log.LogDebug("Пытаемся получить элемент с подписью.");
                    signatureElem = signedXml.GetXml(xmldsigPrefix);
                    log.LogDebug("Элемент с подписью успешно получен.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке получить элемент содержащий подпись. {ex.Message}.");
                }

                string prefix = FindPrefix(doc.DocumentElement, false);

                try
                {
                    log.LogDebug("Заполняем объект sysSignature элементом в с подписью и префиксом.");

                    if (!string.IsNullOrEmpty(prefix))
                    {
                        sysSignature = doc.CreateElement(prefix, SignatureTags.CallerInformationSystemSignatureTag, SignatureTags.CallerInformationSystemSignatureNamespace);
                        sysSignature.PrependChild(doc.ImportNode(signatureElem, true));
                    }
                    else
                    {
                        sysSignature = doc.CreateElement("", SignatureTags.CallerInformationSystemSignatureTag, SignatureTags.CallerInformationSystemSignatureNamespace);
                        sysSignature.PrependChild(doc.ImportNode(signatureElem, true));
                    }

                    log.LogDebug("Заполнение объекта sysSignature успешно выполнено.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке сформировать элемент sysSignature. {ex.Message}.");
                }

                try
                {
                    log.LogDebug("Пытаемся добавить подпись в XML содержимое.");
                    FillSignatureElement(doc, sysSignature, certificate, tagForRequest, tagForRequestNamespaceUri, true);
                    log.LogDebug("Подпись успешно добавлена.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке заполнить XML информацией о подписи. {ex.Message}.");
                }

                return(doc);
            }
            catch (Exception ex)
            {
                log.LogError($"Ошибка при попытке подписать XML. {ex.Message}. StackTrace: {ex.StackTrace}.");
                throw new CryptographicException($"Ошибка при попытке подписать XML для версии МР300. {ex.Message}.");
            }
            finally
            {
                SignServiceUtils.FreeHandleCertificate(certificate);
            }
        }
コード例 #8
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();
            }
        }
コード例 #9
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);
            }
        }
コード例 #10
0
        internal bool VerifyDetachedMessage(byte[] signatureData, byte[] messageData, bool isCheckTrusted, ref X509Certificate2 certFromSign)
        {
            log.LogDebug("Запущен метод проверки открепленной подписи под Unix платформой.");

            // Заполняем буфер с информацией о данных на основе которых получена подпись
            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("Выполняем проверку открепленной подписи.");

                bool result = CApiExtUnix.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 ? "установлен" : "не установлен")}");

                    if ((IntPtr)pCertContext.Target != IntPtr.Zero)
                    {
                        certFromSign = SignServiceUtils.GetX509Certificate2((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
                {
                    CApiExtUnix.CertFreeCertificateContext((IntPtr)pCertContext.Target);
                }

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

                return(result);
            }
            finally
            {
                pCertContext.Free();
            }
        }
コード例 #11
0
        /// <summary>
        /// Добавляет тэг с подписью целиком. Сертификат должен быть в тэге подписи.
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="signatureElem"></param>
        /// <param name="certificate"></param>
        /// <param name="token"></param>
        private void FillSignatureElement(XmlDocument doc, XmlElement signatureElem, IntPtr certificate, XmlElement token)
        {
            XmlElement   wsseSecurity = doc.CreateElement("wsse", SignatureTags.SecurityTag, SignatureTags.SecurityNamespace);          // <wsse:Security soap:actor="http://smev.gosuslugi.ru/actors/recipient" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            XmlAttribute actorAttr    = doc.CreateAttribute("soap", "actor", NamespaceUri.WSSoap11);

            // МР 2.4.5. Информационная система органа власти Потребителя или ПГУ при формировании
            // запроса к ИС поставщика, а также ИС Поставщика при формировании ответа должны
            // проставлять в атрибуте actor значение, соответствующее СМЭВ как стороне проверяющей
            // подпись:
            // 38
            // soapenv:actor="http://smev.gosuslugi.ru/actors/smev"
            // СМЭВ при формировании электронной подписи в запросе при отправке его поставщику
            // или при отправке ответа к потребителю проставляет в атрибуте actor значение:
            // soapenv:actor="http://smev.gosuslugi.ru/actors/recipient"

            // МР 2.5.5. При взаимодействии на уровне регионального узла СМЭВ между региональными
            // участниками, подключенными к данному узлу, предусматриваются такие же правила
            // взаимодействия информационных систем участников с узлом РСМЭВ, как и для
            // федерального узла СМЭВ:
            // формирование ЭП-ОВ от имени ИС регионального участника осуществляется с
            // использованием атрибута actor="http://smev.gosuslugi.ru/actors/smev";
            // региональный узел СМЭВ формирует ЭП-РСМЭВ с использованием атрибута
            // actor="http://smev.gosuslugi.ru/actors/recipient" (данный формат является
            // локальным).
            actorAttr.Value = SmevAttributes.ActorSmev;
            wsseSecurity.Attributes.Append((XmlAttribute)doc.ImportNode(actorAttr, true));

            XmlElement keyInfoElem        = doc.CreateElement("KeyInfo", NamespaceUri.WSXmlDSig);
            XmlElement binaryTokenElem    = doc.CreateElement("wsse", "BinarySecurityToken", NamespaceUri.OasisWSSecuritySecext);
            XmlElement tokenReferenceElem = doc.CreateElement("wsse", "SecurityTokenReference", NamespaceUri.OasisWSSecuritySecext);

            XmlElement referenceElem = doc.CreateElement("wsse", "Reference", NamespaceUri.OasisWSSecuritySecext);

            string       certId = "uuid-" + Guid.NewGuid().ToString();
            XmlAttribute idAttr = doc.CreateAttribute("u", "Id", NamespaceUri.OasisWSSecurityUtility);

            idAttr.Value = certId;
            binaryTokenElem.Attributes.Append((XmlAttribute)doc.ImportNode(idAttr, true));

            XmlAttribute valueTypeAttr = doc.CreateAttribute("ValueType");

            valueTypeAttr.Value = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3";
            referenceElem.Attributes.Append((XmlAttribute)doc.ImportNode(valueTypeAttr, true));

            XmlAttribute uriAttr = doc.CreateAttribute("URI");             // URI="#CertId-5F344A8A21BB6902C113550467558881327"

            uriAttr.Value = "#" + certId;
            referenceElem.Attributes.Append((XmlAttribute)doc.ImportNode(uriAttr, true));

            tokenReferenceElem.PrependChild(doc.ImportNode(referenceElem, true));

            keyInfoElem.PrependChild(doc.ImportNode(tokenReferenceElem, true));

            X509Certificate2 cert = SignServiceUtils.GetX509Certificate2(certificate);

            binaryTokenElem.InnerText = Convert.ToBase64String(cert.RawData);

            wsseSecurity.PrependChild(doc.ImportNode(signatureElem, true));

            wsseSecurity.PrependChild(doc.ImportNode(token, true));

            XmlElement headerElem = (XmlElement)doc.GetElementsByTagName("Header", NamespaceUri.WSSoap11)[0];

            if (headerElem == null)
            {
                headerElem = doc.CreateElement("Header", NamespaceUri.WSSoap11);
                doc.DocumentElement.PrependChild(headerElem);
            }

            RemoveSecurityBodes(headerElem);

            headerElem.PrependChild(doc.ImportNode(wsseSecurity, true));
        }
コード例 #12
0
        /// <summary>
        /// Метод подписи XML подписью органа власти
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="certificate"></param>
        /// <returns></returns>
        private XmlDocument SignMessage2XX(XmlDocument xml, IntPtr certificate)
        {
            try
            {
                // Удаляем тэг Actor
                string message = string.Empty;

                try
                {
                    log.LogDebug("Пытаемся удалить атрибут 'Actor'.");
                    message = SoapDSigUtil.RemoveActor(xml);
                    log.LogDebug("Атрибут 'Actor' успешно удален.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке удалить атрибут 'Actor'. {ex.Message}.");
                }

                XmlDocument doc = new XmlDocument()
                {
                    PreserveWhitespace = true
                };

                try
                {
                    doc.LoadXml(message);
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при формировании XML после удаления атрибута 'Actor'. {ex.Message}.");
                }

                try
                {
                    log.LogDebug("Получаем значение тэга для подписи.");
                    this.tagForSign = this.FindSmevTagForSign(doc);
                    log.LogDebug($"Значение тэга для подписи получено. {tagForSign}.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке получить тэг с элементом для подписи. {ex.Message}.");
                }

                SmevSignedXml signedXml = new SmevSignedXml(doc);

                try
                {
                    log.LogDebug($"Выполняем добавление элемента Reference в XML.");

                    signedXml = (SmevSignedXml)SmevXmlHelper.AddReference(doc, signedXml, certificate,
                                                                          SignWithId,
                                                                          mrVersion,
                                                                          ElemForSign,
                                                                          ref idCounter,
                                                                          tagForSign,
                                                                          tagForSignNamespaceUri,
                                                                          namespaceIdAttr: NamespaceUri.OasisWSSecurityUtility
                                                                          );

                    log.LogDebug($"Добавление элемента Reference в XML выполнено успешно.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке добавить элемент Reference. {ex.Message}.");
                }

                signedXml.NamespaceForReference             = NamespaceUri.OasisWSSecurityUtility;
                signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;

                try
                {
                    log.LogDebug($"Пытаемся получить значение SignatureMethod.");
                    signedXml.SignedInfo.SignatureMethod = SignServiceUtils.GetSignatureMethod(SignServiceUtils.GetAlgId(certificate));
                    log.LogDebug($"Значение SignatureMethod успешно получено: {signedXml.SignedInfo.SignatureMethod}.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке получить значение метода подписи. {ex.Message}.");
                }

                XmlElement keyInfoElem        = doc.CreateElement("KeyInfo", NamespaceUri.WSXmlDSig);
                XmlElement binaryTokenElem    = doc.CreateElement("wsse", "BinarySecurityToken", NamespaceUri.OasisWSSecuritySecext);
                XmlElement tokenReferenceElem = doc.CreateElement("wsse", "SecurityTokenReference", NamespaceUri.OasisWSSecuritySecext);

                XmlElement referenceElem = doc.CreateElement("wsse", "Reference", NamespaceUri.OasisWSSecuritySecext);

                string       certId                = "uuid-" + Guid.NewGuid().ToString();
                XmlAttribute idAttr                = doc.CreateAttribute("u", "Id", NamespaceUri.OasisWSSecurityUtility);
                XmlAttribute valueTypeTokenAttr    = doc.CreateAttribute("ValueType");
                XmlAttribute encodingTypeTokenAttr = doc.CreateAttribute("EncodingType");

                idAttr.Value                = certId;
                valueTypeTokenAttr.Value    = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3";
                encodingTypeTokenAttr.Value = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary";

                binaryTokenElem.Attributes.Append((XmlAttribute)doc.ImportNode(idAttr, true));
                binaryTokenElem.Attributes.Append((XmlAttribute)doc.ImportNode(valueTypeTokenAttr, true));
                binaryTokenElem.Attributes.Append((XmlAttribute)doc.ImportNode(encodingTypeTokenAttr, true));

                X509Certificate2 cert = SignServiceUtils.GetX509Certificate2(certificate);
                binaryTokenElem.InnerText = Convert.ToBase64String(cert.RawData);

                XmlAttribute valueTypeAttr = doc.CreateAttribute("ValueType");
                valueTypeAttr.Value = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3";
                referenceElem.Attributes.Append((XmlAttribute)doc.ImportNode(valueTypeAttr, true));

                XmlAttribute uriAttr = doc.CreateAttribute("URI");
                uriAttr.Value = "#" + certId;

                referenceElem.Attributes.Append((XmlAttribute)doc.ImportNode(uriAttr, true));
                tokenReferenceElem.PrependChild(doc.ImportNode(referenceElem, true));
                keyInfoElem.PrependChild(doc.ImportNode(tokenReferenceElem, true));

                try
                {
                    KeyInfoNode keyNode = new KeyInfoNode(tokenReferenceElem);
                    KeyInfo     keyInfo = new KeyInfo();
                    keyInfo.AddClause(keyNode);
                    signedXml.KeyInfo = keyInfo;
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при формировании элемента KeyInfo. {ex.Message}.");
                }

                try
                {
                    log.LogDebug($"Пытаемся вычислить подпись.");
                    signedXml.ComputeSignatureWithoutPrivateKey(xmldsigPrefix, certificate);
                    log.LogDebug($"Вычисление подписи выполнено успешно.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке вычислить подпись для XML. {ex.Message}.");
                }

                XmlElement signatureElem = null;

                try
                {
                    log.LogDebug("Пытаемся получить элемент с подписью.");
                    signatureElem = signedXml.GetXml(xmldsigPrefix);
                    log.LogDebug("Элемент с подписью успешно получен.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке получить элемент содержащий подпись. {ex.Message}.");
                }

                try
                {
                    log.LogDebug("Пытаемся добавить подпись в XML содержимое.");
                    FillSignatureElement(doc, signatureElem, certificate, binaryTokenElem);
                    log.LogDebug("Подпись успешно добавлена.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке заполнить XML информацией о подписи. {ex.Message}.");
                }

                try
                {
                    log.LogDebug("Пытаемся добавить атрибут 'Actor'.");
                    SoapDSigUtil.AddActor(doc);
                    log.LogDebug("Атрибут 'Actor' успешно добавлен.");
                }
                catch (Exception ex)
                {
                    throw new Exception($"Ошибка при попытке добавить атрибут 'Actor'. {ex.Message}.");
                }

                return(doc);
            }
            catch (Exception ex)
            {
                log.LogError($"Ошибка при попытке подписать XML. {ex.Message}.");
                throw new CryptographicException($"Ошибка при попытке подписать XML для версии {mrText[mrVersion]}. {ex.Message}.");
            }
            finally
            {
                SignServiceUtils.FreeHandleCertificate(certificate);
            }
        }