Отправить http запрос подписанный с помощью X509Certificate - C#
Формулировка задачи:
Добрый вечер.
Возникла задача, которую даже не знаю как теоретически решить.
Имеем:
Сайт с авторизацией через сертификат
JavaScript код на странице этого сайта. Одна из функций подписывает(цифровая подпись) XML данные и Submit'ит форму. Подпись ставится на основании выбираемого сертификата. Вызывается функция при нажатии на кнопку:
Необходимо:
Автоматизировать выбор сертификата и подписание заявки.
Я уже посмотрел какие данные отправляются при сабмите формы и попробовал отправить такой же POST-запрос через HttpWebRequest. Не помогло: ошибок нет, но данные не подписаны.
Переписал JavaScript код на C#, получил идентичную подпись, но и это не помогло.
Из идей осталось:
1)использовать "тяжелый" webbrowser(не понятно как использовать в нем X509Certificate)
2)выполнить просто скопированную функцию javascript, но тоже не знаю каким образом, так как она использует данные из document
Буду рад, если подскажете в каком направлении двигаться.
<INPUT id=ctl01_ctl01_btnSign onclick="esign(); __doPostBack('ctl01$ctl01$btnSign','')" name=ctl01$ctl01$btnSign value=Подписать type=button>
function esign() { //КОНСТАНТЫ STORE_LOCATION = 2; STORE_NAME = "My"; //UserObjectID в конфигурации сервера dsigObjectId = new String("TS_SO_Zayavka_polzovatelya"); //Инициализация active-x объектов (msxml) try { xmldoc = new ActiveXObject("MSXML2.DOMDocument.5.0"); xmldoce = new ActiveXObject("MSXML2.DOMDocument.5.0"); xmldsig = new ActiveXObject("Msxml2.MXDigitalSignature.5.0"); } catch (Exception) { alert(Exception.message); alert("Невозможно загрузить ActiveXObject MSXML2"); return null; } //Инициализация active-x объектов (capicom) try { oStore = new ActiveXObject("CAPICOM.Store.2"); oCerts = new ActiveXObject("CAPICOM.Certificates"); oSigner = new ActiveXObject("CAPICOM.Signer"); } catch(Exception) { alert(Exception.message); alert("Невозможно загрузить ActiveXObject CAPICOM"); return null; } //Текст заявки //text = build_xhtml(); xmldoc.loadXML(document.getElementById('ctl01_ctl01_hdnDemandXML').value); //Конверт xmldoce.async = false; xmldoce.validateOnParse = false; xmldoce.preserveWhiteSpace = false; xmldoce.resolveExternals = false; xmldoce.loadXML("<ds:Signature xmlns:ds='http://www.w3.org/2000/09/xmldsig#'><ds:SignedInfo><ds:CanonicalizationMethod Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315'/><ds:SignatureMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411'/><ds:Reference URI='#"+dsigObjectId+"' Type='http://www.w3.org/2000/09/xmldsig#;Object'><ds:DigestMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#gostr3411'/><ds:DigestValue/></ds:Reference></ds:SignedInfo><ds:SignatureValue/><ds:Object Id='"+dsigObjectId+"' MimeType='text/plain'/><ds:KeyInfo/></ds:Signature>"); xmldoce.setProperty("SelectionNamespaces", "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'"); //Размещение текста в конверт elmToWrap = xmldoc.documentElement.cloneNode(true); elmWhereTo = xmldoce.selectSingleNode("//*[@Id='" + dsigObjectId +"']"); elmWhereTo.appendChild(elmToWrap); xmldoc = xmldoce; xmldoce = null; //Пользователь выбирает сертификат try { oStore.Open(STORE_LOCATION, STORE_NAME, 128); oCerts = oStore.Certificates; if (oCerts.Count == 0) { alert("В личном хранилище нет сертификатов"); return null; } oSelectedCerts = oCerts.Select(); oSignerCert = oSelectedCerts(1); } catch(Exception) { // alert(Exception.description); alert(Exception.message); return null; } //Указатель на конверт xmldsig.signature = xmldoc.selectSingleNode("//*[count(ancestor::*)=0]"); //Доступ к секретному ключу сертификата try { pKey = xmldsig.createKeyFromCSP(oSignerCert.PrivateKey.ProviderType, oSignerCert.PrivateKey.ProviderName, oSignerCert.PrivateKey.ContainerName, 0); } catch(Exception) { //alert(Exception.description); alert(Exception.message); alert("Невозможно получить доступ к секретному ключу сертификата."); return null; } //Подпись конверта try { pKeyOut = xmldsig.sign(pKey, 2); } catch(Exception) { // alert(Exception.description); alert(Exception.message); alert("Невозможно подписать заявку."); return null; } //Отправка заявки на сервер document.getElementById("ctl01_ctl01_hdnDemandSidned").value = xmldoc.xml; //document.getElementById("Form1").submit(); return; }
Решение задачи: «Отправить http запрос подписанный с помощью X509Certificate»
textual
Листинг программы
var xmldoc = new DOMDocument50Class(); var xmldoce = new DOMDocument50Class(); var xmldsig = new MXDigitalSignature50Class(); xmldoc.loadXML(requestBody); //Конверт xmldoce.async = false; xmldoce.validateOnParse = false; xmldoce.preserveWhiteSpace = false; xmldoce.resolveExternals = false; xmldoce.loadXML(string.Format(Signature, ObjectId)); xmldoce.setProperty("SelectionNamespaces", "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'"); //Размещение текста в конверт IXMLDOMNode elmToWrap = xmldoc.documentElement.cloneNode(true); IXMLDOMNode elmWhereTo = xmldoce.selectSingleNode("//*[@Id='" + ObjectId + "']"); elmWhereTo.appendChild(elmToWrap); xmldoc = xmldoce; //Доступ к секретному ключу сертификата IXMLDSigKey pKey = xmldsig.createKeyFromCSP(providerType, string.Empty, containerName, 0); //Подпись конверта xmldsig.sign(pKey, XMLDSIG_WRITEKEYINFO.CERTIFICATES); return xmldoc.xml;
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д