12.07.2006 13:26:50Исходники к вопросу Ответов: 12
Andrey
Вот исходники к моему последнему вопросу,
создание подписи, ф-ия класса.

int CSignature::CreateSignature()
{
if (!m_pSignedData || ! m_pSignedData[0])
return CL_NOT_INITIALIZED;

// Для создания подписи используем ф-ию CryptSignMessage(..)
// а не CryptSignHash(..) и остальные низкоуровневые...
// ибо нам нужна подпись в формате PKSC#7 формате

CString sLastError ="success";
int iLastError =CL_SUCCESS;

// Переменные для указателя на данные и их длины
BYTE *pbSignedBuffer = NULL;
DWORD dwSignedDataLen = 0;

// Переменные для указателя на результат подписи и её длины
BYTE * pbBinSignatureValue =NULL;
DWORD dwBinSignatureValueLen =0;

// Переменные для парметров ф-ии ryptSignMessage
DWORD MessageSizeArray[1];
const BYTE *MessageArray[1];

// Сертификат (PCCERT_CONTEXT)
PCCERT_CONTEXT pCert = NULL;

// Используем из файла для инициализации контекста
pCert =m_pCertificate->GetCertContext(); // Получаем сертификат

// идентификатор алгоритма хеширования (для госта 94 и 2001 используется оди и тот же)
char OID[64] =szOID_CP_GOST_R3411;
m_pSignedData ="test_test_test";
pbSignedBuffer = (BYTE*)m_pSignedData;
dwSignedDataLen = (DWORD)(strlen(m_pSignedData)+1);

// Создаем и заполняем структуру для создания ц.п.
CRYPT_SIGN_MESSAGE_PARA SignParams;

// Обязательно нужно обнулить все поля структуры.
// Иначе это может привести к access violation в функциях CryptoAPI
// В примере из MSDN это отсутствует

memset(&SignParams, 0, sizeof(CRYPT_SIGN_MESSAGE_PARA));
SignParams.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
SignParams.dwMsgEncodingType = ENCODING_TYPE; //(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
SignParams.pSigningCert = pCert;
SignParams.HashAlgorithm.pszObjId = OID;

SignParams.HashAlgorithm.Parameters.cbData = 0;
SignParams.HashAlgorithm.Parameters.pbData = NULL;
SignParams.pvHashAuxInfo = NULL; // не используется
SignParams.cMsgCert = 0; // не включаем сертификат отправителя
SignParams.rgpMsgCert = NULL;
SignParams.cAuthAttr = 0;
SignParams.dwInnerContentType = 0;
SignParams.cMsgCrl = 0;
SignParams.rgAuthAttr = 0;

MessageArray[0] = pbSignedBuffer;
MessageSizeArray[0] =dwSignedDataLen;

// Получаем длину буфера подписи

if(!CryptSignMessage(
&SignParams, // указатель на SigParams
TRUE, // подпись создается отдельно
1, // число сообщений
MessageArray, // сообщение
MessageSizeArray, // длина сообщения
NULL, // буфер для подписи
&dwBinSignatureValueLen)) // размер буфера
{
sLastError.Format("Error %x during CryptBinaryToString.", ::GetLastError());
iLastError = CL_CRYPTOAPI_ERROR;
return iLastError;
}

// выделяем память под подпись
pbBinSignatureValue = new BYTE[dwBinSignatureValueLen];

// формируем подпись
if(!CryptSignMessage(
&SignParams, // указатель на SigParams
TRUE, // подпись создается отдельно
1, // число сообщений
MessageArray, // сообщение
MessageSizeArray, // длина сообщения
pbBinSignatureValue, // буфер для подписи
&dwBinSignatureValueLen)) // размер буфера
{
sLastError.Format("Error %x during CryptBinaryToString.", ::GetLastError());
iLastError = CL_CRYPTOAPI_ERROR;
return iLastError;
}

char * pBASE64SignatureValue =NULL;
DWORD dwBASE64SignatureValueLen =0;

//Переводим в BASE64
if(!CryptBinaryToString(pbBinSignatureValue, dwBinSignatureValueLen,
CRYPT_STRING_BASE64, NULL, & dwBASE64SignatureValueLen))
{
sLastError.Format("Error %x during CryptBinaryToString.", ::GetLastError());
iLastError = CL_CRYPTOAPI_ERROR;
return iLastError;
}
pBASE64SignatureValue =new char [(int)dwBASE64SignatureValueLen+1];

if(!CryptBinaryToString(pbBinSignatureValue,
dwBinSignatureValueLen, CRYPT_STRING_BASE64, pBASE64SignatureValue, & dwBASE64SignatureValueLen))
{
sLastError.Format("Error %x during CryptBinaryToString.", ::GetLastError());
iLastError = CL_CRYPTOAPI_ERROR;
return iLastError;
}

pBASE64SignatureValue[dwBASE64SignatureValueLen]=0;

//присваиваем адрес значения подписи в BASE64 формате переменной класса
m_pSignedValue= pBASE64SignatureValue;
return iLastError;
}
 
Ответы:
12.07.2006 14:03:24Kirill Sobolev
А есть сертификат и результат работы?
12.07.2006 14:12:56Andrey
Да есть
вот полученная полпись:
MIIBBwYJKoZIhvcNAQcCoIH5MIH2AgEBMQwwCgYGKoUDAgIJBQAwCwYJKoZIhvcN
AQcBMYHVMIHSAgEBMHMwZTEgMB4GCSqGSIb3DQEJARYRaW5mb0BjcnlwdG9wcm8u
cnUxCzAJBgNVBAYTAlJVMRMwEQYDVQQKEwpDUllQVE8tUFJPMR8wHQYDVQQDExZU
ZXN0IENlbnRlciBDUllQVE8tUFJPAgpuNK3NAAEAABDHMAoGBiqFAwICCQUAMAoG
BiqFAwICEwUABEAT0dLHVOkpGrAV8/3b9FcNdk10BH8k44BoTKuSQLW/+hlHHfgi
Wi8vMY4ROhWBxq0/5bG17af9ZwYKpoic1GnK

Вот сертификат:
MIIDkjCCAz+gAwIBAgIKbjStzQABAAAQxzAKBgYqhQMCAgMFADBlMSAwHgYJKoZI
hvcNAQkBFhFpbmZvQGNyeXB0b3Byby5ydTELMAkGA1UEBhMCUlUxEzARBgNVBAoT
CkNSWVBUTy1QUk8xHzAdBgNVBAMTFlRlc3QgQ2VudGVyIENSWVBUTy1QUk8wHhcN
MDYwNzA3MTMwNzAxWhcNMDcwNzA3MTMxNzAxWjCBqzELMAkGA1UEBhMCUlUxJjAk
BgNVBAcMHdCh0LDQvdC60YIt0J/QtdGC0LXRgNCx0YPRgNCzMRMwEQYDVQQKEwpz
aWdtYS1zb2Z0MSgwJgYDVQQLDB/QntGC0LTQtdC7INGA0LDQt9GA0LDQsdC+0YLQ
utC4MQ8wDQYDVQQDEwZBbmRyZXkxJDAiBgkqhkiG9w0BCQEWFXBhbkBzaWdtYS1z
b2Z0LnNwYi5ydTBjMBwGBiqFAwICEzASBgcqhQMCAiQABgcqhQMCAh4BA0MABEA/
lU04KDrGpg4XiRn9NQubdJp2JKyfGOP0u2eTt6qMCv1K6fSBRmBZiO7sWmUEdDS7
Zd/Wf39qDjjQudPsbN7Mo4IBhDCCAYAwDgYDVR0PAQH/BAQDAgTwMBkGCSqGSIb3
DQEJDwQMMAowCAYGKoUDAgIVMB0GA1UdDgQWBBTAVxM58CF18a/g/LyRsxfcraBx
+jATBgNVHSUEDDAKBggrBgEFBQcDAjAfBgNVHSMEGDAWgBRIVTAYyzwiqRfXYmJk
BaekzIaKETBSBgNVHR8ESzBJMEegRaBDhkFodHRwOi8vd3d3LmNyeXB0b3Byby5y
dS9jZXJ0ZW5yb2xsL1Rlc3QlMjBDZW50ZXIlMjBDUllQVE8tUFJPLmNybDCBqQYI
KwYBBQUHAQEEgZwwgZkwZAYIKwYBBQUHMAKGWGh0dHA6Ly93d3cuY3J5cHRvcHJv
LnJ1L0NlcnRFbnJvbGwvQ3J5cHRvLmNyeXB0b3Byby5ydV9UZXN0JTIwQ2VudGVy
JTIwQ1JZUFRPLVBSTygxKS5jcnQwMQYIKwYBBQUHMAGGJWh0dHA6Ly93d3cuY3J5
cHRvcHJvLnJ1L29jc3Avb2NzcC5zcmYwCgYGKoUDAgIDBQADQQC3m2wUqK0aiXyK
f0kjGrfB3Zq4EUc3rQ7x4yytxl0gjn4rPri4RDGSCG8S3KkeVYajdNe/lQo945Kt
mOs6PJMz

Вот строку, что подписываем,
хотя это в исходниках есть:
test_test_test

ил Ваи надо все архивом на мыло скинуть???
12.07.2006 15:23:59Andrey
вот шаблон при создании и проверке csptest-ом
csptest.exe -sfsign -in input.txt -out output.txt -my "test" -sign -detached -base64
csptest.exe -sfsign -in input.txt -my "test" -detached -verify -signature output.txt -base64

опять же могу прислать сертификат, полученную подпись,
и подписываемое сообщение в файлах
на ваше мыло, исходники Вы видели,
ума не приложу в чем может быть проблема....
12.07.2006 15:26:42Andrey
Как вообще может быть чтобы я сам что подписываю,
удачно проверяю
а csptest на том же сертификате, подписью
и подписываемом сообщении говорит что подпись неверная????
12.07.2006 15:29:37Kirill Sobolev
Не, на форуме нормально...
У меня проверяет все, csptest выдает
CSP (Type:71) v3.0.3293 KC1 Release OS:Windows CPU:IA32 FastCode:READY,ENABLED.
CSP (Type:75) v3.0.3293 KC1 Release OS:Windows CPU:IA32 FastCode:READY,ENABLED.
#0: pan@sigma-soft.spb.ru, Andrey, ╬Єфхы ЁрчЁрсюЄъш, sigma-soft, ╤рэъЄ-╧хЄхЁсєЁу
, RU
Valid from 07.07.2006 to 07.07.2007

#0: pan@sigma-soft.spb.ru, Andrey, ╬Єфхы ЁрчЁрсюЄъш, sigma-soft, ╤рэъЄ-╧хЄхЁсєЁу
, RU
Valid from 07.07.2006 to 07.07.2007

Detached Signature was verified OK
Total: SYS: 0.141 sec USR: 0.094 sec UTC: 0.250 sec
[ErrorCode: 0x00000000]

Вы код подписи привели, он правильный... А код записи исходного сообщения в файл нет. Вы же когда подписываете специально к подписываемой строке 0 в конце добавляете (не знаю зачем), а в файле который csptestу подсовываете он есть?
Сертификаты тут не при чем.
12.07.2006 15:54:38Andrey
Огромное спасибо что не поленились проверить,
ток я не понял,
подписываемая строка,
которую Вам прислал -правильная?
"test_test_test"
я к ней ноль вроде нигде не добавляю,
ноль я добавляю к значению подписи в формате base64.
ф-ия CryptBinaryToString возвращает длину
значения подписи в формате base64 без
завершающего нуля т.е. как strlen(),
я добавляю на всяк. случай,
а Вы что имели ввиду, напишите пожалуйста???
12.07.2006 16:10:18Kirill Sobolev
Правильная, если 0 добавить.
А Вы его добавляете здесь:
m_pSignedData ="test_test_test";
pbSignedBuffer = (BYTE*)m_pSignedData;
dwSignedDataLen = (DWORD)(strlen(m_pSignedData)+1);
с base64 все нормально
12.07.2006 16:25:59Andrey
А вот Вы о чем
так формально нол я не добавляю,
он уже есть в строке
m_pSignedData ="test_test_test",
а длину передаю с учетом этого нуля т.е. strlen()+1
а что в этом неправильного??
я ж не знаю исходники api ф-ий,
длина-то ведь им нужна,
вероятно чтоб под ней выделить память..
а если длину без ноля передам, дальше она будет обрабатываться, как будто у неё завершающего нуля и нет
и выделяться будет так что для заверш. нуля места не останется,
или я в чем-то не прав???

а в файл строку я записал для csptesta простым
копированием через буфер обмена
руками,
контрл инс, контрл шифт :))
так что наверное ведь при чтении файла csptest
завершающий нуль не обнаружил,
так???
т.е мне нужно например fprintf строку в файл запихнуть
для проверки??
12.07.2006 16:47:41Kirill Sobolev
Неправильно то, что Вы в файл записываете совсем не то что подписываете. Или записывайте не строку, а pbSignedBuffer (который Вы подписываете) с помощью fwrite, или подписывайте то что в файле лежит - т.е. вместо dwSignedDataLen = (DWORD)(strlen(m_pSignedData)+1) просто dwSignedDataLen = (DWORD)(strlen (m_pSignedData)).
Длина функциям нужна чтобы знать что подписывать, иначе как передать бинарный буфер? Им абсолютно наплевать, строка это или вообще одни нули - сколько надо будет памяти в итоге, столько и выделят.
12.07.2006 16:53:33Andrey
Спасибо большое, ОК
у меня вроде последний вопрос,
как Вы проверили csptest-ом,
ведь сертификат я посылал Вам в файле,
а csptest хочет чтоб сертификат был в хранилище my,MY,
???, установили сертификат в это хранилище как-то??
12.07.2006 17:10:35Andrey
ксати, если делаю
dwSignedDataLen = (DWORD)(strlen (m_pSignedData))
вместо
dwSignedDataLen = (DWORD)(strlen(m_pSignedData)+1)
то все равно не работает,
лучше использую для проверки fwrite,
Вы также делали?
12.07.2006 17:34:06Kirill Sobolev
Установил путем тыкания в кнопку "Установить сертификат" в окне просмотра.
Если не работает, где-то еще ошибка значит...
Я взял Ваш текст, подпись и сертификат, подсунул это все csptestу - не проверилось.
Добавил к тексту 0 в конце - все стало нормально.
Рекомендую попробовать не с detached подписью - если все будет нормально, то значит проблема в чтении/записи исходного текста.