/// <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); } }
/// <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); }
/// <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); } }