HTTPS 服務器信任評估
當你進行HTTPS連接時,客戶端必須評估服務器是否可信。如果評估失敗,客服端應該取消連接。這種情況可能由於各種原因,例如,服務器使用自己簽名的證書,中間證書缺失等。還有一些惡意情況,服務器可能是個爲了盜竊用戶數據的冒充服務器。
HTTPS 相關概念
• 驗證諮詢(authentication challenge) - 它是一個HTTP或者HTTPS的響應,指示服務器請求客服端驗證信息。Foundation框架中用NSURLAuthenticationChallenge表示。它同樣支持HTTPS的服務器信任評估。它是保護空間的驗證諮詢。
• 證書(certificate)- 摘要證書。
• 證書認證機構(certificate authority)- 一個可靠的派發證書機構。每個CA會派發一個或者多個根證書,這些根證書用於信任評估該授權機構派發的證書。
• 證書認證機構鎖定(certificate authority pinning)- 服務器需要提供指定的CA派發的證書。
• 證書鎖定(certificate pinning)- 服務器需要提供指定的證書或者證書必須包含指定的公鑰。
• 撤銷證書列表(certificate revocation list,CRL)- 一個被撤銷的證書列表,它們不應該被信任。
• 數字證書(digital certificate)- 一種最通用的證書(certificate)它使用公鑰加密實體的數字簽名來關聯信息。在TLS中,所有數字證書都是X.509數字證書。
• 數字ID(digital identity)- 證書和關聯該證書公鑰的私鑰的結合。
• 數字簽名(digital signature)- 用於證明一些數據的真實性。你可以使用私鑰來驗證簽名來確保是對應的私鑰加密生成的。
• 擴展驗證(extended validation)- 使用擴展證書驗證。
• HTTP - 超文本傳輸協議。
• HTTPS - 在TLS上的HTTP。
• HTTPS服務器信任評估 - (HTTPS server trust evaluation)HTTPS是TLS上的HTTP,所以等價於TLS服務器信任評估。
• 中間證書 - (intermediate certificate)服務器證書到根證書之前的中間證書。
• 發行人 -(issuer)X.509數字證書籤名的實體。
• OCSP -(Online Certificate Status Protocol)一個檢查證書是否被撤銷的協議。
• 私鑰 -(private key)用於解密數據和生成數字簽名。
• 保護空間 -(protection space,realm)一個請求驗證的HTTP或者HTTPS的服務器。在Foundation框架中,用NSURLProtectionSpace表示。
• 公鑰 -(public key)用於加密數據或者驗證數字簽名。
• 公鑰加密系統 -(public key cryptography)一個加密系統。它使用兩個分開的密鑰。一個是公鑰,一個是私鑰。私鑰用於解密數據和生成數字簽名,公鑰用於加密數據和驗證數字簽名。
• 公鑰基礎設施 -(public key infrastructure)一個管理公鑰和私鑰的機制。公鑰內嵌到證書,TLS使用X.509公鑰。
• 根證書 -(root certificate)一個CA提供的自簽名證書,用來信任評估該CA派發的證書。
• 安全套接字層 -(SSL)TLS的上版本。
• 自簽名證書 -(self-signed certificate)一個X.509數字證書,它的主體和發行人是相同的。根證書是自簽名的,但是任何人都可以創建自己的自簽名證書。
• 服務器證書 -(server certificate)TLS服務器提供的X.509數字證書。TLS協議確保私鑰在服務器上,對應的公鑰內嵌在這個證書。這個證書正是TLS服務器信任驗證的對象。
• 服務器信任評估 -(server trust evaluation)客戶端對服務器進行信任評估。
• 主體 -(subject)對於X.509數字證書,它是證書標識的實體。在TLS中,這個服務器證書主體是服務器的DNS名稱。
• TLS -(TLS)傳輸層安全協議,在SSL之後。
• TLS服務器信任評估 -(TLS server trust evaluation)信任評估包含一組X.509證書信任評估和附加的TLS特定檢查。操作的是服務器的證書。
• 信任評估 -(trust evaluation)一個實體決定是否信任另外一個實體,根據這個實體的數字證書。
• 信任錨點 -(trust anchor)系統明確信任的證書。一般是已經存儲在系統的CA的根證書。但在一些情況下,你可以標記任何證書爲信任錨點。
• 信任的證書認證機構 -(trusted certificate authority)CA的根證書都被存儲在系統併成爲信任錨點。
• 有效日期範圍 -(valid date range)對於X.509證書,代表證書的有效日期範圍。
• 驗證日期 -(verify date)在X.509證書信任評估,有效日期需要檢驗。
介紹
服務器信任評估錯誤:
Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “example.com” which could put your confidential information at risk." UserInfo=0x14a730 {NSErrorFailingURLStringKey=https://example.com/, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSErrorFailingURLKey=https://example.com/, NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “example.com” which could put your confidential information at risk., NSUnderlyingError=0x14a6c0 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “example.com” which could put your confidential information at risk.", NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x14ec00>}
在這個錯誤中code=-1202代表NSURLErrorServerCertificateUnTrusted。表明服務器信任評估失敗。
HTTPS是HTTP在TLS上的協議。
• 保證隱私 - 不能修改和替換數據包。
• 客服端驗證服務器證明 - 保證不被中間人攻擊(能夠在客服端和服務器之間修改和替換數據包),中間人可以冒充服務器來獲取客服端的私密數據。
TLS也可以服務器驗證客服端證明。服務器請求客服端證書來驗證是否信任客服端。
處理服務器信任評估失敗
理解服務器信任評估失敗
當你使用TLS連接服務器,服務器會提供證書給你並且保證服務器的私鑰對應證書的公鑰。之後檢查證書是否是你想要連接的服務器。
基礎信任評估
TLS服務器信任評估包括下面2個基本步驟:
1. 基本X.509證書信任評估。
2. 附加的TLS檢查。
X.509證書有5個重要屬性:
• 主體信息。
• 發行人信息。
• 證書信息(例如,有效日期範圍)。
• 公鑰。
• 數字簽名。
如果數字證書是有效的,發行人會擔保證書的主體擁有私鑰和對應的公鑰在證書。
X.509證書信任評估會遞歸這2步處理:
1. 檢查證書的有效性。主要涉及2步檢查,檢查數字簽名的有效性和證書有效日期。
2. 檢查發行人的有效性。檢查發行人的證書並遞歸地檢查證書有效性。
遞歸處理必須最終能夠終止。信任評估只有一種成功情況:命中信任錨點。信任錨點是系統明確信任的證書和已經存儲在系統的著名CA根證書。
信任評估可能會失敗由於各種原因:
• 命中無效證書。
• 不能發現證書的發行人。
• 命中自簽名的證書不是信任錨點。
如果X.509證書信任評估成功,系統會進行附加的特定TLS檢查。涉及檢查連接的DNS域名和證書的DNS域名是否相同。這裏還有一些其他的事情:
• 通常,你可能希望發現DNS域名在主體通用名參數(Common Name field),也可以在主體可選名擴展中(Subject Alternative Name extension)。如果這個名字出現在主體可選名擴展,優先使用它(相對於Common Name field)。
• 主體可選名擴展(Subject Alternative Name extension)可能包含IP地址。客服端可以商量使用IP地址或者是DNS域名。
• 證書的DNS域名可能包含通配符,例如“*.apple.com”。
• Extended Key Usage擴展希望包含Server Authentication值。
通用失敗
• 沒有發行人證書 - 對所以提供的證書(除了信任錨點證書),系統必須能夠定位到發行人證書。
• 日期問題 - 驗證日期在證書的有效日期範圍。
• 自簽名證書 - 對於自簽名證書,這會導致評估失敗(除非它是信任錨點證書)。
• 不是可信任的證書認證機構(CA)- 系統必須隨着發行人證書直到信任的CA根證書。
• DNS域名不匹配 - 你嘗試連接的服務器的DNS域名必須匹配服務器證書的DNS域名。
鑰匙串訪問
鑰匙串
訪問有大量的證書調試特性:
• 它可以導入和導出證書並且用各種格式標識。
• 如果你雙擊證書,系統會打開一個GUI界面。
• 證書助手(從鑰匙串獲取)能夠信任評估指定的證書。
• 證書助手可以創建自簽名證書。
• 證書助手可以創建CA來派發葉子證書或者中間證書。
你可以創建一個鑰匙鏈來進行鑰匙串訪問。
安全工具
• 轉存鑰匙鏈爲文本形式。
• 詳細地進行信任設置。
• 添加和移除鑰匙鏈證書。
Safari瀏覽器
如果你使用Safari瀏覽器訪問HTTPS網站,你可以在title欄點擊鎖頭圖標來獲取證書的相關信息。
如果你使用Safari瀏覽器訪問不被信任的HTTPS網址,Safari會展示一個“不能驗證網站身份”的Sheet。
自定義基本信任
信任評估對象SecTrustRef。你可以直接創建它,但TLS服務器中,系統的API已經幫你做了默認的信任評估處理,你可以在這個基礎上自定義它。
1. 獲取信任對象。
2. 自己評估,確保檢查上述的失敗情況。
3. 如果信任評估成功,你可以指定嚴格的信任評估規則。
4. 如果信任評估失敗,使用你自定義信任對象。
5. 再次評估這個對象,確定允許或者取消連接。
OSStatus err;
BOOL allowConnection;
SecTrustResultType trustResult;
allowConnection = NO;
err = SecTrustEvaluate(trust, &trustResult);
if (err == noErr) {
allowConnection = (trustResult == kSecTrustResultProceed) ||
(trustResult == kSecTrustResultUnspecified);
}
如果你收到的服務器證書不是被系統認證的CA派發的,你可以調用SecTrustSetAnchorCertificates方法來設置錨點證書(相當於CA的根證書)。
OSStatus err;
BOOL allowConnection;
SecCertificateRef customAnchor;
SecTrustResultType trustResult;
allowConnection = NO;
customAnchor = ... the CA's root certificate ...;
err = SecTrustSetAnchorCertificates(
trust,
(__bridge CFArrayRef) [NSArray arrayWithObject:(__bridge id) customAnchor]
);
if (err == noErr) {
err = SecTrustEvaluate(trust, &trustResult);
}
if (err == noErr) {
allowConnection = (trustResult == kSecTrustResultProceed) ||
(trustResult == kSecTrustResultUnspecified);
}
code
最後,可能由於一些情況自定義請求不能直接在信任對象評估。例如,如果你希望信任對象被認爲是額外的中間證書,你不能直接添加到信任對象。你可能需要重新創建信任對象來評估它。
OSStatus err;
BOOL allowConnection;
CFArrayRef policies;
NSMutableArray * certificates;
CFIndex certCount;
CFIndex certIndex;
SecCertificateRef extraIntermediate;
SecTrustRef newTrust;
SecTrustResultType newTrustResult;
allowConnection = NO;
policies = NULL;
newTrust = NULL;
err = SecTrustCopyPolicies(trust, &policies);
if (err == errSecSuccess) {
certificates = [NSMutableArray array];
certCount = SecTrustGetCertificateCount(trust);
for (certIndex = 0; certIndex < certCount; certIndex++) {
SecCertificateRef thisCertificate;
thisCertificate = SecTrustGetCertificateAtIndex(trust, certIndex);
[certificates addObject:(__bridge id)thisCertificate];
}
extraIntermediate = ... the extra intermediate certificate to use ...;
[certificates addObject:(__bridge id)extraIntermediate];
err = SecTrustCreateWithCertificates(
(__bridge CFArrayRef) certificates,
policies,
&newTrust
);
if (err == noErr) {
err = SecTrustEvaluate(newTrust, &newTrustResult);
}
if (err == noErr) {
allowConnection = (newTrustResult == kSecTrustResultProceed) ||
(newTrustResult == kSecTrustResultUnspecified);
}
}
if (newTrust != NULL) {
CFRelease(newTrust);
}
if (policies != NULL) {
CFRelease(policies);
}
關於自定義信任API
WebView
你可以獲取NSURLConnect的authentication challenges通過resourceLoadDelegate屬性。
UIWebView
不能自定義HTTPS服務器信任評估。
HTTP流媒體直播
HTTP流媒體直播支持服務器信任評估根據獲取的資源類型。
NSURLSession
NSURLSession允許你通過實現URLSession:didReceiveChallenge:completionHandler:方法來自定義HTTPS服務器信任評估。爲例實現自定義HTTPS服務器信任評估,你需要檢查Challenge對象的保護空間(protection space)是否有NSURLAuthenticationMethodServerTrust驗證方法。對於其他類型的Challenge,你不用去考慮,只需要調用completion handler block 使用NSURLSessionAuthenticationChallengePerformDefaultHandling的disposition處理和NULL 證書。
當你處理NSURLAuthenticationMethodServerTrust的authentication challenge,你可以獲取信任對象從challenge的保護空間(protection space)調用serverTrust方法獲取。之後你可以使用這個信任對象來執行自定義HTTPS服務器信任評估,你必須處理challenge使用下面2個方法:
• 如果你想要禁止連接,調用completion handler block並提供NSURLSessionAuthChallengeCancelAuthenticationChallenge的disposition和NULL 證書。
• 如果你想要允許連接,創建證書從你的信任對象(使用+[NSURLCredential credentialForTrust:]方法),之後調用completion handler block並提供NSURLSessionAuthChallengeUserCredential的disposition。
注意:系統會避免你使用創建的證書的信任對象的信任結果;任何有效的信任對象將允許連接成功。
NSURLConnection
NSURLConnection允許你自定義HTTPS服務器信任評估。類似NSURLSession,這裏有2個不同的地方:
• 你實現不同的代理方法(-connect:willSendRequestForAuthenticationChallenge:)。
• 當處理challenge,你必須獲取sender從challenge(通過-sender方法),之後調用適當的方法在sender。
• 對於你不用考慮的challenge,調用-performDefaultHandlingForAuthenticationChallenge方法。
• 如果你想要禁止連接,調用-cancelAuthenticationChallenge: 。
• 如果你想要允許連接,調用-useCredential:forAuthenticationChallenge:,提供證書對象使用信任對象創建。
CFHTTPStream
CFHTTPStream允許你自定義HTTPS服務器信任評估。
CFSocketStream
爲了自定義TLS服務器信任評估:
1. 使用kCFStreamSSLValidatesCertificateChain實體的kCFStreamPropertySSLSettings屬性來完全失效服務器信任評估。
2. 一旦流被連接,在你發送任何數據和信任任何接收數據之前,從流的kCFStreamPropertySSLPeerTrust的屬性獲取信任對象。
3. 使用信任對象來實現自定義HTTPS信任評估。
4. 根據信任評估結果來決定繼續連接或者關閉。
第2步:什麼時候流被連接?當你獲取流打開完成事件,信任對象不可用。爲了保證信任對象可用,你必須等待有空間可用事件或者有字節可用事件。
安全傳輸
安全傳輸也允許自定義TLS服務器信任評估。處理過程如下:
1. 開始連接之前,調用SSLSetSessionOption並設置kSSLSessionOptionBreakOnServerAuth。
2. 如果有必要,調用SSLSetEnableCertVerify方法來失效默認服務器認證評估。
3. 執行安全傳輸握手。
4. 當SSLHandshake返回errSSLServerAuthComplete,調用SSLCopyPeerTrust來連接的信任對象。
5. 使用信任對象實現自定義服務器信任評估。
6. 繼續執行安全傳輸的握手或者中斷連接。
處理特殊的服務器信任評估失敗
在處理之前記住2點:
• 目前最簡單和最安全的處理服務器信任評估失敗的方法是修復服務器。你應該在修復服務器很困難的情況下考慮下面的方法。
• 大多數用戶是沒有相關網絡安全的知識的。呈現用戶界面讓用戶決定是否連接是錯誤的方式,這可能會造成一些安全隱患。
服務器名失敗
如果服務器信任評估失敗是由於服務器的DNS域名不匹配證書的DNS域名,你可以忽略這種情況。使用SecPolicyCreateSSL方法創建一個新的帶有正確的服務器名的政策(SecPolicyRef),之後調用SecTrustSetPolicies方法來讓信任對象(SecTrustRef)使用這個政策。
缺失中間證書
這裏有幾種方法來解決缺失中間證書:
• 最佳的方法同時也是常用的方法就是修復服務器。讓服務器提供可以追蹤到信任的CA根證書的服務器證書。
• 在OS X上,你可以添加這個中間證書到鑰匙鏈來完成正確的信任。
• 在IOS上,你可以添加這個中間證書到鑰匙鏈來完成正確的信任。
• 如果上面都失敗,你只能自己生產中間證書(bundle或者從網上下載);之後從原來的信任對象獲取信任鏈證書集合並添加中間證書;重新使用證書集合創建新的信任對象;使用這個信任對象進行信任評估。
信任一個特殊證書
在一些情況,把證書當做簡單的id token是有用的。例如,在點對點程序中,X.509信任評估是無意義的,因爲這裏沒有CA派發它們。但是,你任然可以使用TLS安全傳輸。
1. 通過你自己建議的方式獲取遠程點證書的副本;你可以讓遠程用戶email證書給你並放到U盤上,或者任何其他方式。
2. 從信任對象獲取服務器證書。(傳0下標給SecTrustGetCertificateAtIndex)
3. 獲取證書的數據。(SecCertificateCopyData)
4. 比較這個證書和步驟1獲取的證書數據;匹配,進行正確的連接。
自定義CA
如果服務器證書的CA不是系統信任的,你可以包含這個CA的根證書來處理這個問題。
1. 在程序中,包含這個CA根證書副本。
2. 一旦獲取信任對象,創建這個證書使用證書數據(SecCertificateCreateWithData)並設置這個證書爲信任錨點(SecTrustSetAnchorCertificates)。
3. SecTrustSetAnchorCertificates設置一個flags來阻止信任對象信任其它的錨點;如果你想信任系統的默認錨點,調用SecTrustSetAnchorCertificatesOnly來清楚flag。
4. 評估信任對象。
自簽名證書
這裏有各種原因使用自簽名證書。下面是通常的情況:
開發(Development)
在開發過程中使用自簽名證書有利於建立TLS基本服務器測試。這是有理由使用自簽名證書和關閉TLS服務器信任評估。
當使用自簽名證書進行開發,更好的方式是創建自己的CA並派發證書給測試服務器。你可以導入CA的根證書到APP或者每個測試者的系統都安裝這個CA的根證書。(使用Safari,Mail和配置描述文件(configuration profiles)在IOS,鑰匙串訪問在OS X)。這種方式的好處是不用關閉TLS服務器信任評估,也意味着你不用擔心在發佈環境下忘了打開TLS服務器信任評估。
• 證書助手(Certificate Assistant)- 這個APP已經內嵌在OS X中,它擁有友好的用戶界面和管理自己的CA。
• OpenSSL - OpenSSL命令行工具允許你創建和管理自己的CA。
商業原因
一些組織由於商業原因使用自簽名證書在生產環境的基礎措施。有可能是這個組織不願意從CA購買證書或者它有可夠獲取這樣的證書。
如果自簽名證書是可選的,那麼最好還是使用自己的CA。使用自己的CA比自簽名證書有以下好處:
• 服務器改變 - 如果服務器改變會破壞服務器信任評估,你的CA能夠派發新的證書來描述這個變化而且客服端會自動的信任它。例如,你改變服務器的DNS域名,新的證書包含新的DNS域名。
• 重新派發 - 如果服務器的證書過期,你的CA能重新派發。
• 撤銷 - 你的CA可以通過OCSP或者CRL協議來撤銷證書。
第三方服務器
你可以避免使用自簽名證書,但是如果使用第三方服務器,這個服務器使用自簽名證書;最好的辦法是讓他們使用信任的CA派發的證書。如果這不可能,那麼內嵌這個證書在APP中,使用適當的方法來信任這個證書。
信任異常
如果你構建通用目的應用(能廣泛連接各種服務器),在這種情況你需要通用的解決方案。
最好的通用方式是什麼都不做。這種默認的服務器信任評估有2個重要的好處:
• 容易實現。
• 安全。
最後一點很重要:如果發生服務器信任評估失敗,你提供用戶避免安全性的方式,用戶將會總是選擇它不管有多不安全。從安全性來看,最好是評估失敗並且讓用戶迫使服務器的管理者修復這個問題。
如果你選擇避免這個建議,你可以執行一些步驟來減少風險。
1. 嘗試連接服務器。
2. 如果服務器信任評估失敗(報告用戶這個問題)。
3. 如果用戶決定連接,記住這個決定並繼續這個連接。
4. 之後,如果再次遇到這個服務器信任失敗,避免這個問題並繼續連接。
在第4步,你怎麼確認是同樣的錯誤呢?
1. 用戶連接的這個服務器提供一個過期的證書。
2. 你鑑別這個錯誤並詢問用戶是否真的確認連接它。
3. 用戶同意,記住這個決定並連接它。
4. 之後可能進入一個不安全的網絡,再次連接一個冒充的服務器。
5. 你的程序連接了這個冒充的服務器,雖然檢測到服務器信任失敗,但是用戶同意連接它。
這個問題在你的程序是連接一個冒充的服務器,雖然用戶只是同意避免過期證書。
你可以使用信任異常來解決這個問題。當用戶同意連接這個服務器,在程序中你可以獲取信任對象的信任異常。這記錄了必要信息去避免當前信任評估失敗。在以後,如果你遇到這個的服務器的信任評估失敗,你可以設置這個異常給信任對象(SecTrustSetException)。如果解決了服務器信任評估失敗,可以安全地進行這個連接。如果不,這必須詢問用戶是否同意這個額外的信任異常。
強制執行更嚴格的信任評估
自定義服務器信任評估可能不滿滿足一些問題;你可以使用這種方式來使應用更加安全。如果你進行高級別安全編程,你可能不僅需要默認的服務器信任評估,還需要增加一些自定義檢查。
例如,你可能不僅是檢查服務器正式是否是信任的CA,而且檢查是否是指定的CA派發(這個技術是證書認證機構鎖定,ertificate authority pinning)。這很容易使用信任對象完成。這個步驟如下:
1. 包含這個CA根證書副本。
2. 一旦你有信任對象,創建證書使用這個證書的證書數據(SecCertificateCreateWithData)之後設置這個證書爲信任錨點(SecTrustSetAnchorCertificates)。
3. 評估信任對象。如果評估成功,服務器證書就是有效的而且是由這個指定的CA派發的。
CA鎖定只是一個例子說明怎樣強制執行更嚴格的信任評估。這裏有其他方式你可以考慮:
• 你可以實現證書鎖定(certificate pinning)。從服務器證書取出公鑰(SecTrustCopyPublicKey)。
• 你可以檢查證書的某些屬性值或者擴展是否存在。在OS X,使用SecCertificateCopyValues。
• SecTrustCopyResult讓你決定是否擴展驗證作爲信任評估的一部分。
• SecPolicyCreateRevocation讓你獲取安全政策用於檢查撤銷證書。
SecTrustEvaluate可能會阻塞
這裏有2個情形需要SecTrustEvaluate訪問網絡:
• 需要下載中間證書。
• 需要確定正式是否已經被撤銷。
這些網絡操作可能會有短暫的超時,但是SecTrustEvaluate任然不適合在主線程調用,特別在IOS。如果你需要在主線程調用SecTrustEvaluate方法,你有3個選項:
• 你可以使用SecTrustEvaluateAsync。
• 你可以使用SecTrustSetNetworkFetchAllowed來禁止信任對象訪問網絡。
• 你可以使用併發運行SecTrustEvaluate在另外的線程(GCD,NSOperation)。
調查難調試的信任評估失敗
有時候很難弄清楚爲什麼信任評估失敗。你先檢查是否是通用失敗,如果你任然不能找到失敗原因,你可以嘗試下面的方式:
• 打印SecTrustCopyResult的結果。
• 打印SecTrustCopyProperties的結果。
• 檢查信任異常數據(SecTrustCopyExceptions)。
警告:信任異常數據是用於調試用的,不能直接打印。
第3步返回的是二進制屬性列表文件,你可以保存爲.plist文件,之後用xcode打開。
展示證書
在一些情況下,展示證書給用戶可能是有用的。例如,需要手動確認服務器id標識。在OS X上可以調用高級的API:
• SFCertificateView是一個NSView,用於展示證書。
• SFCertificatePanel是一個面板展示一個或者多個證書。
通常,你應該調用高級的API,如果你需要展示自己的圖形界面,使用低級的API(SecCertificateCopyValues)。
IOS中是沒有高級的API用於展示證書,但是這不重要。因爲IOS限制獲取證書的細節。
展示信任結果
最好不要詢問用戶安全相關問題,因爲他們不是合格的回答者。如果你需要展示失敗的信任評估結果,在OS X中有高級別API(SFCertificateTrustPanel)。
IOS沒有相同的高級別API展示信任結果。