i25061 написал:
Так чем закончилось?
Проверил подпись СМЭВ через CryptoAPI c CSP.
Берём сообщение, сгенерированное примером
http://www.cryptopro.ru/...olzovaniem-kriptopro-jcp
MIME-Version: 1.0
Content-Type: application/octet-stream; name="soap_net.xml.signed.uri.xml"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="soap_net.xml.signed.uri.xml"
PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48UzpFbnZlbG9wZSB4bWxuczpT
PSJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy9zb2FwL2VudmVsb3BlLyIgeG1sbnM6ZHM9Imh0
dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiIHhtbG5zOndzc2U9Imh0dHA6Ly9kb2Nz
Lm9hc2lzLW9wZW4ub3JnL3dzcy8yMDA0LzAxL29hc2lzLTIwMDQwMS13c3Mtd3NzZWN1cml0eS1z
ZWNleHQtMS4wLnhzZCIgeG1sbnM6d3N1PSJodHRwOi8vZG9jcy5vYXNpcy1vcGVuLm9yZy93c3Mv
MjAwNC8wMS9vYXNpcy0yMDA0MDEtd3NzLXdzc2VjdXJpdHktdXRpbGl0eS0xLjAueHNkIj4NCjxT
OkhlYWRlcj4NCjx3c3NlOlNlY3VyaXR5IFM6YWN0b3I9Imh0dHA6Ly9zbWV2Lmdvc3VzbHVnaS5y
dS9hY3RvcnMvc21ldiIgeG1sbnM6d3NzZT0iaHR0cDovL2RvY3Mub2FzaXMtb3Blbi5vcmcvd3Nz
LzIwMDQvMDEvb2FzaXMtMjAwNDAxLXdzcy13c3NlY3VyaXR5LXNlY2V4dC0xLjAueHNkIj4NCjx3
c3NlOkJpbmFyeVNlY3VyaXR5VG9rZW4gRW5jb2RpbmdUeXBlPSJodHRwOi8vZG9jcy5vYXNpcy1v
cGVuLm9yZy93c3MvMjAwNC8wMS9vYXNpcy0yMDA0MDEtd3NzLXNvYXAtbWVzc2FnZS1zZWN1cml0
eS0xLjAjQmFzZTY0QmluYXJ5IiBWYWx1ZVR5cGU9Imh0dHA6Ly9kb2NzLm9hc2lzLW9wZW4ub3Jn
L3dzcy8yMDA0LzAxL29hc2lzLTIwMDQwMS13c3MteDUwOS10b2tlbi1wcm9maWxlLTEuMCNYNTA5
djMiIHdzdTpJZD0iU2VuZGVyQ2VydGlmaWNhdGUiPk1JSUJqekNDQVQ2Z0F3SUJBZ0lGQU51ZDA2
Z3dDQVlHS29VREFnSURNREV4Q3pBSkJnTlZCQVlUQWxKVk1SSXdFQVlEVlFRS0V3bEQNCmNubHdk
RzlRY204eERqQU1CZ05WQkFNVEJVRnNhV0Z6TUI0WERURXlNRGd4TlRFd05Ua3pNVm9YRFRFek1E
Z3hOVEV3TlRrek1Wb3cNCk1URUxNQWtHQTFVRUJoTUNVbFV4RWpBUUJnTlZCQW9UQ1VOeWVYQjBi
MUJ5YnpFT01Bd0dBMVVFQXhNRlFXeHBZWE13WXpBY0JnWXENCmhRTUNBaE13RWdZSEtvVURBZ0lr
QUFZSEtvVURBZ0llQVFOREFBUkErMGVWTnRJbnNFaDBpeXdUbTZKQ0hlUEc5dUR1ODd6RG1JZlgN
CkRWMktYUG9SMmdoMEY1b0U4MC9TNnlhRkZqeTRmM2FxK1E0dXJ3amIvUE5ldVZWZnhxTTdNRGt3
RGdZRFZSMFBBUUgvQkFRREFnUG8NCk1CTUdBMVVkSlFRTU1Bb0dDQ3NHQVFVRkJ3TUNNQklHQTFV
ZEV3RUIvd1FJTUFZQkFmOENBUVV3Q0FZR0tvVURBZ0lEQTBFQStqWGENCk04Y3F4alNFaHgxSkph
K3o5Snk1b2dDNW4yM1UxVFZ1YmRyc1YrWU91U2k4K0ZQc2FxQkc1SmVDOFdpeVc4dWsvRUtvaVJP
UXIrNVENCnNrNEVWQT09PC93c3NlOkJpbmFyeVNlY3VyaXR5VG9rZW4+DQo8U2lnbmF0dXJlIHht
bG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48U2lnbmVkSW5mbz48Q2Fu
b25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAv
eG1sLWV4Yy1jMTRuIyIvPjxTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3Lncz
Lm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNnb3N0cjM0MTAyMDAxLWdvc3RyMzQxMSIvPjxSZWZl
cmVuY2UgVVJJPSIjYm9keSI+PFRyYW5zZm9ybXM+PFRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6
Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvVHJhbnNmb3Jtcz48RGlnZXN0
TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxkc2lnLW1vcmUj
Z29zdHIzNDExIi8+PERpZ2VzdFZhbHVlPlQxYWtiWW5pekFqUk11dHFmb1p2M3Jhd3ZoS1A0ZkVC
TWhNK1lJWUl6OHc9PC9EaWdlc3RWYWx1ZT48L1JlZmVyZW5jZT48L1NpZ25lZEluZm8+PFNpZ25h
dHVyZVZhbHVlPmgrbWgxRTZpTUFzZGxpK0JGWFRaV082OVprWWJaQTRJV1E1U0lKSXBScTEwcVhh
ZkU1NUoxc2UzMVVINmtrS2M0N2poRGpnQlVnWEgNCmFhVUlaR09WbVE9PTwvU2lnbmF0dXJlVmFs
dWU+PEtleUluZm8+PHdzc2U6U2VjdXJpdHlUb2tlblJlZmVyZW5jZT48d3NzZTpSZWZlcmVuY2Ug
VVJJPSIjU2VuZGVyQ2VydGlmaWNhdGUiIFZhbHVlVHlwZT0iaHR0cDovL2RvY3Mub2FzaXMtb3Bl
bi5vcmcvd3NzLzIwMDQvMDEvb2FzaXMtMjAwNDAxLXdzcy14NTA5LXRva2VuLXByb2ZpbGUtMS4w
I1g1MDl2MyIvPjwvd3NzZTpTZWN1cml0eVRva2VuUmVmZXJlbmNlPjwvS2V5SW5mbz48L1NpZ25h
dHVyZT48L3dzc2U6U2VjdXJpdHk+DQo8L1M6SGVhZGVyPg0KPFM6Qm9keSB3c3U6SWQ9ImJvZHki
Pg0KPCEtLSDQl9C00LXRgdGMINC40LTRkdGCINGC0LXQu9C+INC30LDQv9GA0L7RgdCwLS0+DQo8
L1M6Qm9keT4NCjwvUzpFbnZlbG9wZT4=
Вытаскиваем оттуда 403 байта сертификата, 64 байта подписи.
Берём тег SignedInfo и строим каноническую форму. Это отдельная песня, не для этого поста. Рекомендую вставить уровень выдачи логов DEBUG для log4j в примере выше. Увидите эту форма в логах. Я оттуда взял :) В нашем случае она будет такая:
<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#"><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"></SignatureMethod><Reference URI="#body"><Transforms><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"></DigestMethod><DigestValue>T1akbYnizAjRMutqfoZv3rawvhKP4fEBMhM+YIYIz8w=</DigestValue></Reference></SignedInfo>
Ровно 575 байтов, ни больше и не меньше.
Для других примеров будет другая...
Пишем программу на Си.
Загружаем сертификат: CertCreateCertificateContext( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cert, 403 )
Создаём провайдер: CryptAcquireContext(&hCryptProv,NULL,_T("Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider"),75,CRYPT_VERIFYCONTEXT)
Получем открытый ключ сертификата:
CryptImportPublicKeyInfoEx( hCryptProv, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,&(cert->pCertInfo->SubjectPublicKeyInfo),CALG_GR3410EL,0,NULL,&publicKey )
Считаем хэш по канонической форме SignedInfo:
CryptCreateHash( hCryptProv,CALG_GR3411,0,0,&hHash)
CryptHashData( hHash, &data[0], 575, 0 )
А теперь фокус! Нужно изменить порядок байтов в подписи на противоположный. Не спрашивайте почему - не знаю. Интимная связь между CSP и JCP :)
for( int i=0; i < 64; i++ ) signature_reverse[64-i-1]=signature[i];
Ну, и, собственно, проверяем:
CryptVerifySignature( hHash, &signature_reverse[0], 64, publicKey, NULL, 0 )
О! Чудо! Возвращается true.
Расчёт и проверка хэша тега body оставляется читателю...
Надеюсь, кому-нибудь поможет.