Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Visual C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.10.2014, 20:45   #1
sinestro
Пользователь
 
Регистрация: 24.02.2012
Сообщений: 88
По умолчанию wincrypt не экспортируется ключ

накопал в интернете пример и пытаюсь зашифровать файл. при этом мне нужно экспортировать ключ в заголовок файла. делаю это так:
Код:
System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) //шифрование
			 {
				 HCRYPTPROV hProv;
				 HCRYPTKEY hKey, hPublicKey;
				 char* chartext = (char*) Marshal::StringToHGlobalAnsi(text ).ToPointer();
				 DWORD count=strlen(chartext);
				 // Получение контекста криптопровайдера
				 if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
				 {
					MessageBox::Show("CryptAcquireContext"); 
				 }
				 // Генерация сессионного ключа
				 if (!CryptGenKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hKey))
				 {
					 MessageBox::Show("CryptGenKey"); 
				 } 
				 // Шифрование данных
				 if (!CryptEncrypt(hKey, 0, true, 0, (BYTE*)chartext, &count, strlen(chartext)))
				 {
					 MessageBox::Show("CryptEncrypt"); 
				 }
				 // Получение ключа для экспорта ключа шифрования
				 if (!CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hPublicKey))
				 {
					 MessageBox::Show("CryptGetUserKey"); 
				 }
				 // Инициализация массива, используемого для экспорта ключа
				 BYTE* data = static_cast<BYTE*>(malloc(count));
                 ZeroMemory(data, count);
				 // Экспорт ключа шифрования 
				 if (!CryptExportKey(hKey, hPublicKey, SIMPLEBLOB, 0, data, &count)) 
				 {
					 MessageBox::Show("CryptExportKey");
					 MessageBox::Show(Convert::ToString(GetLastError()));
				 }
				 //запись данных в файл
				 String^ path = gcnew String((char*)data);
				 StreamWriter^ writer = gcnew StreamWriter(path);
				 writer->Write(chartext);
			 }
но почему-то функции CryptGetUserKey и CryptExportKey фозвращают false. если вызывать только CryptExportKey - тот же эффект. GetLastError при этом возвращает 0 . в чём может быть проблема?
sinestro вне форума Ответить с цитированием
Старый 27.10.2014, 14:19   #2
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,775
По умолчанию

Я уже советовал пример коллеге Stilet-у, могу посоветовать еще раз. Там вроде выгрузка в файл есть... Ой, это C#?
Vapaamies вне форума Ответить с цитированием
Старый 27.10.2014, 17:41   #3
sinestro
Пользователь
 
Регистрация: 24.02.2012
Сообщений: 88
По умолчанию

Цитата:
Сообщение от Vapaamies Посмотреть сообщение
Ой, это C#?
хуже. с++ winforms))
sinestro вне форума Ответить с цитированием
Старый 27.10.2014, 19:50   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
но почему-то функции CryptGetUserKey и CryptExportKey фозвращают fals
А текст ошибки какой?
Ты используй GetLastError() для получения кода ошибки хотя бы.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 27.10.2014, 20:50   #5
sinestro
Пользователь
 
Регистрация: 24.02.2012
Сообщений: 88
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Ты используй GetLastError() для получения кода ошибки хотя бы.
я использовал. просто убрал её из этого кода. она возвращала 0
sinestro вне форума Ответить с цитированием
Старый 27.10.2014, 20:53   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Как так? О_о
Не могло быть такого: http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
Цитата:
If the function fails, the return value is zero (FALSE). For extended error information, call GetLastError.
Кстати, я тут заметил эту строку:
Цитата:
DWORD count=strlen(chartext);
Не надо так выяснять длину.
Лучше вызови
Код:
CryptExportKey(hKey, hPublicKey, SIMPLEBLOB, 0, 0, &count)
И получишь в count нужно кол-во байт, а уже после этого можно писать
Код:
BYTE* data = static_cast<BYTE*>(malloc(count));
I'm learning to live...

Последний раз редактировалось Stilet; 27.10.2014 в 20:58.
Stilet вне форума Ответить с цитированием
Старый 27.10.2014, 21:47   #7
sinestro
Пользователь
 
Регистрация: 24.02.2012
Сообщений: 88
По умолчанию

попробовал так:
Код:
                                 HCRYPTPROV hProv;
				 HCRYPTKEY hKey, hPublicKey, hNewKey;
				 char* chartext = (char*) Marshal::StringToHGlobalAnsi(text ).ToPointer();
				 DWORD count = 0;
				 // Получение контекста криптопровайдера
				 if (!CryptAcquireContext(&hProv, "{EB57ED8A-CCCC-4bf5-8659-9DF2F05F24AD}",NULL, PROV_RSA_FULL, 0))
				 {
					MessageBox::Show("CryptAcquireContext"); 
					MessageBox::Show(Convert::ToString(GetLastError()));
				 }
				 // Генерация сессионного ключа
				 if (!CryptGenKey(hProv, CALG_RC4, CRYPT_EXPORTABLE | CRYPT_ENCRYPT | CRYPT_DECRYPT, &hKey))
				 {
					 MessageBox::Show("CryptGenKey"); 
					 MessageBox::Show(Convert::ToString(GetLastError()));
				 } 
				 // Шифрование данных 
				 if (!CryptEncrypt(hKey, 0, true, 0, (BYTE*)chartext, &count, strlen(chartext)))
				 {
					 MessageBox::Show("CryptEncrypt"); 
					 MessageBox::Show(Convert::ToString(GetLastError()));
				 }
				 // Получение ключа для экспорта ключа шифрования
				 if (!CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hPublicKey))
				 {
					 MessageBox::Show("CryptGetUserKey"); 
					 MessageBox::Show(Convert::ToString(GetLastError()));
				 } 
				 // Получение размера массива, используемого для экспорта ключа
				 if (!CryptExportKey(hKey, hPublicKey, SIMPLEBLOB, 0, NULL, &count)) 
				 {
					 MessageBox::Show("CryptExportKey");
					 MessageBox::Show(Convert::ToString(GetLastError()));
				 }
				 // Инициализация массива, используемого для экспорта ключа
				 BYTE* data = static_cast<BYTE*>(malloc(count)); 
			     ZeroMemory(data, count);
				 // Экспорт ключа шифрования
				 if (!CryptExportKey(hKey, hPublicKey, SIMPLEBLOB, 0, data, &count)) 
				 {
					 MessageBox::Show("CryptExportKey");
					 MessageBox::Show(Convert::ToString(GetLastError()));
				 }
				 //запись данных в файл
				 String^ path = gcnew String((char*)data);
				 StreamWriter^ writer = gcnew StreamWriter(path);
				 writer->Write(chartext);
после таких преобразований не срабатывает даже CryptAcquireContext. а GetLastError() везде возвращает 0.
вот такие танцы с бубном вверху не влияют никак на данную проблему ? :
Код:
[DllImport("advapi32", CharSet=CharSet::Auto)]
	extern "C" BOOL CryptEncrypt(HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE* pbData, DWORD* pdwDataLen, DWORD dwBufLen);
	[DllImport("advapi32", CharSet=CharSet::Auto)]
	extern "C" WINADVAPI BOOL WINAPI CryptGenKey( HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY * phKey );
	[DllImport("advapi32", CharSet=CharSet::Auto)]
	extern "C" BOOL WINAPI CryptAcquireContext( HCRYPTPROV *phProv, LPCTSTR pszContainer, LPCTSTR pszProvider, DWORD dwProvType, DWORD dwFlags);
	[DllImport("advapi32", CharSet=CharSet::Auto)]
	extern "C" BOOL CryptExportKey(HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType, DWORD dwFlags, BYTE* pdData, DWORD* pdwDataLen);
	[DllImport("advapi32", CharSet=CharSet::Auto)]
	extern "C" BOOL WINAPI CryptGetUserKey( HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey);
sinestro вне форума Ответить с цитированием
Старый 27.10.2014, 22:09   #8
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
{EB57ED8A-CCCC-4bf5-8659-9DF2F05F24AD}
Это такой контейнер у тебя есть? О_о
Ну да ладно, меня больше всего смущает, что GetLastError() везде возвращает 0
Значит ошибок нет.
Тогда вопрос поставлю по другому: Отладку делал? Что попадает в hProv?

Кстати уже на первом if() нужно делать return ибо без активации провайдера дальнейшие вызовы фунок приведут к крэшу.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 27.10.2014, 22:36   #9
sinestro
Пользователь
 
Регистрация: 24.02.2012
Сообщений: 88
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Это такой контейнер у тебя есть?
это я из примера скопипастил.
Цитата:
Сообщение от Stilet Посмотреть сообщение
:Что попадает в hProv?
доходит до строки
HCRYPTPROV hProv;
и там пишет значение 15777208552
но как только прохожу строку
if (!CryptAcquireContext(&hProv, "{EB57ED8A-CCCC-4bf5-8659-9DF2F05F24AD}",NULL, PROV_RSA_FULL, 0))
в этой переменной оказывается 0

а вот уже из другого примера
CryptAcquireContext(&hProv,"test",0 ,PROV_RSA_FULL,CRYPT_NEWKEYSET);
if(CryptAcquireContext(&hProv,"test ",0,PROV_RSA_FULL,0))
{
...
так срабатывает, но в нём тоже проблема с CryptGetUserKey.

а вот так работает, и по прежнему проблемы с CryptGetUserKey. а GetLastError срабатывает нормально получается. мистика...
Код:
if (!CryptAcquireContext(&hProv, "test",NULL, PROV_RSA_FULL, 0))
				 {
					MessageBox::Show("CryptAcquireContext фейл"); 
					MessageBox::Show(Convert::ToString(GetLastError()));
					if (GetLastError() == NTE_BAD_KEYSET) 
					{
						if(CryptAcquireContext(&hProv, "test", NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
						{
						}
						else
						{
							MessageBox::Show("контекст повторно не создан");;
						}
					}
					else
					{ 
					} 
				 }

Последний раз редактировалось sinestro; 27.10.2014 в 23:14.
sinestro вне форума Ответить с цитированием
Старый 27.10.2014, 23:15   #10
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
это я из примера скопипастил.
Так а с чего ты взял что у тебя такой контейнер будет?
Ну ты даешь - у чувака, автора примера такой контейнер (хранилище) уже было создано, это не значит что оно будет у тебя. )))
Потому и ошибка, потому и хендл прова нулевой.
Цитата:
а вот уже из другого примера
CryptAcquireContext(&hProv,"test",0 ,PROV_RSA_FULL,CRYPT_NEWKEYSET);
Ну это уже более менее похоже на правду.
Цитата:
но в нём тоже проблема с CryptGetUserName.
КАКАЯ!!!???
Ты текст ошибки или хотя бы код будешь приводить? Или в угадай мелодию поиграем?
И вообще, что это за функа такая?
Я лично ключ выдираю следующей цепочкой:
1) CryptAcquireContext(... CRYPT_NEWKEYSET)
2) CryptGenKey(hProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, key)
3) CryptGetUserKey(hProv, AT_KEYEXCHANGE, key)
4) CryptExportKey(key, 0, bt, 0, nil, lBufLen)
5) CryptExportKey(key, 0, bt, 0, d, lBufLen)
6) CryptDestroyKey(key)
Где:
bt - PUBLICKEYBLOB
lBufLen - сначала получаю размер для буфера, а потом и сам буфер в переменку "d"
Потом "d" выцеживаю в файл.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
WinCrypt и c++.net sinestro Общие вопросы C/C++ 3 26.10.2014 02:01
Ключ реестра KolaSh Общие вопросы Delphi 7 30.05.2013 08:37
Составить список стран, в которые экспортируется данный товар, и общий объем его экспорта - си - C++ kaizer131 Помощь студентам 0 21.02.2010 16:16
Ключ на ДЕЛФИ 5! sting Помощь студентам 1 28.03.2009 04:43