Ключевое слово в защите информации
ключевое слово
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход. Новые регистрации запрещены.

Уведомление

Icon
Error

2 Страницы12>
Опции
К последнему сообщению К первому непрочитанному
Offline Андрей_  
#1 Оставлено : 1 июня 2009 г. 15:45:54(UTC)
Андрей_

Статус: Активный участник

Группы: Участники
Зарегистрирован: 07.05.2009(UTC)
Сообщений: 41

Добрый день!

Прошу Вашего совета в вопросе использования CRYPTO API из среды C#. Применение Шарпея невозможно по причине необходимости использования кода проекта в среде mono Linux. Причем проблемы возникают только с отдельными функциями. Такими как:
1.CryptMsgOpenToEncode (работает через раз, то ошибка - Access Violation с00005, то чисто)
2. и последующий вызов CryptMsgUpdate постоянно
Привожу фрагмент:

CMSG_SIGNER_ENCODE_INFO SingerEncodeInfo = new CMSG_SIGNER_ENCODE_INFO();
SingerEncodeInfo.pCertInfo = CertContext.pCertInfo;
SingerEncodeInfo.hCryptProv = hCryptProv;
SingerEncodeInfo.dwKeySpec = AT_KEYEXCHANGE;
SingerEncodeInfo.HashAlgorithm = HashAlgoritm;
SingerEncodeInfo.pvHashAuxInfo = IntPtr.Zero;
SingerEncodeInfo.cbSize = Convert.ToUInt32(System.Runtime.InteropServices.Marshal.SizeOf(SingerEncodeInfo));


CMSG_SIGNER_ENCODE_INFO[] SingerEncodeInfoArray = new CMSG_SIGNER_ENCODE_INFO[1];
SingerEncodeInfoArray[0] = SingerEncodeInfo;



CERT_BLOB SingerSertBlob = new CERT_BLOB();
SingerSertBlob.cbData = CertContext.cbCertEncoded;
SingerSertBlob.pbData = CertContext.pbCertEncoded;



CERT_BLOB[] SingerSertBlobArray = new CERT_BLOB[1];
SingerSertBlobArray[0] = SingerSertBlob;



CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo = new CMSG_SIGNED_ENCODE_INFO();
SignedMsgEncodeInfo.cbSize = Convert.ToUInt32(System.Runtime.InteropServices.Marshal.SizeOf(SignedMsgEncodeInfo));
SignedMsgEncodeInfo.cSigners = 1;



SignedMsgEncodeInfo.rgSigners = Marshal.AllocHGlobal(sizeof(ulong));


Marshal.StructureToPtr(SingerEncodeInfoArray[0], SignedMsgEncodeInfo.rgSigners, true);


SignedMsgEncodeInfo.cCertEncoded = 0;
SignedMsgEncodeInfo.rgCertEncoded = IntPtr.Zero;
SignedMsgEncodeInfo.rgCrlEncoded = IntPtr.Zero;

uint flags=0;



rgSigners = Marshal.AllocHGlobal(sizeof(long));
Marshal.StructureToPtr(SignedMsgEncodeInfo, rgSigners, false);

uint cbEncodedBlob=CryptMsgCalculateEncodedLength(TYPE_DER, flags, CMSG_SIGNED, rgSigners, "", cbContent);
Console.WriteLine("Длина ЭЦП рассчитана- {0}", cbEncodedBlob);


byte[] pbEncodedBlob = new byte[cbEncodedBlob];



Console.WriteLine("Hmsg do-" + Win32Error.ErrorMessage(Marshal.GetLastWin32Error()));




hMsg = Marshal.AllocHGlobal(sizeof(ulong));
hMsg = CryptMsgOpenToEncode(TYPE_DER,0, CMSG_SIGNED, rgSigners, null, IntPtr.Zero);



Console.WriteLine("Результат CryptMsgOpenToEncode-" + Win32Error.ErrorMessage(Marshal.GetLastWin32Error()));
Console.WriteLine("hMsg-" + hMsg);



cbEncodedBlob = 0;

;
// Получаем длину буфера подписи
pbContentArray = new byte[pbContent.Length];

for (int kk = 0; kk <= pbContent.Length - 1; kk++)
pbContentArray[kk] = (byte)(pbContent[kk]);


unsafe
{
fixed (byte* ptrContentArray = &pbContentArray[0])
{

if //(CryptMsgUpdate(hMsg, pbContentArray, pbContentArray.Length, true))
(CryptMsgUpdate(hMsg, ptrContentArray, 4, true))
{
Console.WriteLine("MsgUpdate-TRUE");
}
else
{
int ik = Marshal.GetLastWin32Error();
//uint error_msg=Convert.ToUInt32( ik);
Console.WriteLine(" CryptMsgUpdate-FALSE- {0}" + Win32Error.ErrorMessage(Convert.ToInt32(ik)), ik);
uint ii = (uint)ik;
switch (ii)
{
case CRYPT_E_INVALID_MSG_TYPE: Console.WriteLine("The message type is not valid."); break;
case CRYPT_E_MSG_ERROR: Console.WriteLine("An error was encountered doing a cryptographic operation."); break;
case CRYPT_E_OID_FORMAT: Console.WriteLine("The object identifier is badly formatted."); break;
case CRYPT_E_UNEXPECTED_ENCODING: Console.WriteLine(" The message is not encoded as expected."); break;
case CRYPT_E_UNKNOWN_ALGO: Console.WriteLine(" The cryptographic algorithm is unknown."); break;
case E_INVALIDARG: Console.WriteLine(" One or more arguments are not valid."); break;
case E_OUTOFMEMORY: Console.WriteLine("Ran out of memory"); break;
case 0xC0000005: Console.WriteLine("Access violation error"); break;
//default: Console.WriteLine("MsgUpdate-FALSE- {0}" + Win32Error.ErrorMessage(Convert.ToInt32(error_msg)), error_msg);
}

}
}
}

uint cbEncodedBlob1 = 0;
if (CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, null, ref cbEncodedBlob1))
{
Console.WriteLine("MsgGetParam-True. cbEncodedBlob={0}", cbEncodedBlob1);
}
else Console.WriteLine("Error CryptMsgGetParam Len- {0}" + Win32Error.ErrorMessage(Marshal.GetLastWin32Error()), Marshal.GetLastWin32Error());

pbEncodedBlob = new byte[cbEncodedBlob];

if (CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, pbEncodedBlob, ref cbEncodedBlob))
{
Console.WriteLine("MsgGetParam-true");
}
else Console.WriteLine("Error CryptMsgGetParam- {0}" + Win32Error.ErrorMessage(Marshal.GetLastWin32Error()), Marshal.GetLastWin32Error());


Описание функций:
#if OS
[DllImport("crypt32.dll", SetLastError = true)]
#else
[DllImport("/opt/cprocsp/lib/ia32/libcapilite.so")]
#endif
unsafe public static extern bool CryptMsgUpdate(
IntPtr hCryptMsg,
byte *pbData,
int cbData,
bool fFinal
);

#if OS
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
#else
[DllImport("/opt/cprocsp/lib/ia32/libcapilite.so")]
#endif
public static extern IntPtr CryptMsgOpenToEncode(
uint dwMsgEncodingType,
uint dwFlags,
uint dwMsgType,
IntPtr pvMsgEncodeInfo,
[In, MarshalAs(UnmanagedType.LPWStr)]String pszInnerContentObjID,
IntPtr pStreamInfo

Возможно есть особенности. Пробывал различные варианты. В том числе со всеми найденными описаниями указанных функций.

С уважением, Андрей


Offline Седов Роман  
#2 Оставлено : 1 июня 2009 г. 16:28:34(UTC)
Седов Роман

Статус: Мегазвезда

Группы: Участники
Зарегистрирован: 27.12.2007(UTC)
Сообщений: 71
Мужчина

Поблагодарили: 1 раз в 1 постах
Проблема именно при выполнении на Windows?
Не могли бы вы опубликовать законченный пример для воспроизведения проблемы?
Потому что так, глазами сложно посмотреть. К тому же не видно описания структур.
Offline Андрей_  
#3 Оставлено : 1 июня 2009 г. 16:48:36(UTC)
Андрей_

Статус: Активный участник

Группы: Участники
Зарегистрирован: 07.05.2009(UTC)
Сообщений: 41

Сначала только Win 32. Я готов прислать весь проект. Ну к сожалению он в отладочном виде. Прошу уточнить почтовый ящик. Посылаю на support c темой для Седова Романа
Offline Седов Роман  
#4 Оставлено : 1 июня 2009 г. 17:38:54(UTC)
Седов Роман

Статус: Мегазвезда

Группы: Участники
Зарегистрирован: 27.12.2007(UTC)
Сообщений: 71
Мужчина

Поблагодарили: 1 раз в 1 постах
Получил, сегодня постараюсь посмотреть.
Offline Андрей_  
#5 Оставлено : 1 июня 2009 г. 17:45:40(UTC)
Андрей_

Статус: Активный участник

Группы: Участники
Зарегистрирован: 07.05.2009(UTC)
Сообщений: 41

Спасибо, в проекте проверяется не только возможность подписи в формате PCS#7, но и обычная подпись через хэш. По хэшу вроде все получается.
Offline Седов Роман  
#6 Оставлено : 1 июня 2009 г. 18:13:11(UTC)
Седов Роман

Статус: Мегазвезда

Группы: Участники
Зарегистрирован: 27.12.2007(UTC)
Сообщений: 71
Мужчина

Поблагодарили: 1 раз в 1 постах
Увидел первую проблему (возможно, остальные имеют ту же причину - посмотрите сами):
rgSigners = Marshal.AllocHGlobal( sizeof( ulong ) ); // Тут отводится память всего лишь под ulong
Marshal.StructureToPtr( CertInfo.SubjectPublicKeyInfo, rgSigners, true ); // А тут по этому адресу записывается гораздо больший блок данных.
Это - явный ляп, приводящий как раз к "Access Violation".
Правильнее память отводить так: rgSigners = Marshal.AllocHGlobal( Marshal.SizeOf( typeof(CERT_PUBLIC_KEY_INFO )) );
Ну, и в рабочей программе не забывать ее освобождать.
Offline Андрей_  
#7 Оставлено : 2 июня 2009 г. 20:01:30(UTC)
Андрей_

Статус: Активный участник

Группы: Участники
Зарегистрирован: 07.05.2009(UTC)
Сообщений: 41

Огромное спасибо. Дело сдвинулось. Но появились еще вопросы.
1. При определениии имени контейнера его длина получилась 64, хотя в реальности 36 символов. Зазор?
2. Длина имени криптопровайдера 60, а реальности 59
3. Открытый ключ подписи вероятно 512 битный (64-байт), хотя в сертификате длина меньше, экспортируется в 100-байтный массив.
4. При использовании обычной подписи (подпись хэша) длина подписи определяется как 64. При использовании высокоуроневой функции как 395 (31-байт сообщения), для низкоуровневой -454 для того же сообщения. Почему такая разница?
5. Очевидно в высокоуровневой подписи стандарта PCS#7 как элемент содержится простая подпись. Зрительно увидеть не удалось. Другая кодировка?
Offline Седов Роман  
#8 Оставлено : 1 июля 2009 г. 18:45:26(UTC)
Седов Роман

Статус: Мегазвезда

Группы: Участники
Зарегистрирован: 27.12.2007(UTC)
Сообщений: 71
Мужчина

Поблагодарили: 1 раз в 1 постах
Извините, почему-то мне не пришло уведомление об ответе в тему, сейчас случайно увидел...
1. Да, возможно там возвращается длина максимального имени контейнера. Это лучше посмотреть в описании PP_ENUM_CONTAINERS (вроде так пишется).
2. Возможно это просто с '\0' на конце - опять же, посмотрите в документации по этой CryptoAPI-функции.
3. Не очень понял. Что чего меньше и как смотрите длину в сертификате?
4. Какие именно функции используются?
5. Это про 4?
Offline Андрей_  
#9 Оставлено : 21 сентября 2009 г. 16:22:13(UTC)
Андрей_

Статус: Активный участник

Группы: Участники
Зарегистрирован: 07.05.2009(UTC)
Сообщений: 41

Добрый день, Роман!
Спасибо за предыдущий ответ. Лучше позже.

Мне необходимо создать вторую подпись на уже подписанном документе в режиме Detach=true. Для этого необходим вызов
hMsgStore = CryptoDefinition.CertOpenStore(
CryptoDefinition.CERT_STORE_PROV_MSG, // int 10
CyptoDefinition.PKCS_7_ASN_ENCODING | CryptoDefinition.X509_ASN_ENCODING,
0,
CryptoDefinition.CERT_STORE_READONLY_FLAG,
SpbSum);//строка, содержащая подписанный ранее документ и подпись - конкатенация массивов );
Выдает ошибку по памяти при вызове.
Ранее безуспешно пытался вызвать тоже самое без SpbSum c типом IntPtr hMsgAppend, полученного из сообщения внедрением структуры CMSG_SIGNER_ENCODE_INFO.
if (!CryptoDefinition.CryptMsgControl(
hMsgAppend,
0,
CryptoDefinition.CMSG_CTRL_ADD_SIGNER,
IseiSender))

Объявление следующее:
public static extern IntPtr CertOpenStore(
int storeProvider, int encodingType,
int hcryptProv, int flags, string pvPara);
Прошу уточнить возможен ли вызов этой функции C#. Может это вообще невозможно.


С уважением, Андрей
Offline Андрей_  
#10 Оставлено : 21 сентября 2009 г. 20:08:50(UTC)
Андрей_

Статус: Активный участник

Группы: Участники
Зарегистрирован: 07.05.2009(UTC)
Сообщений: 41

Добрый день! Частично задача решилась. Правильный вызов -
hMsgStore = CryptoDefinition.CertOpenStore(
new IntPtr(CryptoDefinition.CERT_STORE_PROV_MSG),
(int)CryptoDefinition.TYPE_DER,
0,
CryptoDefinition.CERT_STORE_READONLY_FLAG,
hMsgAppend );

Формулировка вопроса на Вашем сайте - это уже плюс. Позволяет посмотреть со стороны на себя
С уважением, Андрей
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
2 Страницы12>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.