简体   繁体   English

使用Windows证书存储区中的证书和私钥与OpenSSL

[英]Using certificate and private key from Windows cert store with OpenSSL

I am trying to make a program that uses some Web Services in Delphi XE. 我正在尝试制作一个在Delphi XE中使用某些Web服务的程序。 To connect to the Web Services, I have to use a self signed certificate, which is stored in the Windows cert store. 要连接到Web服务,我必须使用自签名证书,该证书存储在Windows证书库中。 I open the cert store with CertOpenSystemStore, get the cert with CertFindCertificateInStore and set it with SSL_CTX_use_certificate . 我打开与CertOpenSystemStore的证书存储,获得与证书CertFindCertificateInStore ,并设置SSL_CTX_use_certificate No problem with this. 没问题。 Then I get the public key blob with CryptExportKey and make up a private key like this: 然后我用CryptExportKey获取公钥blob并组成一个私钥,如下所示:

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;

I then set it up with SSL_CTX_use_PrivateKey and SSL_CTX_check_private_key - no problem so far. 然后我用SSL_CTX_use_PrivateKeySSL_CTX_check_private_key设置它 - 到目前为止没问题。 But when the data transfer begins, I get an access violation in libeay32.dll. 但是当数据传输开始时,我在libeay32.dll中遇到了访问冲突。 If I load the key from .pem file, everything is fine. 如果我从.pem文件加载密钥,一切都很好。 I can't see what I am doing wrong, please help :) 我看不出我做错了什么,请帮忙:)

Here is the exact error message: 这是确切的错误消息:

Access violation at address 09881C5F in module 'libeay32.dll'. 模块'libeay32.dll'中地址09881C5F的访问冲突。 Read of address 00000000. 读取地址00000000。

The libeay32.dll version is 1.0.0.5. libeay32.dll版本是1.0.0.5。 Tried with version 0.9.something too - got the same error, just different address. 试过版本0.9.something也 - 得到相同的错误,只是不同的地址。

Below is the RSA structure I get in PrivKeyBlob2RSA : 以下是我在PrivKeyBlob2RSA获得的RSA结构:

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

I checked the n and e bignums, and they are CORRECT, and everything else looks ok. 我检查了n和e bignums,它们是正确的,其他一切看起来都不错。 And yes, the error happens when calling function ssl_read . 是的,调用函数ssl_read时会发生错误。

It seems to me the most reasonable reasons you would get these errors include: 在我看来,你会得到这些错误的最合理的原因包括:

  1. Wrong version of OpenSSL dlls (libeay32 ssleay.dll) or error in declaring SSL wrappers (in this case you might need an Indy Version 10 upgrade). 错误的OpenSSL dll版本(libeay32 ssleay.dll)或声明SSL包装器时出错(在这种情况下,您可能需要进行Indy版本10升级)。

  2. Having already freed the block of memory you're passing into the DLL, as per Ken's comment. 根据Ken的评论,已经释放了你传入DLL的内存块。

  3. Some subtle pointer dereferencing bug in the code you posted. 一些微妙的指针解除引用您发布的代码中的错误。 A call to CopyMemory might be missing a level of pointer indirection via "PointerVariableName^" instead of just "PointerVariableName". 对CopyMemory的调用可能会通过“PointerVariableName ^”而不仅仅是“PointerVariableName”错过指针间接层。 Read up on "untyped var parameters and pointers in pascal" if you're unclear. 如果您不清楚,请阅读“pascal中的无类型var参数和指针”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM