ONVIF專題--WS-Security

1 概述

本文檔中使用了下列名稱空間:

前綴

名稱空間

 

s

http://www.w3.org/2001/12/soap-envelope

soap根nm,定義soap中最基本Envelope、Header、Body、Fault等數據結構

ds

http://www.w3.org/2000/09/xmldsig#

xml簽名根nm,定義xml簽名的數據結構,

標準:[https://www.w3.org/TR/2002/REC-xmldsig-core-20020212/Overview.html ]

xenc

http://www.w3.org/2001/04/xmlenc#

xml加密根nm,

標準:[https://www.w3.org/2008/xmlsec/Drafts/xmlenc-core-11/]

m

http://schemas.xmlsoap.org/rp

從xsd文件來看,像是描述數據from和to的標準,版權屬於微軟

wsse

http://schemas.xmlsoap.org/ws/2002/04/secext

WS-Security的根nm(也是縮寫)

2 報文保護

2.1 數字簽名 和 安全證書:

基於公私鑰的數據加密技術,主要目的是防止數據傳輸過程中被冒充、被篡改、被非法截獲

是站在數據發送方的角度,保護數據

2.2 安全性令牌(token)

用戶調用服務器API,向服務器發送的一個可靠的驗證信息,用於服務器判斷是否爲用戶

所以技術的目的在於服務器認證請求發起者,減少傳統web請求場景下網絡上多次密碼交互引入的風險

3 安全性元素

3.1. UsernameToken 元素

在soap的報文頭中包含安全令性令牌,定義如下,令牌包含用戶名節點和可選密碼節點(wsse標準建議只有在使用安全的傳輸時才傳送該元素)

疑問:爲什麼UsernameToken需要Id屬性?

安全性令牌是服務端用來標記用戶的技術,wsse標準並沒有限制一個Username與Password的唯一對應關係,理論上是可以(甚至鼓勵)實現一個Username對應多種Password方式的。因此Username某些情況下不足以唯一標記一個安全性令牌,因此需要增加Id屬性,目的是唯一標記一個UsernameToken,另外從Id屬性的類型xsd:ID也能反應設置這個屬性的目的。

<xsd:element name="UsernameToken">

    <xsd:complexType>

        <xsd:sequence>

            <xsd:element ref="Username" />

            <xsd:element ref="Password" minOccurs="0" />

        </xsd:sequence>

        <xsd:attribute name="Id" type="xsd:ID" />

        <xsd:anyAttribute namespace="##other" />

    </xsd:complexType>

</xsd:element>

<xsd:element name="Username">

    <xsd:complexType>

        <xsd:simpleContent>

            <xsd:extension base="xsd:string">

                <xsd:anyAttribute namespace="##other" />

            </xsd:extension>

        </xsd:simpleContent>

    </xsd:complexType>

</xsd:element>

<xsd:element name="Password">

    <xsd:complexType>

        <xsd:simpleContent>

            <xsd:extension base="xsd:string">

                <xsd:attribute name="Type" type="xsd:QName" />

                <xsd:anyAttribute namespace="##other" />

            </xsd:extension>

        </xsd:simpleContent>

    </xsd:complexType>

</xsd:element>

PassWord節點的Type屬性可以有如下值

描述

wsse:PasswordText(缺省)

用戶名的實際密碼。

wsse:PasswordDigest

用戶名密碼摘要。值爲 UTF8 編碼的密碼的 base64 編碼的 SHA1 散列值。

示例:

<S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">

    <S:Header>

        ...

        <wsse:Security>

            <wsse:UsernameToken>

                <wsse:Username>Zoe</wsse:Username>

                <wsse:Password>ILoveDogs</wsse:Password>

            </wsse:UsernameToken>

        </wsse:Security>

        ...

    </S:Header>

    ...

</S:Envelope>

3.2 二進制安全性令牌

任何基於 XML 的安全性令牌都可以在 <Security> 報頭中指定。然而,二進制(例如 X.509證書和 Kerberos票據)或其它非 XML 格式都需要特殊的編碼格式進行包含。

一個二進制安全性令牌有兩個用於解釋自身的屬性。ValueType 屬性表明安全性令牌是什麼,比如說 Kerberos票據。EncodingType 表明安全性令牌如何被編碼,例如使用 Base64Binary。

BinarySecurityToken 元素定義二進制編碼的安全性令牌。編碼過程用 EncodingType 屬性指定,值類型和空間用 ValueType 屬性指定。

注意:ValueType屬性的類型xsd:QName表明類型定義在本xml作用域內

<xsd:element name="BinarySecurityToken">

    <xsd:annotation>

        <xsd:documentation>A security token that is encoded in binary</xsd:documentation>

    </xsd:annotation>

    <xsd:complexType>

        <xsd:simpleContent>

            <xsd:extension base="xsd:string">

                <xsd:attribute name="Id" type="xsd:ID" />

                <xsd:attribute name="ValueType" type="xsd:QName" />

                <xsd:attribute name="EncodingType" type="xsd:QName" />

                <xsd:anyAttribute namespace="##other" processContents="strict" />

            </xsd:extension>

        </xsd:simpleContent>

    </xsd:complexType>

</xsd:element>

ValueType取值

QName

描述

wsse:X509v3

X.509v3 證書

wsse:Kerberosv5TGT

Kerberos的 5.3.1 節中定義的 Kerberosv5 票據。這個 ValueType 在票據爲賦予票據的票據(ticket granting ticket,TGT)時使用。

wsse:Kerberosv5ST

Kerberos的 5.3.1 節中定義的 Kerberosv5 票據。這個 ValueType 在票據爲服務票據(service ticket,ST)時使用。

EncodingType取值

QName

描述

wsse:Base64Binary

XML Schema base 64 編碼

wsse:HexBinary

XML Schema十六進制編碼

示例:

<wsse:BinarySecurityToken xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext" Id="myToken" ValueType="wsse:X509v3" EncodingType="wsse:Base64Binary">

MIIEZzCCA9CgAwIBAgIQEmtJZc0...

</wsse:BinarySecurityToken>

注意:當在簽名中使用 <BinarySecurityToken> 時(也就是說從 <ds:Signature> 元素引用它),不允許對屬性或元素值中 QName 的名稱空間前綴進行非授權的替換。如果確實需要使用自有的屬性值,則需要聲明私有屬性的作用域,示例如下:

<wsse:BinarySecurityToken xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext" Id="myToken" ValueType="x:MyType" xmlns:x="http://fabrikam123.com/x" EncodingType="wsse:Base64Binary">

MIIEZzCCA9CgAwIBAgIQEmtJZc0...

</wsse:BinarySecurityToken>

3.3. SecurityTokenReference 元素

發送一組安全性令牌聲明。有時候這些聲明駐留在其它某些地方,需要接收的應用程序到指定的URL地址去獲取。<SecurityTokenReference> 元素提供了一種引用 安全性令牌的可擴展機制。

<SecurityTokenReference Id="...">

  <Reference URI="..."/>

</SecurityTokenReference>

示例:

<wsse:SecurityTokenReference xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">

  <wsse:Reference URI="http://www.fabrikam123.com/tokens/Zoe#X509token" />

</wsse:SecurityTokenReference>

注意:該元素還可以被用作 <ds:KeyInfo> 的一個直接子元素,用來表明從其它某些地方的安全性令牌檢索密鑰信息的暗示。在使用 XML 簽名和 XML 加密時,我們特別推薦將 <SecurityTokenReference> 元素放在 <ds:KeyInfo> 內來引用用於簽名或加密的 安全性令牌。

3.4 ds:KeyInfo

對於某些密鑰類型(如 X.509 證書)來說,<ds:KeyInfo> 元素(來自 XML 簽名)和 <BinarySecurityToken> 元素都可以用於傳送密鑰信息。<ds:KeyInfo> 元素慮及了不同密鑰類型和將來的擴展性(祕鑰檢索)。

然而,在本規範中,如果密鑰類型在 wsse規範第 4.2 節中很好地定義過,那麼使用 <BinarySecurityToken> 就是我們推薦用於傳送密鑰信息的方式。

示例:使用該元素獲取命名過的密鑰的過程

<ds:KeyInfo Id="..." xmlns:ds="http://www.w3.org/2000/09/xmldsig#">

 <ds:KeyName>CN=Hiroshi Maruyama, C=JP</ds:KeyName>

</ds:KeyInfo>

3.5 ds:Signature

消息發送方可能希望讓消息接收方能夠決定消息是否在傳輸過程中更改過,並驗證消息是由特定安全性令牌持有人發送的。

當 XML 簽名與 <SecurityTokenReference> 元素同時使用時,消息簽署人的安全性令牌可能被關聯,而安全性令牌聲明和消息之間會以應用程序估計的方式產生映射。

由於某些SOAP報頭的不穩定性,發送者絕不能使用 XML 簽名中定義的封裝的簽名轉換。相對,消息應該顯式包括要簽署的必要元素。類似地,發送方絕不能使用 XML 簽名中定義的封裝簽名。

本規範慮及多個簽名附加在消息中的情況,這時每個簽名都引用不同、甚至重疊的消息部分。這對於很多分佈式應用程序都是很重要的,在這些應用程序程序中,消息要經過多個處理階段。舉例來說,發送方可能提交一個包含 orderID 報頭的訂單。發送方簽署 orderID 報頭和請求的主體(訂單的內容)。當訂單處理子系統收到這個時,它可能向報頭插入一個 shippingID。發出訂單的子系統然後會簽署(最少)orderID 和 shippingID,可能還有請求主體。然後當運輸部門處理和交付該訂單後,可能會附加一個 shippedInfo 報頭。運輸部門將簽署(最少)shippedInfo 和 shippingID,可能還有請求主體,然後將消息轉發給記帳部門進行處理。記帳部門可以驗證簽名並決定訂單的有效信任鏈,以及各個角色所做的事情。

所有依從的實現都必須能夠處理 <ds:Signature> 元素。

4.5.1 算法

WS-Security 規範建立在 XML 簽名的基礎之上,因此具有與 XML 簽名規範中指定的相同的算法需求。

下面的表描述了 WS-Security 推薦的其它算法:

算法類型

算法

算法 URI

規範化

專用 XML 規範化,在簽名hash前用於去除空格和其他格式

http://www.w3.org/2001/10/xml-exc-c14n

轉換

XML 解密轉換(XML Decryption Transformation)

http://www.w3.org/2001/04/decrypt

專用 XML 規範化算法使用“預先存在的簽名”解決了一般規範化在名稱空間有漏洞時存在的缺陷。

最後,如果發送方希望在加密前簽署消息,他們應該使用 XML 簽名的解密轉換( Decryption Transformation for XML Signature)

4.5.2 簽署消息

<Security> 報頭塊用於在 SOAP信封中傳送符合 XML 簽名規範的簽名,爲了簽署 SOAP信封中的一個或多個元素。<Security> 報頭塊中的單獨的 SOAP信封中可以添加多個簽名條目。發送方應該注意簽署消息的所有重要元素,但一定要注意創建的策略不會簽署消息在傳送過程中可能被合理更改的部分。

SOAP應用程序必須滿足下面的條件:

  1. 應用程序必須能夠處理 XML 簽名規範中定義的所需元素。
  2. 要向 <Security> 報頭塊添加簽名,應該預先考慮與 XML 簽名規範一致的 <ds:Signature> 元素,下來纔是已有的 <Security> 報頭塊的內容。也就是說,新信息要在舊信息之前(優先)。簽名中包含的所有 <ds:Reference> 元素都應該引用包含它的 SOAP信封內(或附件中)的資源。

如 XML 簽名規範中所示, XPath過濾可以用於指定將簽署的對象。然而,因爲 SOAP消息交換模型允許中介體應用程序修改信封(如添加或刪除報頭塊), XPath過濾在消息傳遞之後並不總能得到相同對象。使用 XPath過濾時應該注意避免因爲這種修改導致後來的驗證失敗。

中介體應用程序修改的問題不僅僅在 XPath 處理中才會發生。由於規範化和 分類的原因,數字簽名是這種關係的特別脆弱的例子。如果消息處理整體要保持健壯,中介體必須注意轉換不會出現在數字簽名組件的範圍中。

鑑於和名稱空間有關的安全性注意事項,本規範強烈推薦您使用提供相同或更多保護的“ 專用 XML 規範化(Exclusive XML Canonicalization)”算法或其它標準化算法。

4.5.3 驗證完整性

如果發生下列情況,<Security> 報頭塊中 <ds:Signature> 條目的驗證就會失敗:

  1. 條目內容的句法不遵守本規範,或者
  2. 根據 XML 簽名的核心驗證,條目中包含的 簽名的驗證失敗,或者
  3. 應用自己的信任策略的應用程序因爲某種原因拒絕消息(例如, 簽名由非信任的密鑰創建—驗證前兩個步驟只會執行對 簽名加密的驗證)。

如果簽名驗證失敗,那麼應用程序可能會使用 第 6 節中定義的錯誤代碼向發送者報告失敗情況。

4.5.4 示例

下面的樣本消息舉例說明了完整性和安全性令牌的使用(一條完整的符合wsse標準的soap報文)。對於本示例,我們使用了假定的“RoutingTransform”,它選擇不變的路由報頭以及消息主體。

<?xml version="1.0" encoding="utf-8" ?>

<S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">

  <S:Header>

    <m:path xmlns:m="http://schemas.xmlsoap.org/rp">    <!--rp規範,標識路由信息-->

      <m:action>http://fabrikam123.com/getQuote</m:action>

      <m:to>http://fabrikam123.com/stocks</m:to>

      <m:from>mailto:[email protected]</m:from>

      <m:id>uuid:84b9f5d0-33fb-4a81-b02b-5b760641c1d6</m:id>

    </m:path>

    <wsse:Security>

      <wsse:BinarySecurityToken ValueType="wsse:X509v3" EncodingType="wsse:Base64Binary" Id="X509Token">

        MIIEZzCCA9CgAwIBAgIQEmtJZc0rqrKh5i...

      </wsse:BinarySecurityToken>

      <ds:Signature> <!--xml簽名-->

        <ds:SignedInfo>

          <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />

          <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />

          <ds:Reference>

            <ds:Transforms>

              <ds:Transform Algorithm="http://...#RoutingTransform" />

              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />

            </ds:Transforms>

            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />

            <ds:DigestValue>EULddytSo1...</ds:DigestValue>

          </ds:Reference>

        </ds:SignedInfo>

        <ds:SignatureValue>

          BL8jdfToEb1l/vXcMZNNjPOV...

        </ds:SignatureValue>

        <ds:KeyInfo>

          <wsse:SecurityTokenReference>

            <wsse:Reference URI="#X509Token" />

          </wsse:SecurityTokenReference>

        </ds:KeyInfo>

      </ds:Signature>

    </wsse:Security>

  </S:Header>

  <S:Body>

    <tru:StockSymbol xmlns:tru="http://fabrikam123.com/payloads">

      QQQ

    </tru:StockSymbol>

  </S:Body>

</S:Envelope>

4.6 子元素加密

本規範允許通過發送方和接收方共享的通用對稱密鑰或消息中帶有的加密形式的密鑰,對消息主體塊、報頭塊、任意這些子結構和附件的組合進行加密。簡單說就是不對整個xml加密,支隊部分敏感信息加密。

爲了實現這種靈活性,我們利用了 XML 加密(XML Encryption)標準。我們將特別描述如何在 <Security> 報頭塊中使用三個元素(下面列出的和 XML 加密中定義的)。當發送方或中介體使用 XML 加密對部分 SOAP消息加密時,它們會向 <Security> 報頭塊添加子元素。此外,加密方還必須預先考慮在 <Security> 報頭塊中使用子元素作爲應該對加密部分解密的目標接收方。組合加密部分消息和添加其中一個引用加密部分的子元素的過程以後就被稱爲 加密步驟。子元素應該有足夠信息,好讓接收方可以識別消息的那些部分要由接收方解密。

4.6.1 xenc:ReferenceList

在加密 SOAP消息內的元素或元素內容時,您可以使用 XML 加密的 <xenc:ReferenceList> 元素來創建加密部分的證明,它被表示爲信封內的 <xenc:EncryptedData> 元素。(注:意思是說<xenc:ReferenceList>用來聲明要加密的xml局部數據,而加密後的數據封裝在 <xenc:EncryptedData>中)這個加密步驟要加密的元素或元素內容必須根據 XML 加密由對應的 <xenc:EncryptedData> 替換。該加密步驟創建的所有 <xenc:EncryptedData> 元素都應該列在 <xenc:ReferenceList> 元素的 <xenc:DataReference> 元素中。

儘管在 XML 加密中,<xenc:ReferenceList> 最初被設計爲在 <xenc:EncryptedKey> 元素中使用(這表明所有被引用的 <xenc:EncryptedData> 元素都用同一個密鑰加密),本規範允許同一個 <xenc:ReferenceList> 引用的 <xenc:EncryptedData> 元素在不同步驟中加密。每個加密密鑰都可以在 <xenc:EncryptedData> 內的 <ds:KeyInfo> 中指定。

<xenc:ReferenceList> 子元素有用的典型情況是,發送方和接收方都使用共享的祕密密鑰。下面舉例說明了這個子元素的使用:

<S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">

  <S:Header>

    <wsse:Security>

      <xenc:ReferenceList>

        <xenc:DataReference URI="#bodyID" />

      </xenc:ReferenceList>

    </wsse:Security>

  </S:Header>

  <S:Body>

    <xenc:EncryptedData Id="bodyID">

      <ds:KeyInfo>

        <ds:KeyName>CN=Hiroshi Maruyama, C=JP</ds:KeyName>

      </ds:KeyInfo>

      <xenc:CipherData>

        <xenc:CipherValue>...</xenc:CipherValue>

      </xenc:CipherData>

    </xenc:EncryptedData>

  </S:Body>

</S:Envelope>

4.6.2 xenc:EncryptedKey

加密步驟涉及到使用密鑰(它接着會被接收方的密鑰加密並嵌入到消息中)加密 SOAP信封中的元素或元素內容時,就可以使 <xenc:EncryptedKey> 來傳送這種加密密鑰了。該子元素應該有一個證明(也就是 <xenc:ReferenceList> 元素),用來讓接收方瞭解要用這個密鑰(如果存在的話)解密的部分。要用這個加密步驟加密的元素或元素部分必須根據 XML 加密由對應的 <xenc:EncryptedData> 替換。所有這個步驟創建的 <xenc:EncryptedData> 元素都應該列在該子元素內的 <xenc:ReferenceList> 元素中。

這種構建方法在通過隨機生成的對稱密鑰(該密鑰接着由接收方的公共密鑰加密)完成加密時很有用。下面舉例說明了這個元素的使用:

<S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">

  <S:Header>

    <wsse:Security>

      <xenc:EncryptedKey>

        <xenc:EncryptionMethod Algorithm="..." />

        <ds:KeyInfo>

          <ds:KeyName>CN=Hiroshi Maruyama, C=JP</ds:KeyName>

        </ds:KeyInfo>

        <xenc:CipherData>

          <xenc:CipherValue>...</xenc:CipherValue> <!--直接發送祕鑰-->

        </xenc:CipherData>

        <xenc:ReferenceList>

          <xenc:DataReference URI="#bodyID" />

        </xenc:ReferenceList>

      </xenc:EncryptedKey>

    </wsse:Security>

  </S:Header>

  <S:Body>

    <xenc:EncryptedData Id="bodyID">

      <ds:KeyInfo>

        <ds:KeyName>CN=Hiroshi Maruyama, C=JP</ds:KeyName>

      </ds:KeyInfo>

      <xenc:CipherData>

        <xenc:CipherValue>...</xenc:CipherValue>

      </xenc:CipherData>

    </xenc:EncryptedData>

  </S:Body>

</S:Envelope>

4.6.3 xenc:EncryptedData

在某些情況下,有關安全性的信息是以完全加密的形式提供的,或者加密時非 XML 附件會被加密。 XML 加密的 <xenc:EncryptedData> 元素可以用在這種情況下。對加密附件的每個部分來說,都需要一個加密步驟;那就是,對於每個要加密的附件,都必須遵守下列規則添加一個 <xenc:EncryptedData> 子元素(請注意,步驟 2 到 4 只有在 MIME 類型由附件使用時才適用)。

  1. 附件的內容必須被加密八位串代替。
  2. 被替換的 MIME 部分的媒體類型必須是 application/octet-stream。
  3. 附件的原始媒體類型必須在 <xenc:EncryptedData> 元素的 MimeType 屬性中聲明。
  4. 加密的 MIME 部分必須由 <xenc:CipherReference> 元素引用,其中 URI 指向 MIME 部分,cid: 爲 URI 的模式組件。

下面舉例說明了使用該元素表明加密附件的方法:

<S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">

  <S:Header>

    <wsse:Security>

      <xenc:EncryptedData MimeType="image/png">

        <xenc:EncryptionMethod Algorithm="foo:bar" />

        <ds:KeyInfo>

          <ds:KeyName>CN=Hiroshi Maruyama, C=JP</ds:KeyName>

        </ds:KeyInfo>

        <xenc:CipherData>

          <xenc:CipherReference URI="cid:image" />

        </xenc:CipherData>

      </xenc:EncryptedData>

    </wsse:Security>

  </S:Header>

  <S:Body></S:Body>

</S:Envelope>

4.6.4. 處理規則

使用上述其中一種子元素對 SOAP消息加密的部分或附件必須符合 XML 加密規範。加密的 SOAP消息必須還是一個有效的 SOAP信封。消息的創建者絕不能加密 <S:Envelope><S:Header> <S:Body> 元素,但可以加密 <S:Header> <S:Body> 元素的子元素。如果它們的目標都是同一個接收方,那麼就可以向單獨的 <Security> 報頭塊添加多個步驟的加密。

當要加密 SOAP信封中的元素或元素內容(例如 <S:Body> 的內容)時,它必須根據 XML 加密 <xenc:EncryptedData> 替換,而且它應該從此加密步驟創建的 <xenc:ReferenceList> 元素引用。此規範允許在附件中存放加密八位流。舉例來說,如果 <S:Body> 元素內出現的 <xenc:EncryptedData> 有引用附件的 <xenc:CipherReference>,那麼解密八位流就替換 <xenc:EncryptedData>。然而,如果 <enc:EncryptedData> 的位置在 <Security> 報頭塊中,而它引用附件,那麼解密八位流就必須替換附件中的加密八位流。

注:簽名和加密的順序,一般是先簽名後加密,簽名驗證要求對解密後原文,這樣可以保證接收者既知道怎麼解密又防止信息篡改

加密

創建符合此規範的加密 SOAP消息的一般步驟(非標準化的)如下所示(請注意,我們推薦使用 <xenc:ReferenceList>)。

  1. 創建新的 SOAP信封。
  2. 根據加密類型,在 <Security> 報頭塊中創建 <xenc:ReferenceList> 子元素、<xenc:EncryptedKey> 子元素或 <xenc:EncryptedData> 子元素(請注意,SOAP “actor”和“mustUnderstand”屬性是否不同,不同就需要一個新的報頭表)。
  3. 定位要加密的數據項,也就是 XML 元素、目標 SOAP 信封中的元素內容和附件。
  4. 如下所示加密數據:對於目標 SOAP信封中的每個 XML 元素或元素內容來說,根據 XML 加密規範的處理規則進行加密。每個已選擇的原始元素或元素內容都由最後的 <xenc:EncryptedData> 元素刪除和替換。對附件來說,內容則必須由加密的密碼數據替換,如 章節 4.5.3.中所示。
  5. <xenc:EncryptedData> 元素中可選的 <ds:KeyInfo> 可以引用另一個 <ds:KeyInfo> 元素。請注意,如果加密是基於附加的安全性令牌的,那麼就應該向 <ds:KeyInfo> 元素添加一個 <SecurityTokenReference> 元素以便於定位它。
  6. 創建一個引用生成的 <xenc:EncryptedData> 元素的 <xenc:DataReference> 元素。向 <xenc:ReferenceList> 添加 <xenc:DataReference>。

解密

當收到帶有加密報頭條目的 SOAP信封時,對於每個加密報頭來說都應該進行下面的一般步驟(非標準的):

  1. 定位要解密的 <xenc:EncryptedData> 項(可能使用 <xenc:ReferenceList>)。
  2. 如下進行解密:對於目標 SOAP信封中的每個元素,根據 XML 加密規範的處理規則和上面列出的處理規則進行解密。
  3. 如果解密數據是附件的一部分而且使用了 MIME 類型,那麼將附件的 MIME 類型改爲原始 MIME 類型(如果存在)。
  4. 如果因爲某種原因解密失敗,應用程序就可以使用 第 6 節中定義的錯誤代碼向發送方報告失敗情況。

5 擴展示例

(001)<?xml version="1.0" encoding="utf-8" ?>

(002)<S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">

(003)  <S:Header>

(004)    <m:path xmlns:m="http://schemas.xmlsoap.org/rp/">

(005)      <m:action>http://fabrikam123.com/getQuote</m:action>

(006)      <m:to>http://fabrikam123.com/stocks</m:to>

(007)      <m:from>mailto:[email protected]</m:from>

(008)      <m:id>uuid:84b9f5d0-33fb-4a81-b02b-5b760641c1d6</m:id>

(009)    </m:path>

(010)    <wsse:Security>

(011)      <wsse:BinarySecurityToken ValueType="wsse:X509v3" Id="X509Token" EncodingType="wsse:Base64Binary">

(012)        MIIEZzCCA9CgAwIBAgIQEmtJZc0rqrKh5i...

(013)      </wsse:BinarySecurityToken>

(014)      <xenc:EncryptedKey>

(015)        <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />

(016)        <ds:KeyInfo>

(017)          <ds:KeyName>CN=Hiroshi Maruyama, C=JP</ds:KeyName>

(018)        </ds:KeyInfo>

(019)        <xenc:CipherData>

(020)          <xenc:CipherValue>

(021)            d2FpbmdvbGRfE0lm4byV0...

(022)          </xenc:CipherValue>

(023)        </xenc:CipherData>

(024)        <xenc:ReferenceList>

(025)          <xenc:DataReference URI="#enc1" />

(026)        </xenc:ReferenceList>

(027)      </xenc:EncryptedKey>

(028)      <ds:Signature>

(029)        <ds:SignedInfo>

(030)          <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />

(031)          <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />

(032)          <ds:Reference>

(033)            <ds:Transforms>

(034)              <ds:Transform Algorithm="http://...#RoutingTransform" />

(035)              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />

(036)            </ds:Transforms>

(037)            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />

(038)            <ds:DigestValue>

(039)              LyLsF094hPi4wPU...

(040)            </ds:DigestValue>

(041)          </ds:Reference>

(042)        </ds:SignedInfo>

(043)        <ds:SignatureValue>

(044)          Hp1ZkmFZ/2kQLXDJbchm5gK...

(045)        </ds:SignatureValue>

(046)        <ds:KeyInfo>

(047)          <wsse:SecurityTokenReference>

(048)            <wsse:Reference URI="#X509Token" />

(049)          </wsse:SecurityTokenReference>

(050)        </ds:KeyInfo>

(051)      </ds:Signature>

(052)    </wsse:Security>

(053)  </S:Header>

(054)  <S:Body>

(055)    <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" Id="enc1">

(056)      <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#3des-cbc" />

(057)      <xenc:CipherData>

(058)        <xenc:CipherValue>

(059)          d2FpbmdvbGRfE0lm4byV0...

(060)        </xenc:CipherValue>

(061)      </xenc:CipherData>

(062)    </xenc:EncryptedData>

(063)  </S:Body>

(064)</S:Envelope>

讓我們來回顧本示例中一些關密鑰的部分:

  • 行(003)到(053)包含 SOAP 消息報頭。
  • 行(004)到(009)指定 消息路由信息(如 WS-Routing 定義的)。在本示例中,我們發送消息到 http://fabrikam123.com/stocks 服務,請求“getQuote”操作。
  • 行(010)到(052)表示 <Security> 報頭塊。它包含消息的與安全性相關的信息。
  • 行(011)到(013)指定與消息關聯的安全性令牌。在本示例中,它指定按 Base64 編碼的 X.509證書。行(012)指定該證書的實際 Base64 編碼。
  • 行(014)到(027)指定用於加密消息主體的密鑰。因爲這是一個對稱密鑰,所以它是以加密形式傳送的。行(015)定義用於加密密鑰的算法。行(016)到(018)指定用於加密對稱密鑰的密鑰的名稱。行(019)到(022)指定對稱密鑰實際的加密形式。行(023)到(025)識別消息中使用該對稱密鑰的加密塊。在本示例中,它只用於加密消息主體(Id="enc1")。
  • 行(027)到(049)指定數字簽名。在本示例中,簽名是基於X.509證書的。行(028)到(040)表明簽署什麼。行(029)表明規範化算法(本示例中是排它的)。行(030)表明簽名算法(在本示例中是 sha1 上的 rsa)。
  • 行(032)到(041)標識正在被簽署的消息部分。行(033)特別標識"轉換"。這個假定的轉換將選擇路由報頭和消息主體不變的部分。行(034)指定行(033)所選擇的消息部分上要使用的規範化算法。行(036)表明規範化數據上的分類算法使用。行(037)指定規範化數據上的指定算法得出的分類值。
  • 行(043)到(045)表明實際的簽名值 — 在行(042)指定。
  • 行(053)到(050)表明用於簽名的密鑰。在本示例中,它是消息中包括的 X.509證書。行(046)提供對行(011)到(013)的 URI 鏈接。
  • 消息主體是由行(055)到(062)表示的。
  • 行(052)到(063)表示加密的元數據和使用 XML 加密的消息主體的形式。行(053)表明“元素值”將被替換,並標識加密。行(054)指定加密算法 — 在本示例中爲 Triple-DES。行(055)到(058)包含實際的密碼文本(也就是加密的結果)。請注意,我們不包括對密鑰的引用作爲引用加密的密鑰 — 行(024)。

6 錯誤碼

在很多情況下,處理安全性信息時都會出現 錯誤。例如:

  • 無效或不支持的安全性令牌、簽名或加密類型
  • 無效、非授權或不可授權的安全性令牌
  • 無效簽名
  • 解密失敗
  • 所引用的安全性令牌無法使用

這些錯誤可以分爲兩 類:不支持的和失敗的。

對於不支持的錯誤情況來說,接收者可以提供響應,告知發送者支持的格式等等。

對於失敗的錯誤來說,接收者可以選擇不響應,因爲這可以算是拒絕服務(Denial of Service,DOS)或加密攻擊的一種形式。

結合簽名和加密失敗來減少某些類型的攻擊。

如果失敗返回到發送者,那麼必須使用 SOAP的“錯誤(Fault)”機制來報告錯誤。

下面的表描述了預定義的安全性錯誤代碼。

錯誤的“不支持”類爲:

出現的錯誤

錯誤代碼

提供了不支持的令牌

wsse:UnsupportedSecurityToken

使用了不支持的簽名或加密算法

wsse:UnsupportedAlgorithm

錯誤的“失敗”類爲:

出現的錯誤

錯誤代碼

處理 <Security> 報頭時發現錯誤。

wsse:InvalidSecurity

提供了無效的安全性令牌

wsse:InvalidSecurityToken

安全性令牌無法被驗證或授權

wsse:FailedAuthentication

簽名或解密是無效的

wsse:FailedCheck

引用的安全性令牌無法檢索

wsse:SecurityTokenUnavailable

 

參考資料:

[1] w3c-xml schema
[2] "RELAX NG"--Eric van der Vlist
[3] ws-secure中翻譯
[4] xml-signature

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章