Windows下驗證https證書

2021-09-09 00:23:28 字數 4806 閱讀 6494

最近在寫乙個windows桌面程式需要給https請求加上證書驗證,使用的http庫是libcurl+openssl,使用openssl自帶的證書驗證功能,只能內嵌ca證書,但是我的程式不方便更新,所以最好的方式是使用windows的證書儲存做驗證,這裡有兩種方式。

這種方式的缺點是如果windows沒有安裝服務端使用的ca證書,驗證會失敗。

void

addcertificatesforstore

(x509_store *certstore,

const

char

*subsystemname)

while

(windowscertificate=

certenumcertificatesinstore

(storehandle, windowscertificate))}

}while

(false);if

(storehandle)

}int

sslcontextfunction

(void

* curl,

void

* sslctx,

void

* userdata)

return curle_ok;

}curl_easy_setopt

(curl, curlopt_ssl_verifypeer,1)

;curl_easy_setopt

(curl, curlopt_ssl_ctx_function, sslcontextfunction)

;

這種方式的好處是即使windows證書不全,也能自動更新,缺點是驗證時間可能會很長。

原來windows在驗證證書的時候會預設通過網路獲取ca的crl(證書吊銷列表),檢查該證書是否已被吊銷。我們可以通過libcurl設定不檢查crl(這樣做會不安全)。

curl_easy_setopt

(curl, curlopt_ssl_options, curlsslopt_no_revoke)

;

禁用證書吊銷檢查後依然出錯了,顯示15秒超時。

為了知道是哪一步出問題了,我自己寫了驗證證書**(使用windows介面)來代替libcurl的預設實現,**可以參考libcurl,php,chromium,使用cert_chain_revocation_check_cache_only可以阻止從網路獲取crl。

static

intsslcontextfunction

(void

* curl,

void

* sslctx,

void

* userdata)

static

intsslverifycallback

(x509_store_ctx *x509_store_ctx,

void

*arg)

certctx =

certcreatecertificatecontext

(x509_asn_encoding, derbuf, derlen);if

(certctx ==

null

)/* next fetch the relevant cert chain from the store */

cert_enhkey_usage enhkeyusage =

; cert_usage_match certusage =

; cert_chain_para chainparams =

; lpstr usages=

; enhkeyusage.cusageidentifier =3;

enhkeyusage.rgpszusageidentifier = usages;

certusage.dwtype = usage_match_type_or;

certusage.usage = enhkeyusage;

chainparams.requestedusage = certusage;

dword chainflags = cert_chain_cache_end_cert|cert_chain_revocation_check_chain_exclude_root;if(

!certgetcertificatechain

(null

, certctx,

null

, certctx->hcertstore,

&chainparams, chainflags,

null

,&certchainctx))if

(certchainctx)

/* then verify it against a policy */

auto certname =

x509_get_subject_name

(cert)

;auto index =

x509_name_get_index_by_nid

(certname, nid_commonname,-1

);if(index <0)

asn1_string_to_utf8

(&certnameutf8,

x509_name_entry_get_data

(x509_name_get_entry

(certname, index)))

; std:

:wstring servername;if(

!strutils:

:utf8tounicode

(servername,

(char*)

(certnameutf8)))

ssl_extra_cert_chain_policy_para sslpolicyparams =

; cert_chain_policy_para chainpolicyparams =

; cert_chain_policy_status chainpolicystatus =

; sslpolicyparams.dwauthtype = authtype_server;

sslpolicyparams.pwszservername =const_cast

>

(servername.

c_str()

);sslpolicyparams.fdwchecks =

0x00001000

;// security_flag_ignore_cert_cn_invalid

chainpolicyparams.pvextrapolicypara =

&sslpolicyparams;

chainpolicyparams.dwflags = cert_chain_policy_ignore_all_rev_unknown_flags;

auto verifyresult =

certverifycertificatechainpolicy

(cert_chain_policy_ssl, certchainctx,

&chainpolicyparams,

&chainpolicystatus);if

(verifyresult && chainpolicystatus.dwerror == error_success)

else

else}}

while

(false);if

(derbuf)

if(certnameutf8)

if(certctx)

if(certchainctx)

return ret;

}

呼叫certgetcertificatechain時抓取程式dump,發現程式阻塞在了winhttpgetproxyforurl,原來crypt介面使用winhttp來獲取ctl和根證書,在發起請求前會使用winhttpgetproxyforurl獲取**資訊。

winhttpgetproxyforurl為什麼會一直阻塞呢,使用ida分析發現,winhttpgetproxyforurl內部會使用rpc呼叫wpad服務查詢**資訊,然後呼叫waitformultipleobjects等待返回,所以歸根到底是wpad服務阻塞了。

win7預設開啟了wpad(winhttp web proxy auto-discovery service),該服務可以讓程式自動發現**伺服器,wpad 可以借助 dns 伺服器或 dhcp 伺服器來查詢**自動配置(pac)檔案的位置。關閉掉internet選項-連線-區域網設定-自動檢測設定或者禁用wpad服務後重新執行,發現正常了。

為什麼wpad服務會阻塞呢,呼叫certgetcertificatechain時抓取wpad服務dump,發現wpad會呼叫gethostname獲取本地主機名,然後呼叫getaddrinfo解析,最終阻塞在了nbt_resolvename。

查閱資料發現解析本地主機名超時和netbios以及dhcp有關係,虛擬機器下的windows本地連線會生成乙個「連線特定的dns字尾」localdomain,生成手動填寫本地連線ip位址也正常了。

https證書驗證

目前是在 godaddy 申請的 cn test.com 收到檔案後會列印乙份送行政部法務組,存入保險櫃。檔案構成 nginx 上配置 https 需要兩個引數 新證書驗證 2013年10月13日我們收到了新的 gd bundle.crt 和 test.com.crt 兩個檔案,理論上應該是匹配舊的...

windows下編譯支援https的curl

先編譯好openssl,過程詳見 windows下編譯openssl 編譯好zlib,過程詳見 windows下編譯zlib 官網 2.配置包含檔案目錄和依賴庫目錄 檢視原始碼根目錄下winbuild目錄下build.windows.txt的提示 在源 同級的目錄下建立deps資料夾 此時的目錄結構...

解決windows下gem SSL證書驗證錯誤

執行gem update時證書驗證錯誤 error while executing gem gem remotefetcher fetcherror ssl connect returned 1 errno 0 state sslv3 read server certificate b certif...