ONVIF專題--XML-Encryption

利用XML Signature, 消息的完整性(Integrity)得到了保證。回顧之前提到的安全的三個基本概念: Integrity, Confidentiality, Authentication, 現在該考慮消息的機密性的問題。

雖然簽名可以保證消息在傳送的途中沒有被篡改,但是並不能避免它被偷取。如果消息沒有經過加密,那麼某個敏感的信息就會被泄漏。

與XML-Signature類似,結合了XML技術和傳統加密技術而產生的XML-Encryption,也並不僅僅是加密XML文件那麼簡單,它提供了以下的功能:

  1. 加密整個XML文件。
  2. 加密XML文件中的某個元素。
  3. 加密XML文件中某個元素的內容。
  4. 加密非XML格式的資源。(例如一張JPEG圖片)。
  5. 加密已經過加密的內容。

XML Encryption的結構如下所示:

<EncryptedData (Id)? (Type)? (MimeType)? (Encoding)?>

  (<EncryptionMethod/>)?

  (<ds:KeyInfo>

    (<ds:KeyName>)?

    (<ds:RetrievalMethod>)?

    (<ds:*>)?

    (<EncryptedKey>)?

    (<AgreementMethod>)?

  </ds:KeyInfo>)?

  <CipherData>

    (<CipherValue>)?

    (<CipherReference (URI)?>)?

  </CipherData>

  (<EncryptionProperties>)?

</EncryptedData>

注:
(x)? 代表x出現0-1次
(x)+ 代表x出現1-n次
(x)* 代表x出現0-n次

與XML Signature不同,XML Encryption更加體現了自包含的性質,它不象XML-Signature通過引用對某個資源簽名,而是在原資源的位置上創建一個新的EncryptedData元素完全的替代原資源(使用CipherReference除外)。也是因爲這個原因,你不可能象XML-Signature那樣在一個Signature元素中對多個資源簽名,有幾個需要加密的資源就有幾個EncryptedData元素替代它們

EncryptedData元素是原資源經過XML-Encryption作用後的結果,將替代原資源。Type屬性有兩個合法值: element, content. 它們用於區別是否加密tag(標籤)。如果Type設爲element將加密整個元素包括tag在內, 而設爲content時只對元素中的內容加密

EncryptionMethod元素指定加密將使用的算法

CipherData元素中的內容爲原資源加密後的結果,可以用兩種形式表示,通常使用CipherValue,而CipherReference類似於XML Signature的Reference元素,往往用於對外部資源(jpeg文件)的加密。

EncryptionProperties元素用於爲加密的數據添加一些額外的信息,比如加密發生的時間。

KeyInfo元素描述加密所使用的密鑰。這裏的KeyInfo是借用的XML-Signature下的KeyInfo元素。在簽名的時候,大多使用非對稱密鑰,即利用私鑰產生簽名,然後將公鑰信息放在KeyInfo元素中,這樣消息的接受方就可以直接使用公鑰來驗證簽名。但是在加密的時候,通常使用的是對稱密鑰,如果此時把密鑰的信息直接放在KeyInfo中顯然是不安全的。

此時有以下幾種方法:

  1. 不使用KeyInfo元素,假定消息交換已經約定好了加密使用的密鑰。
  2. 在KeyInfo中指定一個標識(Identity),假定消息接受方已經擁有了解密所需的密鑰,通過這個標識,消息接受方接可以定位到此次解密所需要的密鑰。
  3. 使用消息接受方的公鑰加密此次加密消息所使用的對稱密鑰,消息接受方利用自己唯一擁有的私鑰解密出加密消息使用的密鑰。
  4. 通過key agreement protocol獲得密鑰(較少使用)。

基於以上幾種方法,下面對KeyInfo元素做具體介紹:

KeyName: 方法2中的一種形式,通過指定一個標識來獲得解密所需的密鑰。

RetrievalMethod: 方法2中的另一種形式,通過一個URI指向解密所需的密鑰, 比如指向信息中另一段被加密的內容,而那段內容可以方便的被解密。

EncryptedKey: 爲了使用第3種方法,XML Encryption爲KeyInfo加入的擴展元素。通過非對稱密鑰技術來傳遞對稱密鑰,綜合了兩種的優點,前提是消息加密方需擁有消息接受方的公鑰。下面是使用該方法的一個例子。

AgreementMethod: 該元素使用key agreement protocol來獲得密鑰,極少使用故不做介紹。

示例1:

<EncryptedData>

  <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />

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

    <EncryptedKey>

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

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

        <ds:X509Data>

          <ds:X509SubjectName>

            o=MyCompany,ou=Engineering,cn=Dave Remy

          </ds:X509SubjectName>

        </ds:X509Data>

      </ds:KeyInfo>

      <CipherData>

        <CipherValue>...</CipherValue>

      </CipherData>

    </EncryptedKey>

  </ds:KeyInfo>

  <CipherData>

    <CipherValue>...</CipherValue>

  </CipherData>

</EncryptedData>

從上面的例子中可以看出EncryptedKey 和EncryptedData 具有類似的結構,其實它們本來就是同一類型(EncryptedType),一個用於加密數據,一個用於加密密鑰(密鑰就是一種特殊的數據)。它們之間的關係就象面向對象中的sub class和abstract class。

EncryptedKey和EncryptedData是EncryptedType的子類,而EncryptedType是不能具體存在的。因此EncryptedKey可以獨立於EncryptedData存在,甚至EncryptedKey還可以象EncryptedData那樣在子元素中嵌套EncryptedKeyEncryptedData

瞭解了這個特性,就可以避免在兩段使用相同密鑰加密的消息中重複包含一個複雜的EncryptedKey。利用ReferenceList元素可以在密鑰中引用到使用該密鑰的不同地方,避免重複,如示例2。

示例2:

<Employee>

  <Name>Dave Remy</Name>

  <SocialSecurityNumber>

    <EncryptedData id="socsecnum" Type="http://www.w3.org/2000/09/xmldsig#content">

      <EncryptionMethod Algorithm="..." />

      <CipherData>

        <CipherValue>...</CipherValue>

      </CipherData>

    </EncryptedData>

  </SocialSecurityNumber>

  <Salary>

    <EncryptedData id="salary" Type="http://www.w3.org/2000/09/xmldsig#content">

      <EncryptionMethod Algorithm="..." />

      <CipherData>

        <CipherValue>...</CipherValue>

      </CipherData>

    </EncryptedData>

  </Salary>

  <EncryptedKey>

    <EncryptionMethod Algorithm="..."/>

    <CipherData>

      <CipherValue>...</CipherValue>

    </CipherData>

    <ReferenceList>

      <DataReference URI="#socsecnum"/>

      <DataReference URI="#salary" />

    </ReferenceList>

  </EncryptedKey>

</Employee>

通過以上方法,可以通過EncryptedKey中的ReferenceList定位到使用該密鑰的不同信息段,但是這是一個單向引用,爲了增加可讀性,以及方便XML Encryption Processor處理還可以通過CarriedKeyName元素來實現雙向引用,在WS-Security中也有類似的實現,如示例3:

示例3:

<Employee>

  <Name>Dave Remy</Name>

  <SocialSecurityNumber>

    <EncryptedData id="socsecnum" Type="http://www.w3.org/2000/09/xmldsig#content">

      <KeyInfo>

        <KeyName>Jothy Rosenberg</KeyName>

      </KeyInfo>

      <EncryptionMethod Algorithm="..." />

      <CipherData>

        <CipherValue>...</CipherValue>

      </CipherData>

    </EncryptedData>

  </SocialSecurityNumber>

  <Salary>

    <EncryptedData id="salary" Type="http://www.w3.org/2000/09/xmldsig#content">

      <EncryptionMethod Algorithm="..." />

      <CipherData>

        <CipherValue>...</CipherValue>

      </CipherData>

    </EncryptedData>

  </Salary>

  <EncryptedKey>

    <EncryptionMethod Algorithm="..." />

    <CipherData>

      <CipherValue>...</CipherValue>

    </CipherData>

    <ReferenceList>

      <DataReference URI="#socsecnum" />

      <DataReference URI="#salary" />

    </ReferenceList>

    <CarriedKeyName>Jothy Rosenberg</CarriedKeyName>

  </EncryptedKey>

</Employee>

與XML-Signature相比而言,XML-Encryption的創建(加密)和驗證(解密)過程要簡單的多。

簡要步驟如下:

加密過程:

1.選擇一個加密算法
2.選擇一個加密用的密鑰,如果需要將密鑰的有關信息展示給消息接受方。
3.在加密前,將待加密的資源轉換爲字符流的格式。
4.使用選擇的密鑰和算法加密經過串行化的原始消息。
5.設置加密的類型(Content還是Element?)。
6.根據結果和以上的選項創建出EncryptedData元素,替代原來的資源。

解密過程:

1.將CipherValue元素的內容抽取出來。
2.從EncryptionMethod的Algorithm中獲得加密所用的算法。
3.獲得加密的類型(Content還是Element?)。
4.通過KeyInfo中的信息取得密鑰。
5.根據以上信息將密文解密獲得原始信息。

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