Store.Open(,“My”)
call Store.Load(“C:\test\newcert.cer”)
‘допустим добавленный сертификат по индексу 1
Set Signer.Certificate = Store.Certificates(1) ‘НЕ РАБОТАЕТ
SignedData.Content = “Это надо подписать”
SignedData(Signer,,True) ‘подписываем без включения в подпись подписываемых данных
Capicom
у меня возникла некоторая проблема при реализации механизма ЭЦП через CAPICOM.
Описание:
Нужно подписать из HTML-страницы (detached подпись) некоторые данные с помощью приватного ключа, хранимого на дискете.
Ключ генерируется при запросе сертификата через Web certificate enroll.
Используется Базовый CSP v1.0.
Если при генерации запроса, указывается что нужно сгенерировать новый набор ключей для хранилища My, то естественно, никаких проблем потом не возникает: ключ хранится на локальной машине в персональном хранилище текущего пользователя, в реестре появляется запись о хранилище My. После подтверждения сертификата и его установки, для подписи используется DataSigner объект, который по умолчанию использует установленный сертификат и соответствующий ему ключ локального хранилища “My” пользователя.
Альтернативно, при создании запроса на сертификат можно указать, что ключ будет экспортируемый, указать имя файла, в который сохранить сгенерированный набор ключей. При сохранении ключа в файл, получаемый сертификат не помещается в хранилище My.
Но в DataSigner можно указать объект Signer, с помощью которого подписываются данные. Я почему-то думал, что, используя метод Load объекта Signer, можно будет загрузить ключ на альтернативном носителе, типа дискета. Не получилось – выдает ошибку.
Тогда я подумал, что раз SignedData использует My-хранилище, то можно динамически открыть хранилище My, добавить туда сертификат из файла *.cer, при подписи использовать его и файл ключа, затем удалить все добавленные данные (подразумевается, что на любой машине пользователь может подпись делать).
Проблема как раз в «при подписи использовать сертификат и файл ключа», так как явной связи между Store объектом и SignedData нет. Попробовал связать так (VB):
Код:
В чем проблема?
Можно ли вообще подписать с помощью CAPICOM по ключу и сертификату на дискете.
Может, как-то по-особому надо было запрашивать сертификат и генерировать ключи, с определенными параметрами?
P.S. Извиняйте, если в коде ошибки. Сейчас нет CAPICOM-библиотеки под рукой, не могу проверить. И MSDN древний – 2001 года, в нем предварительная документация на CAPICOM только есть, многие методы отсутствуют.
Фактически: обошел.
Кому интересно:
Если при запросе сертификата сохранять ключ отдельно, не в хранилище, то так и не нашел способа потом связать полученный сертификат и набор ключей в CAPICOM для подписи.
Сделал по-другому:
Сертификат запрашивается нормально с генерацией ключа в персональном хранилище My (но набор ключа помечается экспортируемым). После утверждения в центре сертификации, инсталлирую сертификат, который сам связывается с хранимым для него набором ключей. Чтобы перенести сертификат с приватным ключом на внешний носитель пишу скрипт-утилиту:
(Опять нет под рукой ни помощи ни библиотеки, поэтому псевдокодом:
Код:
Store.Open( ТИП_ХРАНИЛИЩА_ПОЛЬЗОВАТЕЛЬСКОЕ ,"My", НА_ЧТЕНИЕ_И_ЗАПИСЬ)
Set Cert = Store.Certificates.Select()(1) 'диалог для выбора экспортируемого сертификата, по идее фильтровать надо по допустимости на экспорт, ну да ладно
Cert.save(ИМЯ_ФАЙЛА_PFX, ПАРОЛЬ_ШИФРОВАНИЯ_ФАЙЛА, СОХРАНИТЬ_В_ФОРМАТЕ_PFX) 'этот формат экспортирует приватный ключ с сертификатом.
Store.Certificates.remove(Cert) 'удаляем из локального хранилища
Set Cert = Store.Certificates.Select()(1) 'диалог для выбора экспортируемого сертификата, по идее фильтровать надо по допустимости на экспорт, ну да ладно
Cert.save(ИМЯ_ФАЙЛА_PFX, ПАРОЛЬ_ШИФРОВАНИЯ_ФАЙЛА, СОХРАНИТЬ_В_ФОРМАТЕ_PFX) 'этот формат экспортирует приватный ключ с сертификатом.
Store.Certificates.remove(Cert) 'удаляем из локального хранилища
А зашифровываем с помощью загрузки PFX-файла в объект Signer:
Код:
Signer.Load(ПОЛНОЕ_ИМЯ_ФАЙЛА_PFX, ПАРОЛЬ_РАСШИФРОВКИ)
SignedData.Content = "Текст для зашифровки"
signature = SignedData.Sign(Signer, True) 'detached подпись
SignedData.Content = "Текст для зашифровки"
signature = SignedData.Sign(Signer, True) 'detached подпись
Одна проблема - метод Load объекта Signer нельзя напрямую из HTML страницы вызвать, пришлось обертку написать :) - ужас, наверное проще было бы CryptoAPI использовать напрямую, все равно не получилось все скриптами поделать. Теперь на странице будет 2 ActiveX объекта инсталиться: CAPICOM и мой CAPICOMHelper - умора, только плачу почему-то сижу.
Итого: криво, но работает.
P.S.
Если кто-нибудь все-таки найдет, как без таких сложностей проделать подпись с HTML-страницы ключем с дискетки - напишите, пожалуйста.