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

时间:2011-10-27 08:59:06

标签: windows delphi openssl certificate-store

我正在尝试制作一个在Delphi XE中使用某些Web服务的程序。要连接到Web服务,我必须使用自签名证书,该证书存储在Windows证书库中。我使用CertOpenSystemStore打开证书存储区,使用CertFindCertificateInStore获取证书并使用SSL_CTX_use_certificate进行设置。没问题。然后我使用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;

然后我使用SSL_CTX_use_PrivateKeySSL_CTX_check_private_key进行设置 - 到目前为止没问题。但是当数据传输开始时,我在libeay32.dll中遇到了访问冲突。如果我从.pem文件加载密钥,一切都很好。我看不出我做错了什么,请帮忙:)

以下是确切的错误消息:

  

模块'libeay32.dll'中地址09881C5F的访问冲突。阅读   地址00000000。

libeay32.dll版本是1.0.0.5。尝试使用0.9.something版本 - 得到了相同的错误,只是不同的地址。

以下是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

我检查了n和e bignums,它们是正确的,其他一切看起来都不错。是的,调用函数ssl_read时会发生错误。

1 个答案:

答案 0 :(得分:1)

在我看来,你会得到这些错误的最合理的原因包括:

  1. 错误的OpenSSL dll版本(libeay32 ssleay.dll)或声明SSL包装器时出错(在这种情况下,您可能需要进行Indy版本10升级)。

  2. 根据Ken的评论,已经释放了你传入DLL的内存块。

  3. 您发布的代码中的一些微妙指针解除引用错误。对CopyMemory的调用可能会通过“PointerVariableName ^”而不仅仅是“PointerVariableName”错过指针间接层。如果你不清楚的话,请阅读“pascal中的无类型var参数和指针”。