Использование сертификата и закрытого ключа из хранилища сертификатов Windows с OpenSSL

27

Я пытаюсь создать программу, которая использует некоторые веб-службы в Delphi XE. Чтобы подключиться к веб-службам, я должен использовать самоподписанный сертификат, который хранится в хранилище сертификатов Windows. Я открываю хранилище сертификатов с помощью CertOpenSystemStore, получаю сертификат с CertFindCertificateInStore и устанавливаю его с помощью SSL_CTX_use_certificate. Нет проблем с этим. Затем я получаю открытый ключ blob с CryptExportKey и создаю закрытый ключ следующим образом:

function PrivKeyBlob2RSA(const AKeyBlob: PByte; const ALength: Integer; const ASSLCtx: PSSL_CTX): IdSSLOpenSSLHeaders.PEVP_PKEY;
var
  modulus: PByte;
  bh: PBLOBHEADER;
  rp: PRSAPUBKEY;
  rsa_modlen: DWORD;
  rsa_modulus: PAnsiChar;
  rkey: PRSA;
begin
  bh := PBLOBHEADER(AKeyBlob);
  Assert(bh^.bType = PUBLICKEYBLOB);
  rp := PRSAPUBKEY(AKeyBlob + 8);
  Assert(rp.magic = $31415352);
  rsa_modulus := PAnsiChar(Integer(Pointer(rp))+12);
  rkey := RSA_new_method(ASSLCtx.client_cert_engine);
  rkey^.References := 1;
  rkey^.e := BN_new;
  rkey^.n := BN_new;
  BN_set_word(rkey^.e, rp^.pubexp);
  rsa_modlen := (rp^.bitlen div 8) + 1;
  modulus := AllocMem(rsa_modlen);
  CopyMemory(modulus, rsa_modulus, rsa_modlen);
  RevBuffer(modulus, rsa_modlen);
  BN_bin2bn(modulus, rsa_modlen, rkey^.n);
  Result := EVP_PKEY_new;
  EVP_PKEY_assign_RSA(Result, PAnsiChar(rkey));
end;

Затем я установил его с SSL_CTX_use_PrivateKey и SSL_CTX_check_private_key - пока не проблема. Но когда начинается передача данных, я получаю нарушение доступа в libeay32.dll. Если я загружу ключ из файла .pem, все в порядке. Я не вижу, что я делаю неправильно, пожалуйста, помогите:)

Вот точное сообщение об ошибке:

Нарушение доступа по адресу 09881C5F в модуле libeay32.dll. Читайте адрес 00000000.

Версия libeay32.dll 1.0.0.5. Пробовал с версией 0.9.something тоже - получил ту же ошибку, просто другой адрес.

Ниже представлена ​​структура RSA, которую я получаю в PrivKeyBlob2RSA:

pad    0
version  0
meth       $898030C
engine     nil
n      $A62D508
e      $A62D4D8
d      nil
p      nil
q      nil
dmp1       nil
dmq1       nil
iqmp       nil
ex_data (nil, -1163005939 {$BAADF00D})
references  1
flags      6
_method_mod_n   nil
_method_mod_p   nil
_method_mod_q   nil
bignum_data nil {#0}
blinding    nil
mt_blinding nil

Я проверил n и e bignums, и они CORRECT, и все остальное выглядит нормально. И да, ошибка возникает при вызове функции ssl_read.

  • 3
    Добро пожаловать в StackOverflow. Я боюсь, что «я получаю нарушение прав доступа в libea32.dll» не дает нам никакой информации, чтобы попытаться помочь вам. Если вы получаете сообщение об ошибке или исключение или AV, очень важно включить точное сообщение об ошибке (вместе с любыми адресами памяти). Неспособность предоставить это означает, что мы просим об этом, а затем ждем, пока вы не отдадите его нам, прежде чем мы сможем попытаться помочь. Если вы предоставите информацию об ошибке в исходном вопросе (вместе с кодом и текстом вопроса, который вы предоставили), вы получите ответ намного быстрее. Пожалуйста, отредактируйте и добавьте его. Благодарю. :)
  • 2
    Исключения с Read of address 0x00000000 в Delphi почти всегда (не в 100% случаев, но почти) вызваны доступом к объекту до его создания или указателем, которому никогда не назначается что-либо, на что можно указать (нулевой указатель). Можете ли вы сузить место в коде, который вызывает нарушение прав доступа? (+1 за хороший вопрос после редактирования, кстати.)
Показать ещё 5 комментариев
Теги:
openssl
certificatestore

1 ответ

1

Мне кажется, наиболее разумные причины, по которым вы получите эти ошибки, включают:

  • Неверная версия DLL OpenSSL (libeay32 ssleay.dll) или ошибка при объявлении оберток SSL (в этом случае вам может потребоваться обновление Indy Version 10).

  • После освобождения блока памяти, который вы передаете в DLL, согласно комментарию Кена.

  • Некоторая тонкая ошибка разыменования указателя в отправленном вами коде. В вызове CopyMemory может отсутствовать уровень указателя указателя через "PointerVariableName ^" вместо "PointerVariableName". Прочитайте "неопределенные параметры и указатели var в паскале", если вы неясны.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню