Подписание данных в браузере
Потратил несколько дней на обзор ситуации с подписанием документов в браузере. Что удалось выяснить...
Простое подписание документа при помощи DSIG в Windows (IE) невозможно. Для этого необходимо либо использовать нерекомендованную версию MSXML (5.0), либо самостоятельно заниматься такими малоприятными вещами, как покусочное формирование XML Digital Signature. Бесплатного COM-компонента или библиотеки для выполнения этой работы не существует. Это с одной стороны. С другой, есть .NET и XSign, но требования к текущей задачи не позволяют рассчитывать на наличие у пользователя хотя бы .NET 1.1, не говоря уже об XSign.
Хоть и очень хотелось, но от XMLDSIG пришлось отказаться. Вместо этого принято решение использовать цифровые подписи PKCS #7. На клиенте (в Internet Explorer) документ подписывается и в составе скрытого поля отправляется на сервер, там подпись проверяется и если всё в порядке, то и ... всё.
Если кратко. На клиенте (CAPICOM + C++)
- Дать выбрать сертификат из персонального хранилища текущего пользователя.
- Проверить факт выбора сертификата и наличие закрытого ключа (а то мало ли...)
- Подписать сообщение
IStorePtr store(__uuidof(Store));
HRESULT hr = store->Open(CAPICOM_CURRENT_USER_STORE, _T("My"), CAPICOM_STORE_OPEN_READ_ONLY);
if (FAILED(hr))
return hr;
ICertificates2Ptr ptr(store->Certificates);
ICertificates2Ptr selected = ptr->Select(_T(""), _T(""), VARIANT_FALSE);
ICertificate2Ptr p(selected->Item[1]);
ISignerPtr signer(__uuidof(CAPICOM::Signer));
signer->PutCertificate(CComQIPtr(p));
ISignedDataPtr data(__uuidof(SignedData));
data->put_Content(*m_Xml);
bstr_t signature = data->Sign(signer, FALSE, CAPICOM_ENCODE_BASE64);
m_Signature = new CComBSTR(signature.GetBSTR());
На сервере (.NET)
- Декодировать (привести в бинарный вид) полученное сообщение
byte[] data = Convert.FromBase64String(signature);
SignedCms cms = new SignedCms();
cms.Decode(signed);
Поскольку подпись объединена с исходным сообшением, то это всё. Только не забывайте, что CAPICOM выдаёт Unicode-строки, а .NET - если его не трогать специально - ожидает UTF-8 строк.
Комментариев нет:
Отправить комментарий