#windows #delphi #openssl #certificate-store
#Windows #delphi #openssl #хранилище сертификатов
Вопрос:
Я пытаюсь создать программу, которая использует некоторые веб-службы в Delphi XE. Для подключения к веб-службам я должен использовать самозаверяющий сертификат, который хранится в хранилище сертификатов Windows. Я открываю хранилище сертификатов с помощью CertOpenSystemStore, получаю сертификат с CertFindCertificateInStore
помощью и устанавливаю его SSL_CTX_use_certificate
. С этим проблем нет. Затем я получаю большой двоичный объект с открытым ключом 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
помощью and SSL_CTX_check_private_key
— пока никаких проблем. Но когда начинается передача данных, я получаю нарушение доступа в libeay32.dll . Если я загружу ключ из файла .pem, все в порядке. Я не вижу, что я делаю не так, пожалуйста, помогите 🙂
Вот точное сообщение об ошибке:
Нарушение доступа по адресу 09881C5F в модуле ‘libeay32.dll «. Считывание адреса 00000000.
libeay32.dll версия 1.0.0.5. Пробовал с версией 0.9. что-то тоже — получил ту же ошибку, только другой адрес.
Ниже приведена структура 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, и они ВЕРНЫ, а все остальное выглядит нормально. И да, ошибка возникает при вызове функции ssl_read
.
Комментарии:
1. Добро пожаловать в StackOverflow. Я боюсь, что «я получаю нарушение доступа в libea32.dll » не дает нам никакой информации, чтобы попытаться помочь вам. Если вы получаете сообщение об ошибке, исключении или AV, очень важно указать точное сообщение об ошибке (вместе с любыми адресами памяти). Если мы не сможем предоставить это, это означает, что мы запрашиваем его, а затем ждем, пока вы не предоставите его нам, прежде чем мы сможем попытаться помочь. Если вы укажете информацию об ошибке в своем исходном вопросе (вместе с кодом и текстом вопроса, которые вы предоставили), вы получите ответ намного быстрее. Пожалуйста, отредактируйте и добавьте его. Спасибо. 🙂
2. Исключения с
Read of address 0x00000000
in Delphi почти всегда (не в 100% случаев, но почти) вызваны доступом к объекту до его создания или указателем, которому никогда не присваивается ничего, на что можно указывать (нулевой указатель). Можете ли вы сузить область в коде, которая вызывает нарушение доступа? ( 1 за хороший вопрос после редактирования, кстати.)3. @Ken White Спасибо за ответ. Почему-то я не могу правильно выровнять код в комментарии, поэтому я отредактировал вопрос. Структура RSA, которую я получаю, выглядит нормально для меня..
4. Все значения nil выглядят подозрительно, особенно ex_data(nil, -1163005939 {$BAADF00D}) — $BAADF00D обычно является заполнителем для недопустимого блока памяти, установленного FastMM и некоторыми другими библиотеками. Это определенно признак проблемы
5. В какой строке возникает ошибка и откуда вы получаете заголовки OpenSSL?
Ответ №1:
Мне кажется, что наиболее разумные причины, по которым вы могли бы получить эти ошибки, включают:
- Неправильная версия библиотеки DLL OpenSSL (libeay32 ssleay.dll ) или ошибка при объявлении оболочек SSL (в этом случае вам может потребоваться обновление Indy версии 10).
- Согласно комментарию Кена, вы уже освободили блок памяти, который вы передаете в DLL.
- Какая-то тонкая ошибка разыменования указателя в опубликованном вами коде. При вызове CopyMemory может отсутствовать уровень косвенного указания указателя через «PointerVariableName ^» вместо просто «PointerVariableName». Если вам непонятно, прочитайте «нетипизированные параметры и указатели var в pascal».