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

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

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 03.01.2012, 13:43   #1
bro
Пользователь
 
Аватар для bro
 
Регистрация: 02.12.2010
Сообщений: 29
По умолчанию CryptoAPI (JWSCL) - не могу расшифровать

Генерирую и сохраняю пару ключей так:

Код:
procedure TFormMain.ButtonGenRSAPairClick(Sender: TObject);
var
  RSA: HCRYPTPROV;
  HKeyPair: HCRYPTKEY;
  Pair: TMemoryStream;
  buflen: DWORD;
begin
  Pair := TMemoryStream.Create;

  // Инициализаируем CryptoAPI
  if not(CryptAcquireContext(RSA, nil, nil, PROV_RSA_FULL,
    CRYPT_VERIFYCONTEXT)) then
    ShowMessage(IntToStr(GetLastError));

  // Генерируем пару ключей
  if not(CryptGenKey(RSA, AT_KEYEXCHANGE, RSA1024BIT_KEY or CRYPT_EXPORTABLE,
    HKeyPair)) then
    ShowMessage(IntToStr(GetLastError));

  // Пытаемся определить размер буфера для экспорта ключей
  if not(CryptExportKey(HKeyPair, 0, PRIVATEKEYBLOB, 0, nil, buflen)) then
    ShowMessage(IntToStr(GetLastError));

  // Готовим буфер
  Pair.SetSize(buflen);

  // Экспортируем сгенерированные клюи
  if not(CryptExportKey(HKeyPair, 0, PRIVATEKEYBLOB, 0, PByte(Pair.Memory),
    buflen)) then
    ShowMessage(IntToStr(GetLastError));

  // Сохраняем ключи в файл
  Pair.SaveToFile('pair.dat');

  // Освобождаем занятые ресурсы
  CryptDestroyKey(HKeyPair);
  CryptReleaseContext(RSA, 0);
  FreeAndNil(Pair);
end;
Шифрую текст публичным ключом из этой пары так:

Код:
  function EncryptString(source: string): string;
    function StringToMemStream(SourceString: string): TMemoryStream;
    begin
      Result := TMemoryStream.Create;
      Result.WriteBuffer(Pointer(SourceString)^, Length(SourceString));
    end;
    function MemStreamToString(SourceStream: TMemoryStream): string;
    begin
      SetString(Result, PChar(SourceStream.Memory), SourceStream.Size);
    end;

  var
    DecryptedData, EncryptedData, KeyPair: TMemoryStream;
    RSA: HCRYPTPROV;
    HPair: HCRYPTKEY;
    DDataSize, EDataSize: DWORD;
  begin
    DecryptedData := StringToMemStream(source);
    EncryptedData := TMemoryStream.Create;
    KeyPair := TMemoryStream.Create;

    // Инициализаируем CryptoAPI
    if not(CryptAcquireContext(RSA, nil, nil, PROV_RSA_FULL,
      CRYPT_VERIFYCONTEXT)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptAcquireContext');

    // Импортируем ключ
    KeyPair.LoadFromFile('pair.dat');
    if not(CryptImportKey(RSA, PByte(KeyPair.Memory), KeyPair.Size, 0, 0,
      HPair)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptImportKey');

    // Готовим буфер
    EDataSize := SizeOf(source);
    if not(CryptEncrypt(HPair, 0, true, 0, nil, EDataSize, 0)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptEncrypt 1');
    EncryptedData.SetSize(EDataSize);

    // Шифруем
    DDataSize := DecryptedData.Size;
    if not(CryptEncrypt(HPair, 0, true, 0, PByte(DecryptedData.Memory),
      DDataSize, EDataSize)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptEncrypt 2');

    Result := MemStreamToString(DecryptedData);

    // Освобождаем занятые ресурсы
    FreeAndNil(DecryptedData);
    FreeAndNil(EncryptedData);
    FreeAndNil(KeyPair);
    CryptDestroyKey(HPair);
    CryptReleaseContext(RSA, 0);
  end;
Пытаюсь расшифровать его закрытым ключом из этой пары так:

Код:
  function DecryptString(source: string): string;
    function StringToMemStream(SourceString: string): TMemoryStream;
    begin
      Result := TMemoryStream.Create;
      Result.WriteBuffer(Pointer(SourceString)^, Length(SourceString));
    end;
    function MemStreamToString(SourceStream: TMemoryStream): string;
    begin
      SetString(Result, PChar(SourceStream.Memory), SourceStream.Size);
    end;

  var
    EncryptedData, KeyPair: TMemoryStream;
    RSA: HCRYPTPROV;
    HPair: HCRYPTKEY;
    DDataSize, EDataSize: DWORD;
  begin
    EncryptedData := StringToMemStream(source);
    KeyPair := TMemoryStream.Create;

    // Инициализаируем CryptoAPI
    if not(CryptAcquireContext(RSA, nil, nil, PROV_RSA_FULL,
      CRYPT_VERIFYCONTEXT)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptAcquireContext');

    // Импортируем ключ
    KeyPair.LoadFromFile('pair.dat');
    if not(CryptImportKey(RSA, PByte(KeyPair.Memory), KeyPair.Size, 0, 0,
      HPair)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptImportKey');

    // Дешифруем
    EDataSize := EncryptedData.Size;
    if not(CryptDecrypt(HPair, 0, true, 0, PByte(EncryptedData.Memory),
      EDataSize)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptDecrypt');

    Result := MemStreamToString(EncryptedData);

    // Освобождаем занятые ресурсы
    FreeAndNil(EncryptedData);
    FreeAndNil(KeyPair);
    CryptDestroyKey(HPair);
    CryptReleaseContext(RSA, 0);
  end;
Получаю ошибку 2148073477 (NTE_BAD_DATA) при вызове CryptDecrypt. Что я делаю не так?
bro вне форума Ответить с цитированием
Старый 03.01.2012, 16:51   #2
bro
Пользователь
 
Аватар для bro
 
Регистрация: 02.12.2010
Сообщений: 29
По умолчанию

Самопочин:

Код:
procedure TFormMain.ButtonGenRSAPairClick(Sender: TObject);
var
  RSA: HCRYPTPROV;
  HKeyPair: HCRYPTKEY;
  Pair: TStringStream;
  buflen: DWORD;
begin
  Pair := TStringStream.Create;

  // Инициализаируем CryptoAPI
  if not(CryptAcquireContext(RSA, nil, nil, PROV_RSA_FULL,
    CRYPT_VERIFYCONTEXT)) then
    ShowMessage(IntToStr(GetLastError));

  // Генерируем пару ключей
  if not(CryptGenKey(RSA, AT_KEYEXCHANGE, RSA1024BIT_KEY or CRYPT_EXPORTABLE,
    HKeyPair)) then
    ShowMessage(IntToStr(GetLastError));

  // Пытаемся определить размер буфера для экспорта ключей
  if not(CryptExportKey(HKeyPair, 0, PRIVATEKEYBLOB, 0, nil, buflen)) then
    ShowMessage(IntToStr(GetLastError));

  // Готовим буфер
  Pair.SetSize(buflen);

  // Экспортируем сгенерированные клюи
  if not(CryptExportKey(HKeyPair, 0, PRIVATEKEYBLOB, 0, PByte(Pair.Memory),
    buflen)) then
    ShowMessage(IntToStr(GetLastError));

  // Сохраняем ключи в файл
  Pair.SaveToFile('pair.dat');

  // Освобождаем занятые ресурсы
  CryptDestroyKey(HKeyPair);
  CryptReleaseContext(RSA, 0);
  FreeAndNil(Pair);
end;
Код:
  function EncryptString(source: string): string;
  var
    DecryptedData, EncryptedData, KeyPair: TStringStream;
    RSA: HCRYPTPROV;
    HPair: HCRYPTKEY;
    DDataSize, EDataSize: DWORD;
  begin
    DecryptedData := TStringStream.Create(source);
    EncryptedData := TStringStream.Create;
    KeyPair := TStringStream.Create;

    // Инициализаируем CryptoAPI
    if not(CryptAcquireContext(RSA, nil, nil, PROV_RSA_FULL,
      CRYPT_VERIFYCONTEXT)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptAcquireContext');

    // Импортируем ключ
    KeyPair.LoadFromFile('pair.dat');
    if not(CryptImportKey(RSA, PByte(KeyPair.Memory), KeyPair.Size, 0, 0,
      HPair)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptImportKey');

    // Готовим буфер
    EDataSize := SizeOf(source);
    if not(CryptEncrypt(HPair, 0, true, 0, nil, EDataSize, 0)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptEncrypt 1');
    EncryptedData.SetSize(EDataSize);

    // Шифруем
    DDataSize := DecryptedData.Size;
    if not(CryptEncrypt(HPair, 0, true, 0, PByte(DecryptedData.Memory),
      DDataSize, EDataSize)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptEncrypt 2');

    Result := DecryptedData.DataString;

    // Освобождаем занятые ресурсы
    FreeAndNil(DecryptedData);
    FreeAndNil(EncryptedData);
    FreeAndNil(KeyPair);
    CryptDestroyKey(HPair);
    CryptReleaseContext(RSA, 0);
  end;
Код:
  function DecryptString(source: string): string;
  var
    EncryptedData, KeyPair: TStringStream;
    RSA: HCRYPTPROV;
    HPair: HCRYPTKEY;
    EDataSize: DWORD;
  begin
    EncryptedData := TStringStream.Create(source);
    KeyPair := TStringStream.Create;

    // Инициализаируем CryptoAPI
    if not(CryptAcquireContext(RSA, nil, nil, PROV_RSA_FULL,
      CRYPT_VERIFYCONTEXT)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptAcquireContext');

    // Импортируем ключ
    KeyPair.LoadFromFile('pair.dat');
    if not(CryptImportKey(RSA, PByte(KeyPair.Memory), KeyPair.Size, 0, 0,
      HPair)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptImportKey');

    // Дешифруем
    EDataSize := EncryptedData.Size;
    if not(CryptDecrypt(HPair, 0, true, 0, PByte(EncryptedData.Memory),
      EDataSize)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptDecrypt');

    Result := EncryptedData.DataString;

    // Освобождаем занятые ресурсы
    FreeAndNil(EncryptedData);
    FreeAndNil(KeyPair);
    CryptDestroyKey(HPair);
    CryptReleaseContext(RSA, 0);
  end;
Ошибка та же...
Сдаётся мне, что с размерами буферов что-то не так. Только вот что...
P.S.: хочу сделать как в CryptoPad (C#), только на дельфях.

Последний раз редактировалось bro; 03.01.2012 в 16:58.
bro вне форума Ответить с цитированием
Старый 04.01.2012, 12:01   #3
3D Hunter
Сумрачная тень
Форумчанин
 
Аватар для 3D Hunter
 
Регистрация: 05.03.2009
Сообщений: 689
По умолчанию

Скорее всего, проблема в этом:
1. Идем на http://msdn.microsoft.com/en-us/library/aa925738.aspx
2. Видим параметр DWORD* pdwDataLen? Это указатель на размер, а не сам размер. Вы передаете в качестве указателя размер структуры EDataSize.

Попробуйте заменить на @EDataSize.

З.Ы. Рекомендую пробежаться по МСДНу и посмотреть внимательно параметры этих функций. У вас в коде есть подобные ошибки.
"ковыряю изнутри" (с)
3D Hunter вне форума Ответить с цитированием
Старый 04.01.2012, 13:21   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

2)надо смотреть параметры, если там var-параметр то все ОК.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 04.01.2012, 18:47   #5
bro
Пользователь
 
Аватар для bro
 
Регистрация: 02.12.2010
Сообщений: 29
По умолчанию

3D Hunter, да нет, это же JWSCL - там вместо указателей идут сами данные.
bro вне форума Ответить с цитированием
Старый 05.01.2012, 11:25   #6
3D Hunter
Сумрачная тень
Форумчанин
 
Аватар для 3D Hunter
 
Регистрация: 05.03.2009
Сообщений: 689
По умолчанию

Ну вам виднее)
"ковыряю изнутри" (с)
3D Hunter вне форума Ответить с цитированием
Старый 06.01.2012, 10:17   #7
Slym
Участник клуба
 
Регистрация: 07.12.2011
Сообщений: 1,025
По умолчанию

в EncryptString не заполняешь DecryptedData
гдето так не проверял...
Код:
EDataSize := SizeOf(source);
if not(CryptEncrypt(HPair, 0, true, 0, nil, EDataSize, 0)) then
ShowMessage(IntToStr(GetLastError) + ' CryptEncrypt 1');
result:=source;
SetLength(result,EDataSize);
DDataSize := length(source);
if not(CryptEncrypt(HPair, 0, true, 0, PByte(PChar(result)), DDataSize, EDataSize)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptEncrypt 2');
декрипт гдето так
Код:
result:=source;
EDataSize := length(result);
if not(CryptDecrypt(HPair, 0, true, 0, PByte(PChar(result)), EDataSize)) then
      ShowMessage(IntToStr(GetLastError) + ' CryptDecrypt');
SetLength(result,EDataSize);
Не стесняемся, плюсуем!
Slym вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
функция CryptoAPI mira_m Помощь студентам 5 14.12.2011 22:51
Не могу расшифровать код Snave Паскаль, Turbo Pascal, PascalABC.NET 6 04.10.2011 00:00
CryptGenRandom,CryptoAPI tiger Помощь студентам 0 25.05.2011 00:10
расшифровать в ASCII потом цифры расшифровать в бинарный код viorel Общие вопросы Delphi 1 07.05.2010 14:43
CryptoAPI: вопрос по ф-ям Lisi4ka Компоненты Delphi 1 28.09.2008 14:53