【WCF安全】WCF X.509 證書雙向認證

摘要:【WCF安全】WCF X.509 證書雙向認證

 

一、SSL運作原理

 

a. Client端(Browser…)向Server端請求,發送相應Client端支持加密算法列表,Server會根據提供的算法列表選擇最佳的算法。

b. Server端發送最佳算法與證書給Client端。

c. Client端通過第三方CA證書來確認Server端身分。如信任則成功生成一隨機數作為(Session Key),也成為工作階段金鑰

d.Session Key緩存在Client端,然後Client利用Server端發送的證書中的公鑰(Public Key)加密Session Key放送到Sever端。

e. Server端接收加密後的Session Key 通過自己擁有的私鑰(Private Key)解密而得到Session Key.

f. 雙方通過Session Key對稱加密來傳輸信息。

 

所以SSL的終極目標就是使用對稱密鑰

 

 

二、WCF 安全模式

 

         WCF綁定,默認是Message安全模式,也就是消息安全,遵守的規範為WS-Security,與SSL運作原理一樣,密鑰交換與協商期間為非對稱加密

如果雙方擁有對稱密鑰後,後續採用的是對稱加密。但區別在於它是對SOAP進行加密,也就是應用層加密(Message,而非SSL傳輸層加密(Transport)

 

 

三、WCF 具體實現

 

a. 建立X.509根證書(自簽)

         先通過makecert命令生成根節點證書如下:

 

makecert -n "CN=WCFRootCA"-a sha1 -len 2048 -r-sv WCFRootCA.pvk WCFRootCA.cer .

 

命令詳解ref:http://msdn.microsoft.com/zh-cn/library/bfsktky3(v=vs.80).aspx

-n 代表輸出的X.509證書的名稱

-a 使用的加密算法

-len 公鑰的長度.(Defult:1024,長度增加加密程度越高,但效率越慢)

         -r 自簽標記

         -sv 指定pvkfile

 

根節點證書需要放置在Server端與Client端的Trusted Root Certification Authorities位置中.讓雙方系統信任WCFRootCA發出的證書.

 

b. 建立服務端證書

 

makecert -sk WCF -iv WCFRootCA.pvk -n "CN=WCFServer" -a sha1 -len 2048 -ic WCFRootCA.cer

-srlocalmachine -ss my -sky exchange -pe WCFServer.cer

 

         參數詳解:

         -sk 密鑰容器位置,該位置包含私鑰,如果容器不存在,則創建一個.

         -iv 頒發者私鑰文件

         -ic 頒發者證書文件

         -sr 證書安裝位置(Default: CurrentUser)

         -ss 主題的存儲名稱,輸出的證書存儲在此處.

         -sky 主題的密鑰類型,是簽章類型(signature, 2)或交換類型(exchange,1)

         -pe 生成的私鑰標記為可導出,這樣可以把私鑰包含在證書中.

 

         Server端外部程序應有訪問此證書私鑰的權限.

         Client端安裝此證書,為了安全性考量,不要給客戶端私鑰. 憑證安裝時要包含私鑰,用於解密.

 

c. 建立客戶端證書

 

makecert -sk WCF -iv WCFRootCA.pvk -n "CN=WCFClient" -asha1 -len 2048 -ic WCFRootCA.cer

-srlocalmachine -ss my -sky exchange-pe WCFClient.cer

 

         此命令應該在客戶端生成.

         Client端安裝此證書,為了安全性考量,客戶端不要洩露私鑰.憑證安裝時要包含私鑰,用於解密.

 

 

 

綜上所述,總而言之. WCFServer證書與WCFClient證書應該注意私鑰管理問題.

 

d. Server端WCF Config配置內容

 

<system.serviceModel>

    <services>

      <service name="SelfHostingTest.HelloWorldService" behaviorConfiguration="beh1">

        <endpoint address="" contract="SelfHostingTest.IHelloWorldService" binding="wsHttpBinding" bindingConfiguration="binding1">

          <identity>

            <!-- 服務端X509證書的Subject Name-->

            <dns value="WCFServer"/>

          </identity>

        </endpoint>

        <!--<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />-->

        <host>

          <baseAddresses>

            <add baseAddress="http://server:8003/hello.svc"/>

          </baseAddresses>

        </host>

      </service>

    </services>

    <behaviors>

      <!-- 設置Server端-->

      <serviceBehaviors>

        <behavior name="beh1">

          <serviceDebug includeExceptionDetailInFaults="true"/>

          <serviceMetadata httpGetEnabled="true"/>

          <serviceCredentials>

            <clientCertificate>

              <!—

1. 這是默認的驗證客戶端證書.似乎有一個缺點,多個客戶端只能用同一個Client端證書.這會喪失認證的意義.如

              不通過證書來識別客戶端,Server可以通過用戶名與密碼方式來識別客戶端.

                            2.CertificateValidationMode設定為PeerOrChainTrust,默認為ChainTrust.默認認證模式要求服務證書的頒發機構鏈必須在客戶端的”受信任根證書頒發機構”,

,雖然我們已經加入到客戶端的(Trusted Root Certification Authorities),但由於是使用CA根證書是Makecert創建,即使導入到相應存儲區但依然會造成無法通過驗證.

3. 對與WCF 成品交付,為了交易安全,一定需要一個真正的第三方CA證書,而不是自己創建的憑證.認證模式要改為ChainTrust

 

參考: 1. 為何要設定為PeerOrChainTrust.  http://www.cnblogs.com/artech/archive/2011/05/29/Authentication_041.html

         2. 參數代表的意義http://msdn.microsoft.com/zh-cn/library/system.servicemodel.security.x509certificatevalidationmode.aspx

         3. 自簽憑證的安全隱患http://www.wosign.hk/FAQ/selfsigned_SSL_insecure.htm

              -->

              <!--<certificate findValue="WCFClient" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>-->

              <!--<authentication revocationMode="NoCheck" certificateValidationMode="PeerOrChainTrust" />-->

            

              <!-- 2. 以下是通過Validator識別客戶端證書,個人認為可以一個Server端對多個Client端證書-->

              <authentication certificateValidationMode="Custom" customCertificateValidatorType="CertificateValidator.MyX509Validator,CertificateValidator" revocationMode="Online"/>

            </clientCertificate>

 

            <serviceCertificate findValue="WCFServer" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>

            <issuedTokenAuthentication allowUntrustedRsaIssuers="true"/>

          </serviceCredentials>

        </behavior>

      </serviceBehaviors>

    </behaviors>

    <bindings>

      <wsHttpBinding>

        <binding name="binding1">

          <security mode="Message">

            <transport clientCredentialType="None"/>

            <!--security mode of certificate -->

            <message negotiateServiceCredential="true" establishSecurityContext="true" clientCredentialType="Certificate"/>

          </security>

        </binding>

      </wsHttpBinding>

    </bindings>

  </system.serviceModel>

 

 

d. Client端配置內容

         由於Client端的Config是系統自動生成,但生成的配置文件中沒有生成behaviors 的配置,所以通過代碼控制時最優方案.如下:

 

DimobjService = New MyService.HelloWorldServiceClient()

 

        '1. Set client Certificate

        objService.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, _

                                                                      StoreName.My, _

                                                                      X509FindType.FindBySubjectName, _

                                                                      "WCFClient")

        ' 不對此證書執行吊銷檢查.

        objService.ClientCredentials.ServiceCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck

' 基於以上同樣的理由,我們必須設定為:PeerOrChainTrust.

objService.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode =          

ServiceModel.Security.X509CertificateValidationMode.PeerOrChainTrust

 

        '2. Set Server Certificate

        ' if negotiateServiceCredential property set false, we must set Server Certificate

        objService.ClientCredentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine, _

                                                                               StoreName.TrustedPeople, _

                                                                                X509FindType.FindBySubjectName, _

                                                                                "WCFServer")

 

        Dim Result = objService.SayHello("Magic")

 

e. 其他

         1. 證書的存放位置,要根據系統的運行環境來決定,Server端都放置與LocalMachine中,因為其不依賴與某個登錄的用戶.Client端如果是普通的WinForm(依賴於WINDOWS登錄用戶)可以考慮把客戶端證書放置在CurrentUser中. 客戶端存放的Server的憑證最好放置最好在信任的用戶中(TrustedPeople),


人生到處知何似
應似飛鴻踏雪泥