Отправить 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;