X.509Token

BinarySecurityToken

在WS-Security規範出現之前,針對Web Service或者其他的分佈式技術並不是沒有安全協議來保證它們的安全。只是這些協議一旦跨越了企業邊界往往會受到防火牆的影響,而不再起作用。在WS-Security中,並沒有拋棄這些現有的協議,而是將這些Binary的Security Token通過Encoding的方式集成到XML元素中,從而在Web Service中仍然能使用這些經典的安全協議,並利用SOAP消息穿越防火牆的特性,使它們適用於新的環境。這類Security Token在WS-Security中被稱爲BinarySecurityToken,目前僅支持X509v3 Certificate和Kerberos兩種,但是利用XML的高度擴展性,用戶可以定義自己的BinarySecurityToken。
 
下面是BinarySecurityToken的標準格式:
<wsse:BinarySecurityToken wsu:Id=...
        EncodingType=...
        ValueType=...>
      ...Binary Data ...
<wsse:BinarySecurityToken/>
其中EncodingType屬性指定將Binary數據Encoding到XML中的方法(常用Base64); ValueType屬性指定BinarySecurityToken的類型(比如X509v3); 元素內容則是經過Encoding的BinaryToken的內容。       

    
Note  Binary數據要嵌入XML時需要經過Encoding,因爲其中的某些內容可能不符合XML的語法。
    


X.509Token


使用X.509 Token來保證消息安全在介紹UsernameToken的文章最後已經提到。如果把UsernameToken從那個例子中去除,就變成了WSE中已經實現了的AnonymousForCertificate。
下圖就是AnonymousForCertificate對SOAP Envelop的擴展結構。


       
 
可以看出它和UsernameForCertificate非常相似,僅僅缺少了被加密的UsernameToken元素. 這點也正如它的名字所描述的一致,即使用這種方式的用戶對於Service來說是匿名的,也就沒有用戶鑑別的概念. 這恰好適用於那些僅僅需要保證消息安全而不需要驗證用戶身份的應用. 在介紹UsernameForCertificate的時候,並沒有詳細說明對X509Certificate Token的引用, 這裏做一些補充. 先來回顧一下之前在是如何引用X509Certificate Token. 從示意圖上我們也可以看出X509Certificate Token並沒有象UsernameToken那樣被包含在Request Security Head中, 爲什麼? 原因很簡單, 因爲這裏的X509證書並不是Client自己的證書,而是Service的證書(根據對稱密鑰的原理,加密需要使用消息接受方的公鑰). 以下是採用KeyIdentifier來引用Service的證書的方式.

<xenc:EncryptedKey wsu:id="userSysmetricKey">
              …            
     <ds:KeyInfo>
          <wsse:SecurityTokenReference>
                <wsse:KeyIdentifier 
                     ValueType="...oasis-wss-soap-message-security-1.1#ThumbPrintSHA1">
                         LKiQ/CmFrJDJqCLFcjlhIsmZ/+0=
                </wsse:KeyIdentifier>
         </wsse:SecurityTokenReference>
     </ds:KeyInfo>
              …
</xenc:EncryptedKey>

對於這種使用消息接受方X509證書加密的應用場景, 在WS-Security1.1規範中還定義了另一種引用證書的方法---X509IssuerSerial.

<xenc:EncryptedKey wsu:id="userSysmetricKey">
              …            
     <ds:KeyInfo>
       <wsse:SecurityTokenReference>
         <ds:X509Data>
            <ds:X509IssuerSerial>
               <ds:X509IssuerName>
                  DC=ACMECorp, DC=com
               </ds:X509IssuerName>
               <ds:X509SerialNumber>12345678</ds:X509SerialNumber>
            </ds:X509IssuerSerial>
         </ds:X509Data>
       </wsse:SecurityTokenReference>
    </ds:KeyInfo>
         ….
</xenc:EncryptedKey>

使用AnonymousForCertificate的方法最大的缺陷就是無法實現用戶的身份鑑別, 然而在大多數的應用中這個功能是不可豁缺的. 使用UsernameForCertificate可以達到鑑別用戶身份的目的, 不過它一般用於保證個人用戶和企業之間的安全. 而企業與企業之間常採用X509證書來達到互相的信任.一方面因爲使用X509證書的安全性要高於Username&Password, 另一方面從現實的角度你不可能爲每個企業分配一個用戶名密碼. 於是就會在SOAP Head中出現兩個X509證書, 從而實現相互認證. 這也是WSE中MutualCertificate所要實現的功能.

在採用兩個X509證書來實現相互認證中, 比AnonymousForCertificate方式多出了用戶的X509證書. 而加入它的原因就是要利用用戶的私鑰來簽名消息, 從而讓Service通過證書來鑑別用戶的身份.下圖就是MutualCertificate11對SOAP Envelop的擴展結構。

  
NoteMutualCertificate11其中的11表示採用了WS-Security1.1規範,在這裏主要用到1.1中對稱密鑰做簽名的特性, 如果直接使用非對稱密鑰對消息部分做簽名的話僅僅使用WS-Security1.0規範就可以了, WSE中的MutualCertificate10就支持這種方式,雖然採用1.0規範可以獲得更好的通用性,但是用非對稱密鑰簽名比對稱密鑰效率要低很多.


      


從中可以看出變化比較小,僅僅多出了一個用戶X509 Certificate,並用它對原來的ds:Signature元素做了一次簽名. 對應這副圖的Soap Envelop如下:

<?xml version="1.0" encoding="utf-8"?>
<
SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2001/12/soap-envelope"
   
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
   
xmlns:xenc="http://www.w3.org/2001/04/xmlenc"
   
xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility">
    <
SOAP-ENV:Header>
        <
wsse:Security
            xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/secext">
            
<wsse:BinarySecurityToken
                     
wsu:Id="userX509Cert"
                     
ValueType="…#X509v3"
                     
EncodingType="…#Base64Binary">
                         MIIEZzCCA9CgAwIBAgIQEmtJZc0…
               </
wsse:BinarySecurityToken>
             <xenc:EncryptedKey wsu:id="userSysmetricKey">
                <
xenc:EncryptionMethod
                    Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
                 <
ds:KeyInfo>
                       <
wsse:SecurityTokenReference>
                           <
wsse:KeyIdentifier 
                              
ValueType="...oasis-wss-soap-message-security-1.1#ThumbPrintSHA1">
                               LKiQ/CmFrJDJqCLFcjlhIsmZ/+0=
                           </
wsse:KeyIdentifier>
                       </
wsse:SecurityTokenReference>
                </
ds:KeyInfo>
                <
xenc:CipherData>
                    <
xenc:CipherValue>G2wDCq24FsgBGerE...</xenc:CipherValue>
                </
xenc:CipherData>
                <
xenc:ReferenceList>
                    <
xenc:DataReference URI="#DiscountResponse"/>
                </
xenc:ReferenceList>
            </
xenc:EncryptedKey>
            <
ds:Signature wsu:id="originSignature">
                <
ds:SignedInfo>
                    <
ds:CanonicalizationMethod
                        Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                    <
ds:SignatureMethod
                        Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"/>
                    <
ds:Reference URI="#DiscountedBookingForPartnersResponse">
                        <
ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                        <
ds:DigestValue>JwFsd3eQc0iXlJm5PkLh7...</ds:DigestValue>
                    </
ds:Reference>
                </
ds:SignedInfo>
                <
ds:SignatureValue>BSxlJbSiFdm5Plhk...</ds:SignatureValue>
                <
ds:KeyInfo>                  
                    <
wsse:SecurityTokenReference>
                         <
wsse:Reference URI="#userSysmetricKey"
                          
ValueType="...oasis-wss-soap-message-security-1.1#EncryptedKey"/>
                    </
wsse:SecurityTokenReference>
                </
ds:KeyInfo>
            </
ds:Signature>
       
     <ds:Signature>
                   <
ds:SignedInfo>
                         ...                  
                         
<ds:Reference URI="#originSignature">
                                 <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                                 <
ds:DigestValue>FeGre4lWv1lY2Kn4LJkg9...</ds:DigestValue>
                          </
ds:Reference>
                   </
ds:SignedInfo>
                   <
ds:SignatureValue>ADfkTeYsGen5Re4L...</ds:SignatureValue>
                  
<ds:KeyInfo>                  
                          <
wsse:SecurityTokenReference>
                                  <
wsse:Reference URI="#userX509Cert"
                          </
wsse:SecurityTokenReference>
                   </
ds:KeyInfo>
            </ds:Signature>
        </wsse:Security>
    </
SOAP-ENV:Header>
    <
SOAP-ENV:Body wsu:Id="DiscountedBookingForPartnersResponse">
        <
s:GetSpecialDiscountedBookingForPartnersResponse
            xmlns:s="http://www.MyHotel.com/partnerservice ">
            <
xenc:EncryptedData
                wsu:Id="DiscountResponse"
               
type="http://www.w3.org/2001/04/xmlenc#Element">
                <
xenc:EncryptionMethod
                    Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc "/>
                <
CipherData>
                    <
CipherValue>XD6sFa0DrWsHdehrHdhcW0x...</CipherValue>
                </
CipherData>
            </
xenc:EncryptedData>
        </
s:GetSpecialDiscountedBookingForPartnersResponse>
    </
SOAP-ENV:Body>
</
SOAP-ENV:Envelope>

和加密引用證書一樣, 在WS-Security1.1中爲簽名也定義了3種引用方式.第一種就是上述的引用BinarySecurityToken. 第二種同加密所用的第二種方法一樣採用X509IssuerSerial.第三種是KeyIdentifier, 只不過與加密所用的KeyIdentifier的類型不同,下面是使用KeyIdentifier做簽名的引用的示例:

<ds:Signature    
            …
     <ds:KeyInfo>
           <wsse:SecurityTokenReference>
                <wsse:KeyIdentifier EncodingType="...#Base64Binary"
                          ValueType="...#X509SubjectKeyIdentifier">
                            MIGfMa0GCSq…
                </wsse:KeyIdentifier>
           </wsse:SecurityTokenReference>
      </ds:KeyInfo>
</ds:Signature>


     
Note
看到如此多的引用方式,讀者可能會對此產生一些疑惑。主要可能會有如下三個問題:
1. 爲什麼要支持如此多的引用方式?
2. 爲什麼加密不支持引用BinarySecurityToken的方式?
3. 爲什麼同爲KeyIdentifier方式, 在加密和簽名中信息的類型卻不同?

在解答以上疑問之前,首先需要明白WS-Security中使用X509Token和SSL有一點不同的就是: SSL中Server端的X509證書用戶能夠在協議中動態的獲得,而WS-Security中使用X509Token卻需要用戶在消息傳遞前獲得Server端得X509證書(靜態方式)。在瞭解了這個前提後,讓我們依次解答上述得問題。

1. 雖然表面看來有3種引用方式,實際上可以分爲包含式和標識式。所謂包含式就是將X509證書包含到消息中,然後引用包含它的XML元素(引用BinarySecurityToken就是此種方式)。而標識式並不將X509證書包含到消息中,僅僅包含某些屬性從而讓消息的發送方和接受方能夠通過它們在本地的證書庫中定位到相應的證書。以上兩種方式各自有其應用場景。當我們利用Server的證書加密消息的時候自然會使用標識式,因爲Server端顯然保存有自己的證書,能夠通過標識定位到相應的證書就足夠了。 而當用戶使用與自己證書對應的私鑰簽名消息的時候,自然希望能同時將自己的證書傳送給消息的接受方(Server),以便它利用證書的公鑰驗證簽名,此時就會採用了包含式的引用。當然如果Server端已經獲得了用戶的證書並保存到本地(比如通過第一次包含式的消息傳遞後),自然也可以使用標識式引用。
2. 由於加密使用的是Server的證書,用戶顯然沒必要採用包含式的引用向證書的擁有者傳遞證書。
3. 同樣是因爲簽名和加密所使用的證書的擁有者不同的原因。簽名使用的是用戶的證書,所以需要傳遞完整的信息,以方便Server去其他地方查找。而加密使用的是Server的證書,server端本地已經擁有該證書,只需要定位到即可,所以利用摘要(SHA)一方面可以減少數據傳輸量,另一方面可以增強安全性。


同時使用Client和Service的X509證書, 可以在保證消息安全的同時實現Client與Service的身份鑑別. 與UsernameForCertificate用於個人與企業之間的安全不同的是MutualCertificate通常用於保障企業與企業之間的安全.

應用場景:
B2B供應鏈, 在物資需求方的企業內部使用Kerberos協議來保障個人或各個部門的安全, 而在物資需求方和供應方之間採用X509 Certification.
       
      


參考資料:
OASIS X509 Token Profile 1.1
Protect Your Web Services Through The Extensible Policy Framework In WSE 3.0
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章