Статус: Участник
Группы: Участники
Зарегистрирован: 28.04.2008(UTC) Сообщений: 11
|
ниже представлен тестовый пример, который подписывает тестовые данные и тут же проверяет подпись. проблема в том, что подпись является невалидной. Код:
# идентификатор юзера, по которому находится сертияикат (ниже)
my $user = '18b729e9d7485c1b12964e2ef3fba8a8';
my $data = '1234567890';
# ищем сертификат
my $Store = Win32::OLE->new('CAPICOM.Store') or die "Cannot start CAPICOM.Store";
$Store->Open( CAPICOM_CURRENT_USER_STORE, "My", CAPICOM_STORE_OPEN_READ_ONLY );
my $Certificates = $Store->Certificates;
my $certificate;
for ( my $i = 1 ; $i <= $Certificates->Count() ; $i++ ) {
my $Certificate = $Certificates->Item($i);
if ( hashSubjectName( $Certificate->SubjectName() ) eq $user ) {
$certificate = $Certificate;
last;
}
}
# да, наш сертификат, имеет приватный ключ $Certificate->HasPrivateKey()
print $certificate->SubjectName();
# подписываем выше найденным сертификатом
my $Signer = Win32::OLE->new('CAPICOM.Signer') or die "Cannot start CAPICOM.Signer";
$Signer->LetProperty( 'Certificate', $certificate );
my $SignedData = Win32::OLE->new('CAPICOM.SignedData') or die "Cannot start CAPICOM.SignedData";
$SignedData->LetProperty( 'Content', $data ); # или $SignedData->Content($data) ?
my $signature = $SignedData->Sign( $Signer, 1, CAPICOM_ENCODE_BASE64 );
# что-то есть
print $signature;
# проверяем подпись
my $SignedData = Win32::OLE->new('CAPICOM.SignedData') or die "Cannot start CAPICOM.SignedData";
$SignedData->LetProperty( 'Content', $data ); #или $SignedData->Content($data) ?
# возвращается undef, что значает, что подпись неверна (и так ли это?)
print $SignedData->Verify( $signature, 1, CAPICOM_VERIFY_SIGNATURE_ONLY );
если вывести все переменные сертификата из подписи(!) - $SignedData->Certificates(1); - то окажется, что он похож на исходный сертификатор (которым подписывали), НО он не имеет приватного ключа ($Certificate->HasPrivateKey()) в каком месте я допускаю ошибку? имеет смысл использовать CAPICOM_VERIFY_SIGNATURE_AND_CERTIFICATE ? заранее спасибо. Отредактировано пользователем 29 апреля 2008 г. 22:23:08(UTC)
| Причина: Не указана
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 25.12.2007(UTC) Сообщений: 1,733  Откуда: КРИПТО-ПРО Поблагодарили: 177 раз в 168 постах
|
Попробуйте тоже самое с присоединенной подписью |
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 28.04.2008(UTC) Сообщений: 11
|
Kirill Sobolev написал:Попробуйте тоже самое с присоединенной подписью правильно я понимаю, что вы предлагаете подписать документ сторонней утилитой и затем отправить на сервер?
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 28.04.2008(UTC) Сообщений: 11
|
любопытно, что аналогичный скрипт на javascript (клиент и сервер, в данном случае - одна физическая машина) - прекрасно работает. и к томуже намного(!) быстрее - доли секунды. на perl занимает несколько десятков секунд. вот пример javascript: Код:
<object id="oCAPICOM"
codeBase="http://download.microsoft.com/download/E/1/8/E18ED994-8005-4377-A7D7-0A8E13025B94/capicom.cab#version=2,0,0,3"
classid="clsid:A996E48C-D3DC-4244-89F7-AFA33EC60679"
VIEWASTEXT>
</object>
<script>
var CAPICOM_STORE_OPEN_READ_ONLY = 0;
var CAPICOM_CURRENT_USER_STORE = 2;
var CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME = 0;
var CAPICOM_CERT_INFO_SUBJECT_SIMPLE_NAME = 0;
var CAPICOM_CERT_INFO_ISSUER_SIMPLE_NAME = 1;
var CAPICOM_VERIFY_SIGNATURE_ONLY = 0;
var Now = new Date();
var CertStore = new ActiveXObject("CAPICOM.Store");
var Signer = new ActiveXObject("CAPICOM.Signer");
var SignedAuth = new ActiveXObject("CAPICOM.SignedData");
CertStore.Open(CAPICOM_CURRENT_USER_STORE, "MY", CAPICOM_STORE_OPEN_READ_ONLY);
Signer.Certificate = CertStore.Certificates.Item(1); // 1-ый из личного хранилища сертификатов, поскольку мы работаем на стороне клиента
SignedAuth.Content = "бла бла бла"; // текст документа, который будем подписывать
document.write("text:\r\n" + SignedAuth.Content + "\r\n\r\n");
document.write("signing... ");
try {
var Signature = SignedAuth.Sign(Signer, true); // подписываем, получаем подпись Signature на основе документа и сертификата
} catch (e) {
document.write("failed: " + e.message + "\r\n\r\n"); // ошибка
}
document.write("done\r\n\r\n");
document.write("signature:\r\n" + Signature + "\r\n");
document.write("-------------------------------------------------------------------\r\n\r\n");
// Проверка подписи...
var SData = new ActiveXObject("CAPICOM.SignedData");
SData.Content = "бла бла бла"; // текст проверяемого документа
document.write("text:\r\n" + SData.Content + "\r\n\r\n");
document.write("signature:\r\n" + Signature + "\r\n");
document.write("verifying... ");
try {
SData.Verify(Signature, true, CAPICOM_VERIFY_SIGNATURE_ONLY);
document.write("done\r\n\r\n");
var Certificate=SData.Certificates(1);
var CertOwner=Certificate.GetInfo(CAPICOM_CERT_INFO_SUBJECT_SIMPLE_NAME);
document.write("signer: " + CertOwner);
} catch (e) {
document.write("failed: " + e.message + "\r\n\r\n"); // либо подпись либо документ липовые
}
</script>
Отредактировано пользователем 29 апреля 2008 г. 22:25:09(UTC)
| Причина: Не указана
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 28.04.2008(UTC) Сообщений: 11
|
добавлю, что пример определения валидности сертификата, который дается на http://www.cryptopro.ru/...ro/forum/view.asp?q=1105Certificate.IsValid().CheckFlag Certificate.IsValid().Result Chain.Build(Certificate) возвращают статус CAPICOM_TRUST_REVOCATION_STATUS_UNKNOWN означает ли это, что сертификат неверно сгенерирован или еще что нить в этом роде? как в таком случае, генерация подписи и ее последующая проверка с помошью javascript (выше) нормально отрабатывает?
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 25.12.2007(UTC) Сообщений: 1,733  Откуда: КРИПТО-ПРО Поблагодарили: 177 раз в 168 постах
|
poltora написал: правильно я понимаю, что вы предлагаете подписать документ сторонней утилитой и затем отправить на сервер?
нет, я предлагаю в качестве 2го параметра в вызове SignedData.Sign передать false. poltora написал:возвращают статус CAPICOM_TRUST_REVOCATION_STATUS_UNKNOWN означает ли это, что сертификат неверно сгенерирован или еще что нить в этом роде? как в таком случае, генерация подписи и ее последующая проверка с помошью javascript (выше) нормально отрабатывает? нет, это означает что сертификат не удалось проверить на отзыв. |
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 28.04.2008(UTC) Сообщений: 11
|
связана ли эта ошибка с невалидностью подписи? как указать не проверять сертификат на отзыв и поможет ли это решению проблемы(проверка валидности подписи)?
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 25.12.2007(UTC) Сообщений: 1,733  Откуда: КРИПТО-ПРО Поблагодарили: 177 раз в 168 постах
|
а в Вашем коде сертификат на отзыв и не проверяется - вы же передаете CAPICOM_VERIFY_SIGNATURE_ONLY |
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 28.04.2008(UTC) Сообщений: 11
|
Kirill Sobolev написал:а в Вашем коде сертификат на отзыв и не проверяется - вы же передаете CAPICOM_VERIFY_SIGNATURE_ONLY получается, что я указываю не проверять на отзыв сертификат и получаю ошибку - "сертификат не удалось проверить на отзыв" ??? а как просто проверить на валидность сертификат? вот пример кода - достаем сертификат из хранилища, и тут же проверяем его по рецепту http://www.cryptopro.ru/...ro/forum/view.asp?q=1105в результате - срабатывание на CAPICOM_TRUST_REVOCATION_STATUS_UNKNOWN Код:
# идентификатор юзера, по которому находим сертификат
my $user = '18b729e9d7485c1b12964e2ef3fba8a8';
my $Store = Win32::OLE->new('CAPICOM.Store') or die "Cannot start CAPICOM.Store";
$Store->Open( CAPICOM_CURRENT_USER_STORE, "My", CAPICOM_STORE_OPEN_READ_ONLY );
my $Certificates = $Store->Certificates;
my $Certificate;
for ( my $i = 1 ; $i <= $Certificates->Count() ; $i++ ) {
my $Cert = $Certificates->Item($i);
if ( _CertificateSubjectName2SSL_CLIENT_S_DN( $Cert->SubjectName() ) eq $user ) {
$Certificate = $Cert;
last;
}
}
# нашли, выводим имя и наличие приватного ключа - угу, он самый
print $Certificate->SubjectName() . ' ' . $Certificate->HasPrivateKey();
# проверяем на валидность
my $CertificateStatus = $Certificate->IsValid();
$CertificateStatus->CheckFlag(
CAPICOM_CHECK_TRUSTED_ROOT
or CAPICOM_CHECK_TIME_VALIDITY
or CAPICOM_CHECK_SIGNATURE_VALIDITY
or CAPICOM_CHECK_ONLINE_REVOCATION_STATUS
);
if ( $CertificateStatus->Result() ) {
print "CryptoAPI believes to be trustworthy.";
}
else {
my $Chain = Win32::OLE->new("CAPICOM.Chain") or die "Cannot start CAPICOM.Store";
$Chain->Build($Certificate);
#...пропущено...
# срабатывает на этот код
if ( CAPICOM_TRUST_REVOCATION_STATUS_UNKNOWN & $Chain->Status() ) {
print
"CryptoAPI was unable to determine the certificate status for ’"
. $Certificate->GetInfo(CAPICOM_INFO_SUBJECT_SIMPLE_NAME)
. "’";
}
}
или у меня неверный сертификат. или я проверяю неверно. подскажите, где ошибка. видимо из-за этой проблемы при проверке (в первом примере) на валидность подписи я получаю ошибку, хотя эта подпись сгенерирована тут же... Отредактировано пользователем 29 апреля 2008 г. 22:19:43(UTC)
| Причина: Не указана
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 25.12.2007(UTC) Сообщений: 1,733  Откуда: КРИПТО-ПРО Поблагодарили: 177 раз в 168 постах
|
"poltora" написал:получается, что я указываю не проверять на отзыв сертификат и получаю ошибку - "сертификат не удалось проверить на отзыв" ??? а с чего Вы взяли что в 1м примере у вас ошибка проверки на отзыв? "poltora" написал:а как просто проверить на валидность сертификат? ну Вы же сами указываете правильный способ "poltora" написал:или у меня неверный сертификат. или я проверяю неверно. я думаю у вас просто нет локально установленного CRL |
|
|
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close