08.11.2006 11:30:47capicom + perl Ответов: 7
Дмитрий
Использует ли кто либо связку capicom + perl?
Может кто наступал уже на эти грабли?
в perl использую следующую конструкцию

my $Signer = Win32::OLE->new('CAPICOM.Signer') or die "Oops, cannot start CAPICOM.Signer";
my $Store = Win32::OLE->new('CAPICOM.Store') or die "Oops, cannot start CAPICOM";
my $SignedData = Win32::OLE->new('CAPICOM.SignedData') or die "Oops, cannot start CAPICOM.SignedData";

# поиск сертификата для подписи я опускаю ибо работает без проблем
my $Content = 'Текст для подписи';

my $MyMail = MIME::Entity->build(
From => 'frommail@mymail.ru',
To => 'tomail@mymail.ru',
Subject => "Test crypto",
Type => 'multipart/signed; protocol="application/pkcs7-signature"',
);

$MyMail->attach(
Data => "$Content",
Type => "text/plain",
Encoding => "quoted-printable"
);

my $ContentToSign = $MyMail->parts(0)->stringify;
$SignedData->LetProperty('Content',$ContentToSign);
my $Message = $SignedData->Sign($Signer, 1,CAPICOM_ENCODE_BASE64);

$MyMail->attach(
Data => decode_base64($Message),
Type => 'application/pkcs7-signature',
Name => 'smime.p7s',
Disposition => 'attachment',
Filename => 'smime.p7s',
Description => 'S/MIME Cryptographic Signature',
Encoding => "base64"
);

my $smtp = Net::SMTP->new('mail.mymail.ru',Timeout => 30);
$smtp->mail('frommail@mymail.ru');
$smtp->recipient('tomail@mymail.ru');
$smtp->data;
$smtp->datasend($MyMail->stringify);
$smtp->dataend;
$smtp->close;

при получении письма неправильная подпись.
может кто подскажет, какие особенности параметра Content?
Что именно туда должно попасть?
в примерах для VB постоянно присутствует
oSignedData.Content = StrConv(strContent, vbFromUnicode)
но перл с юникодом и не работет.
 
Ответы:
08.11.2006 11:47:26Kirill Sobolev
Зато CAPICOM работает.
Свойство Content ожидает юникодную строку (BSTR).
Как осуществляет преобразование метод LetProperty - делает неявное преобразование ANSI-Unicode или копирует как последовательность байт?
В дельфи и некоторых классах С++ как раз имеет место быть
такое неявное преобразование например.
09.11.2006 11:29:49Дмитрий
Самое интересное, что средствами capicom эти сообщения распознаются, как подписанные не зависимо от конвертирования Content в BSTR, а почтовиками нет.

Что же он подписывает?
09.11.2006 13:43:25Kirill Sobolev
Сделайте присоединенную подпись и посмотрите
10.11.2006 14:20:53Дмитрий
Вы правы. Все так и было. Исходный текст был в юникоде. Преобразование помогло.
10.01.2007 23:17:38Андрей
а как преобразовать ?
первый раз пытаюсь что то сделать на perl спасибо
11.01.2007 9:38:41DimMan
Пример создания и отправки письма с двумя подписями на перл для Windows.

#!/usr/bin/perl -w
use strict;
use WIN32::OLE;
use Win32::OLE::Variant;
use warnings;
use NET::SMTP;
use MIME::Entity;
use MIME::Base64;
use Encode;




# CAPICOM constant definitions
use constant {
Unknown => 0,
Sign => 1,
Timestamp => 2,
Verify => 3,

CAPICOM_LOCAL_MACHINE_STORE => 1,
CAPICOM_CURRENT_USER_STORE => 2,
CAPICOM_ACTIVE_DIRECTORY_USER_STORE => 3,
CAPICOM_SMART_CARD_USER_STORE => 4,

CAPICOM_CERTIFICATE_FIND_SHA1_HASH => 0,
CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME => 1,
CAPICOM_CERTIFICATE_FIND_ISSUER_NAME => 2,
CAPICOM_CERTIFICATE_FIND_ROOT_NAME => 3,
CAPICOM_CERTIFICATE_FIND_TEMPLATE_NAME => 4,
CAPICOM_CERTIFICATE_FIND_EXTENSION => 5,
CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY => 6,
CAPICOM_CERTIFICATE_FIND_APPLICATION_POLICY => 7,
CAPICOM_CERTIFICATE_FIND_CERTIFICATE_POLICY => 8,
CAPICOM_CERTIFICATE_FIND_TIME_VALID => 9,
CAPICOM_CERTIFICATE_FIND_TIME_NOT_YET_VALID => 10,
CAPICOM_CERTIFICATE_FIND_TIME_EXPIRED => 11,

CAPICOM_CERTIFICATE_INCLUDE_CHAIN_EXCEPT_ROOT => 0,
CAPICOM_CERTIFICATE_INCLUDE_WHOLE_CHAIN => 1,
CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY => 2,

CAPICOM_VERIFY_SIGNATURE_ONLY => 0,
CAPICOM_VERIFY_SIGNATURE_AND_CERTIFICATE => 1,

CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME => 0,
CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_NAME => 1,
CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_DESCRIPTION => 2,

CAPICOM_PROPID_KEY_PROV_INFO => 2,

CAPICOM_LOCAL_MACHINE_STORE => 1,
CAPICOM_CURRENT_USER_STORE => 2,
CAPICOM_STORE_OPEN_READ_ONLY => 0,
CAPICOM_KEY_STORAGE_DEFAULT => 0,

CAPICOM_ENCODE_ANY => 0xffffffff,
CAPICOM_ENCODE_BASE64 => 0,
CAPICOM_ENCODE_BINARY => 1,
};


my $StoreLocation;
my $DocName = 'test.txt';

Win32::OLE->Option ('Warn' => 3);

my $Signer = Win32::OLE->new('CAPICOM.Signer') or die "Oops, cannot start CAPICOM.Signer";
my $Signer2 = Win32::OLE->new('CAPICOM.Signer') or die "Oops, cannot start CAPICOM.Signer";
my $Store = Win32::OLE->new('CAPICOM.Store') or die "Oops, cannot start CAPICOM";

my $StoreName = 'MY';

$Store->Open(CAPICOM_CURRENT_USER_STORE, $StoreName);
my $Certificates = $Store->Certificates;

if ($Certificates->Count > 0)
{
$Certificates = $Certificates->Find(CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, 'test3@test.ru');
}

SWITCHCERT:
{
if ($Certificates->Count == 0)
{
print "Error! Сертификат не найден!\n";
exit;
}
if ($Certificates->Count == 1)
{
$Signer->LetProperty('Certificate',$Certificates->Item(1));
last;
}
print "Error! Ошибка работы с сертификатом!\n";
exit;
}

$Certificates = $Store->Certificates;

if ($Certificates->Count > 0)
{
$Certificates = $Certificates->Find(CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, 'test1@test.ru');
}
SWITCHCERT2:
{
if ($Certificates->Count == 0)
{
print "Error! Сертификат не найден!\n";
exit;
}
if ($Certificates->Count == 1)
{
$Signer2->LetProperty('Certificate',$Certificates->Item(1));
last;
}
print "Error! Ошибка работы с сертификатом!\n";
exit;
}
undef $Certificates;
undef $Store;

my $SignedData = Win32::OLE->new('CAPICOM.SignedData') or die "Oops, cannot start CAPICOM.SignedData";

my $Content = '';

open FileToSign, $DocName;
while (<FileToSign>)
{
$Content .= $_;
}
close FileToSign;

my $MyMail = MIME::Entity->build( From => 'test1@test.ru',
To => 'test2@test.ru',
Subject => "Test crypto".time(),
Type => 'multipart/signed; protocol="application/pkcs7-signature"',
Protocol => '"application/pkcs7-signature"',
);

$MyMail->attach(
Data => $Content,
Type => "text/plain; charset=koi8-r",
Encoding => "quoted-printable"
);

my $ContentToSign = $MyMail->parts(0)->stringify;

$ContentToSign =~ s/\n/\r\n/g;

$SignedData->{'Content'} = Variant(VT_UI1, $ContentToSign);

my $Message = $SignedData->Sign($Signer, 1, CAPICOM_ENCODE_BASE64);

$SignedData->Verify($Message, 1, 1);

$Message = $SignedData->CoSign($Signer2,CAPICOM_ENCODE_BASE64);

$MyMail->attach(
Data => decode_base64($Message),
Type => 'application/pkcs7-signature',
Name => 'smime.p7s',
Disposition => 'attachment',
Filename => 'smime.p7s',
Description => 'S/MIME Cryptographic Signature',
Encoding => "base64"
);

my $smtp = Net::SMTP->new('mail.test.ru',Timeout => 30);
$smtp->mail('test1@test.ru');
$smtp->recipient('test2@test.ru');
$smtp->data;
$smtp->datasend($MyMail->stringify);
$smtp->dataend;
$smtp->close;
12.01.2007 0:30:21Dimas
а есть ли пример шифрования на perl