享受代码,享受人生

SOA is an integration solution. SOA is message oriented first.
The Key character of SOA is loosely coupled. SOA is enriched
by creating composite apps.
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

XML Encryption

Posted on 2006-04-16 09:47  idior  阅读(5804)  评论(7编辑  收藏  举报

利用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:    为了使用第三种方法,XML Encryption为KeyInfo加入的扩展元素。通过非对称密钥技术来传递对称密钥, 综合了两种的优点,前提是消息加密方需拥有消息接受方的公钥。下面是使用该方法的一个例子。
    AgreementMethod: 该元素使用key agreement protocol来获得密钥,极少使用故不做介绍。

<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那样在子元素中嵌套EncryptedKey或EncryptedData。
了解了这个特性,就可以避免在两段使用相同密钥加密的消息中重复包含一个复杂的EncryptedKey。利用ReferenceList元素可以在密钥中引用到使用该密钥的不同地方,避免重复。

<
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中也有类似的实现,示例如下:

<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. 根据以上信息将密文解密获得原始信息。

系列文章