探索 XML 加密,第 1 部分

演示结构化数据的安全交换

级别: 初级

Bilal Siddiqui, CEO

2002 3 01

XML 加密为需要结构化数据安全交换的应用程序提供了一种端到端安全性。XML 本身是对数据进行结构化最流行的技术,因此基于 XML 的加密成为处理数据互换应用程序中安全性的复杂需求的方法。在这个两部分系列的第 1 部分中,Bilal 解释了打算如何将 XML 和安全性集成到 W3C XML 加密工作草案中。

当前,传输层安全性(Transport Layer Security(TLS))是因特网上安全通信的事实标准。TLS 是继著名的安全套接字层(SSL)之后的端到端安全性协议。SSL 最初是由 Netscape 设计的,而且,之后国际工程任务小组(Internet Engineering Task Force (IETF))改编了它的 3.0 版本,同时他们还在设计 TLS。这是一个非常安全和可靠的协议,它提供了通信双方之间的端到端安全性会话。XML 加密(XML Encryption)无意替换或取代 SSL/TLS。相反,它提供了用于 SSL 未涵盖的安全性需求的机制。以下是两个 SSL 未涉及的重要领域:

·                     加密交换数据的一部分

·                     多方(不止两方)之间的安全会话

使用 XML 加密,每一方都可以保持与任何通信方的安全或非安全状态。可以在同一文档中交换安全的和非安全的数据。例如,考虑一个包含许多聊天室的安全聊天应用程序,其中每个聊天室都有几个人。可以在聊天伙伴之间交换 XML 加密的文件,这样一个聊天室中的数据对其它聊天室而言是不可见的。

XML 加密能够处理 XML 和非 XML(例如二进制)数据。现在我们将演示一个简单的数据交换,通过 XML 加密使它安全。然后我们将慢慢地增加安全性需求的复杂程度,并解释 XML 加密模式及其不同元素的使用。

XML 数据安全交换的简单示例

假设您希望将 清单 1中的 XML 文件发送给出版公司。这个文件包含一本您要购买的书的详细信息。此外,它还包含您付款的信用卡信息。自然地,您希望对这些敏感数据使用安全通信。一种选择是使用 SSL,它将保护整个通信的安全。备选方案是使用 XML 加密。正如已经提到的,XML 加密不是 SSL/TLS 的替代。如果应用程序要求整个通信是安全的,则您将使用 SSL。另一方面,如果应用程序需要安全和非安全通信的组合(这意味着部分数据将被安全地交换,而其它数据将按原样交换),那么 XML 加密是最佳选择。

清单 1. 要加密的样本 XML 文件

Listing 1.

<purchaseOrder>
      <Order>
            <Item>book</Item>
            <Id>123-958-74598</Id>
            <Quantity>12</Quantity>
      </Order>
      <Payment>
            <CardId>123654-8988889-9996874</CardId>
            <CardName>visa</CardName>
            <ValidDate>12-10-2004</ValidDate>
      </Payment>
</purchaseOrder>

注意:我们故意使 清单 1 中的 XML 文件非常简单。这有助于将我们的注意力集中在与加密相关的问题上。用于合作商业或 Web 服务的现实 XML 文件将有类似的结构,但更冗长。WSDLWeb 服务定义语言)和 SOAP(简单对象访问协议)是 B2B 集成中经常使用的基于 XML 的语法。WSDL SOAP 都可使用 XML 加密来提供企业内的安全通信。有关它们的详细信息,请访问 W3C(请参阅 参考资料)。

使用 XML 加密对整个文档加密

XML 加密提供各种选项。 清单 2 清单 3 清单 4显示了不同的加密结果。让我们逐个仔细研究它们。

倘若您决定加密 清单 1中的整个 XML 文档,则 清单 2 显示最后所得到的 XML 加密的文件。请注意 <CipherData> <CipherValue> 标记。实际加密的数据作为 <CipherValue> 标记的内容出现。整个 CipherData 元素出现在一个 EncryptedData 元素内。 EncryptedData 元素包含用于加密的 XML 名称空间。例如,加密前的原始数据是 XML 并且 Internet Assigned Numbers AuthorityIANA)对 XML 的正式类型定义是 http://www.isi.edu/in-notes/iana/assignments/media-types/text/xml。这作为 Type 属性的值出现。XML 对各种流行的数据格式(如 RTFPDF JPG)使用 IANA 的类型定义。完整细节,请参阅它们的网站(请参阅 参考资料 )。如果有特殊的应用程序数据类型(可能是属于您公司的内容管理系统特有的 DTD XSD),可以在 EncryptedData 元素的 Type 属性里指定它们。另一个属性 xmlns 指定了用来加密 XML 数据的 XML 加密名称空间。

使用 XML 加密对单个元素加密

您可能只想加密 清单 1 中的一个元素例如 Payment 元素。在这种情况下, 清单 3中阐明了其结果。比较 清单 2 清单 3,您将发现下列差异:

  1. 清单 2只包含 XML 加密的模式,而 清单 3既包含 XML 加密模式又包含来自 清单 1中原始数据的元素。在 清单 3中,XML 加密被嵌入到用户的 XML 中。
  2. 清单 3 <EncryptedData> 中也有一个 Type 属性,但它的值是 http://www.w3.org/2001/04/xmlenc#Element。我们不再使用 IANA 类型;相反,我们使用 XML 加密已指定的类型。
  3. 请特别注意末尾的片段 #Element,它表示 EncryptedData ― 这代表一个元素。

加密元素的内容

如果您只要加密 清单 1 中元素 CardId 中的内容, 清单 4 就是其结果。这次,我们使用 http://www.w3.org/2001/04/xmlenc#Content 作为 Type 属性的值。每当我们都仅须加密内容时都使用这个值。

加密非 XML 数据

假如您希望通过 XML 加密发送一个 JPEG 文件,那会怎么样呢? 清单 5 是将产生的一个典型文件。按字节序列加密的整个 JPEG 文件将作为 CipherValue 元素的内容出现。请注意, 清单 2 清单 5 之间唯一的差异: EncryptedData 元素的 Type 属性。 清单 5包含了 JPEG 格式的 IANA 类型。类似地,可以通过提供 IANA 值(参考 IANA 网站,请参阅 参考资料)加密任何格式。

XML 加密的密钥

在清单 1 5 中,我们已经演示了加密,而加密就不可能不使用密钥(请参下 公钥、私钥和秘钥)。使用 XML 加密,所有与密钥相关的问题划分成两个部分:

·           密钥的交换(非对称加密)

·           使用预先交换的密钥(对称加密)

这样,用户可以交换密钥并在以后使用它们。

公钥、私钥和秘钥
我们使用了三个与密钥相关的术语(公钥、私钥和秘钥)。尽管这些术语对从事端到端安全性的开发人员而言是众所周知的,但 XML 开发人员可能并不熟悉它们。让我们阐明这些术语:
公钥和私钥:我们成对使用它们。有些算法生成一对公钥和私钥。我们将公钥发送给任何希望与我们交换加密数据的人。使用公钥,我们只能加密有限大小的数据。通信伙伴使用我们的公钥加密数据,然后将加密的数据发送给我们。接着,我们用私钥解密数据。这是非对称加密。
秘钥: 我们使用公钥和私钥来交换秘钥。通常随机生成秘钥。一旦使用非对称加密与通信伙伴交换了秘钥,我们就可以在两端都使用这个秘钥加密数据了。这是对称加密。

用于交换秘钥的非对称密钥

在这个方案中,一方将它的公钥发送给另一方。另一方使用这个公钥加密其秘钥。 清单 6(请求)和 清单 7 (响应)中显示了这种数据交换。我们假设 Imran Ali 分别是相互通信的第一方和第二方。Imran 初始化了公钥交换请求并在名为 KeyValue 的元素中发送了他的公钥。属性 CarriedKeyName 表示所传输密钥的名称。请注意这个结构的根元素是 EncryptedKey ,它包含 ds:KeyInfo ds:KeyValue 元素。 ds: KeyInfo ds:KeyValue 元素属于 XML 数字签名(ds:)名称空间。对于密钥交换 XML 加密完全依赖于 XML 数字签名规范。因此, <ds:EncryptedKey> <ds:KeyValue> 都属于 XML 数字签名规范名称空间。 清单 7 Ali 发送的响应。 清单 7 中的 CipherValue 元素包含一个新生成的秘钥,它是用第一方的公钥加密的。仔细看清单 6 和清单 7,您将注意到请求和响应都包含 EncryptedKey 元素。 EncryptedKey 元素内的 ds:KeyInfo ds:KeyValue 元素携带着公钥( 清单 6 )。另一方面, EncryptedKey 元素内的 CipherData CipherValue 元素( 清单 7 )将传输(加密的)秘钥。还请注意 EncryptedKey 元素总是包含一个 CarriedKeyName 属性来指定其所携带密钥的名称。

使用我们过去已经交换的密钥

在前一节中,我们交换了一个秘钥。现在我们将使用那个密钥来加密数据。我们将假定 Imran 发送了一条 XML 消息( 清单 8)来响应 清单 7(请回忆 清单 7包含一个名为“Imran Ali”的加密的秘钥)。Imran 将使用他的(Imran 自己的)私钥来解密这个秘钥(因为 Ali Imran 的公钥加密了这个秘钥)。Imran 可以使用这个秘钥并将它放在 清单 8 中的 CipherValue 元素中来加密他打算发送给 Ali 的数据。

清单 8 中的 ds:KeyInfo 元素包含一个 KeyName 元素。这个组合引用了 Imran 用于数据加密的密钥名称。

1 是显示用于安全数据交换的 XML 文件的这种交换的可视图。

1. 使用 XML 加密进行密钥与数据交换的顺序

清单 5 7 中, CipherData 元素可以出现在 EncryptedData 元素或 EncryptedKey 元素中。我们使用 CipherData 元素来引用加密数据(当它出现在 EncryptedData 元素中时)或加密密钥(当它出现在 EncryptedKey 元素中时)。在清单 5 7 中,包含实际加密数据的 CipherData 元素中都有一个 CipherValue 子元素。

我们也可以引用外部加密数据或加密密钥。这意味着实际加密数据或密钥将出现在别的地方(可能是因特网上的某个地方),而不是在 XML 加密文件内。在这种情况下,我们将在 CipherData 中使用 CipherReference 而不是 CipherValue 子元素。我们将通过 URI 引用实际加密数据。这在 清单 9中显示。

引用外部 XML 文件中的特定元素

清单 10 说明了引用外部 XML 文件的一个变体。这里我们只引用了 URI 所指向的外部文件的一部分。 CipherReference 元素中有一个 Transforms 子元素。这个 Transforms 元素可以包含许多 Transform 元素,其中每个都将包含单个 XPath 元素。这个 XPath 元素指定一个 XPath 表达式,该表达式引用外部 XML 文档的特定节点。

我们的 API DOM 结构

我们已经演示了如何创建 XML 加密文件以及交换加密数据。现在我们将推荐用于 XML 加密的 Java API 并提供一个样本实现。为达到这个目的,我们将使用 DOM

我们的 DOM 实现由一组类组成(清单 11 16)。 XmlEncryption 类( 清单 11)是其余类的封装器,这意味着我们的 API 用户将只需要与这个类交互。在内部它使用其它类的功能。

清单 11是一个能够生成完整 XML 加密文件的封装器类。

清单 12 创建 EncryptedData 元素。

清单 13 创建 EncryptionMethod 元素。

清单 14 创建 KeyInfo 元素。

清单 15 创建 CipherData 元素。

清单 16包含作为静态整数的算法名称及其作为字符串的相应名称空间。

XmlEncryption 类( 清单 11)包含各种公用 Get/Set 方法。用户将调用 Set 方法来指定加密参数,包括下列:

1.                   要加密的文件名称

2.                   所产生的 XML 加密文件的名称

3.                   加密算法的名称

4.                   将用于加密的密钥名称

5.                   用于 <EncryptedData> 结构标识的 ID

我们已经通过 main () 方法演示了 XmlEncryption 类( 清单 11 )的使用。我们在 main () 方法中创建了这个类的实例。构造器实例化了 DOM,因此所有基本类都将使用同个对象。

清单 2 中所示,这个实现只支持整个文件的加密。 EncryptCompleteXmlFile () 方法将通过按序列调用下列方法完成这个任务:

1.     GetEncryptedDataDoc() 返回 EncryptedData 类( 清单 12 )的对象。它包含 EncryptedData 元素的结构。

2.     GetEncryptionMethodDoc() 返回 Document 对象,该对象包含对应于 EncryptionMethod 元素的 XML 结构。 GetEncryptionMethodDoc() 使用 EncryptionMethod 类( 清单 13)来创建 XML

3.     GetKeyInfoDoc() 返回 Document 对象,该对象包含对应于 KeyInfo 元素的 XML 结构。 GetKeyInfoDoc() 使用 GenericKeyInfo 类( 清单 14 )的对象来创建 XML。这个类仅提供最小的必需功能(对 KeyName KeyValue 元素的支持),您将通过对 GenericKeyInfo 类的继承来提供完整的功能,其中包含对 X509 证书、PGP 数据等的支持。

4.     ReadFile() 取得我们希望加密的数据(整个 XML 文件)。

5.     GetEncryptedData() 暂时不做任何事情。我们将在本文的下一部分实现这个方法。它应该创建在步骤 4 中取得的 XML 数据的加密格式。在上一节(Java 密码体系结构)中,我们已经简要地讨论了我们的加密策略。

6.     GetCipherDataDoc() 将加密数据作为参数,然后返回包含 CipherData 元素的 Document 对象。 GetCipherDataDoc() 使用 CipherData 类( 清单 12)的对象来创建 XML

7.     最后,三次调用 EncryptedData 清单 15 )对象的 addChild() 方法,该方法将获得步骤 23 6 Document 对象,然后将它们添加到 <EncryptedData> 结构,这是它们所有对象的父类。

8.     SaveEncryptedFile() 保存完整的 XML 加密文件。

AlgoNames 清单 16)是一个只指定 XML 加密所需要的名称空间声明的助手类。

XmlEncryption 类( 清单 11)也可以作为服务器端组件使用。在本系列的下一部分中,我们将演示它在独立应用程序中以及在服务器端应用程序中的使用。

我们已开发的这组类只执行基于 DOM XML 创建。我们还需要实现密码功能。现在我们将尝试形成一个用于密码支持的策略。出于这个目的,我们需要研究 Java 密码体系结构(Java Cryptographic Architecture(JCA))。

Java 密码体系结构(JCA

Java 提供对密码术的完整支持。出于这个目的,J2SE 中有几个包,它们涵盖了安全性体系结构的主要特性,如访问控制、签名、证书、密钥对、密钥存储和消息摘要等。

JCA 设计的主要原理是将密码概念从算法实现中分离出来,以便不同的供应商可以在 JCA 框架内提供他们的工具。

JCA 引擎类

JCA 定义了一系列引擎(Engine)类,其中每个引擎提供一种密码功能。例如,MD(消息摘要)算法有几种不同的标准。这些标准的实现各不相同,但在引擎 API 级别,它们都是相同的。不同的供应商可以自由地提供特定算法的实现。

Java 密码扩展(JCE

所有独立(第三方)供应商的密码算法实现都称为 Java 密码扩展(Java Cryptographic Extension (JCE))。Sun Microsystems 也提供了 JCE 的一种实现。无论何时使用 JCE,都必需将它和 JCA 一起配置。为此,我们需要执行如下操作:

1. 添加 jar 文件的地址以在 CLASSPATH 环境变量中配置供应商(将所有 JCE 实现称为供应商)。

2. 通过编辑 java.security 文件,在您认可的供应商列表中配置供应商。这个文件位于 JavaHome/jre/lib/security 文件夹。下列是指定优先级的语法: security.provider.<n>=<masterClassName> 。这里 n 是优先级号(123 等等)。 MasterClassName 是引擎类将为特定算法实现调用的主类的名称。供应商文档将指定其主类名称。例如,考虑 java.security 文件中的下列项:

·           security.provider.1=sun.security.provider.Sun

·           security.provider.2=com.sun.rsajca.Provider

·           security.provider.3=com.sun.net.ssl.internal.ssl.Provider

这些项意味着引擎类将按上面提到的顺序搜索任何算法实现。它将执行最先找到的实现。完成这些简单步骤之后,我们完全准备好开始在 XML 加密应用程序中使用 JCA/JCE

在我们的 XML 加密实现中使用 JCA JCE

封装器类 XmlEncryption 清单 11 )中的 GetEncryptedData() 函数是处理所有与 JCA/JCE 相关问题的所在。目前,这个方法仅返回字符串“This is Cipher Data”。我们还没有编写与 JCA/JCE 相关的类。这个方法获得未加密数据,然后将它作为加密字符串返回。在编写了用于 JCA/JCE 的封装器类之后,我们将在这个方法中处理所有与算法和密钥相关的问题。

下一次:在这一系列文章的下一部分中,我们将讨论并实现密码术的细节。我们将演示加密和解密类的工作方式以及它们使用解析逻辑的交互,并展示 Web 服务中 XML 加密的应用程序。

 

Listing 1.

<purchaseOrder>
            <Order>
                        <Item>book</Item>
                        <Id>123-958-74598</Id>
                        <Quantity>12</Quantity>
            </Order>
            <Payment>
                        <CardId>123654-8988889-9996874</CardId>
                        <CardName>visa</CardName>
                        <ValidDate>12-10-2004</ValidDate>
            </Payment>
</purchaseOrder>

Listing 2. Encrypting the entire file

<?xml version='1.0' ?>
<EncryptedData xmlns='http://www.w3.org/2001/04/xmlenc#'
                        Type='http://www.isi.edu/in-notes/iana/assignments/media-types/text/xml'>
            <CipherData>
                        <CipherValue>A23B45C56</CipherValue>
            </CipherData>
</EncryptedData>

Listing 3. Encrypting only the <Payment> element

<?xml version='1.0' ?>
<PurchaseOrder>
            <Order>
                        <Item>book</Item>
                        <Id>123-958-74598</Id>
                        <Quantity>12</Quantity>
            </Order>
            <EncryptedData Type='http://www.w3.org/2001/04/xmlenc#Element'
                                                                        xmlns='http://www.w3.org/2001/04/xmlenc#'>
                        <CipherData>
                                     <CipherValue>A23B45C564587</CipherValue>
                        </CipherData>
            </EncryptedData>
</PurchaseOrder>

Listing 4. Encrypting only the content in the CardId element

<?xml version='1.0' ?>
<PurchaseOrder>
            <Order>
                        <Item>book</Item>
                        <Id>123-958-74598</Id>
                        <Quantity>12</Quantity>
            </Order>
            <Payment>
                        <CardId>
                                     <EncryptedData Type='http://www.w3.org/2001/04/xmlenc#Content'
                                                                                    xmlns='http://www.w3.org/2001/04/xmlenc#'>
                                                 <CipherData>
                                                             <CipherValue>A23B45C564587</CipherValue>
                                                 </CipherData>
                                     </EncryptedData></CardId>
                        <CardName>visa</CardName>
                        <ValidDate>12-10-2004</CardName>
            </Payment>
</PurchaseOrder>

Listing 5. Encrypting arbitrary non-XML data (JPEG)

<?xml version='1.0' ?>
<EncryptedData xmlns='http://www.w3.org/2001/04/xmlenc#'
                                      Type='http://www.isi.edu/in-notes/iana/assignments/media-types/jpeg' >
            <CipherData>
                        <CipherValue>A23B45C56</CipherValue>
            </CipherData>
</EncryptedData>

Listing 6. One party sends its public key to a second party for key exchange

<?xml version='1.0' ?>
<SecureCommunicationDemonstration>
            <EncryptedKey  CarriedKeyName="Muhammad Imran" xmlns='http://www.w3.org/2001/04/xmlenc#'>
                        <ds:KeyInfo xmlns:ds='http://www.w3.org/2000/09/xmldsig#'>
                                     <ds:KeyValue>1asd25fsdf2dfdsfsdfds2f1sd23</ds:KeyValue>
                        </ds:KeyInfo>
            </EncryptedKey>
</SecureCommunicationDemonstration>

Listing 7. Second party sends back the randomly generated secret key encrypted with public key of first party

<?xml version='1.0' ?>
<SecureCommunicationDemonstration>
            <EncryptedKey  CarriedKeyName="Imran Ali" xmlns='http://www.w3.org/2001/04/xmlenc#'>
                         <EncryptionMethod   Algorithm= "http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
                                    <CipherData>
                                                 <CipherValue>xyza21212sdfdsfs7989fsdbc</CipherValue>
                                     </CipherData>  
            </EncryptedKey>
</SecureCommunicationDemonstration>

Listing 8. Data is encrypted with a secret key and placed in the <CipherValue> element

<?xml version='1.0' ?>
<<SecureCommunicationDemonstration>
            <Order>
           <Item>book</Item>
                  <Id>123-958-74598</Id>
           <Quantity>12</Quantity>
                  <CardName>Visa</CardName>
                  <ExpDate>10-10-2005</ExpDate>

                        <EncryptedData  Type='http://www.w3.org/2001/04/xmlenc#Element'
                                                                         xmlns='http://www.w3.org/2001/04/xmlenc#'>
                                     <EncryptionMethod Algorithm='http://www.w3.org/2001/04/xmlenc#tripledes-cbc '/>
                                     <ds:KeyInfo xmlns:ds='http://www.w3.org/2000/09/xmldsig#'>
                                                <ds:KeyName>Imran ali</ds:KeyName>
                                    </ds:KeyInfo>
                                     <CipherData>
                                                 <CipherValue>A23B45C564587</CipherValue>
                                    </CipherData>    
                        </EncryptedData>
            </Order>
</SecureCommunicationDemonstration>

Listing 9. Using the <CipherReference> element to refer to external encrypted data

<?xml version='1.0' ?>
<EncryptedData   xmlns='http://www.w3.org/2001/04/xmlenc#' 
                                                 Type='http://www.w3.org/2001/04/xmlenc#Element'>
            <ds:KeyInfo xmlns:ds='http://www.w3.org/2000/09/xmldsig#'>
                       <ds:KeyName>Imran ali</ds:KeyName>
            </ds:KeyInfo>
            <CipherData>
                        <CipherReference URI="www.waxsys.com/secureData/waxFile.txt"/>
            </CipherData>
</EncryptedData>

Listing 10. Using the <Transforms> element and XPath to refer to a particular node of the external XML File

<?xml version='1.0' ?>
<EncryptedData  ID="Enc-Data" xmlns='http://www.w3.org/2001/04/xmlenc#'
                                                              Type='http://www.w3.org/2001/04/xmlenc#Element' >
            <CipherReference URI="http://www.waxsys.com/EncFile.xml" > 
                        <Transforms  xmlns:ds="http://www.w3.org/2000/09/xmldsig#" >
                       <ds:Transform     Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
                                  <wax:XPath xmlns:wax="http://www.waxsys.com/xpathNS">
                                               PruchaseOrder/EncryptedData [@Id="Imran-Enc-Data"]   
                                  </wax:XPath>
                                     </ds:Transform>
          </Transforms>
            </CipherReference>
</EncryptedData>

Listing 11. XmlEncryption.java

/*
            DW/BS
            20020204
            XmlEncryption.java
            Listing 11
            A wrapper class that can generate complete XML encrypted file.
            It uses all the other classes.
            Users of our XML Encryption Engine will only need to interact with
            this class.
 */

import java.io.*;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import org.apache.crimson.tree.XmlDocument;

public class XmlEncryption {
           
            // Source and Result file names.
            private String fileSource = null;
            private String fileResult = null;
           
            // Name of Algorithm which will be used to encrypt data.
            private String algoName = null;

            // Name of Secret key which was previously agreed upon
            // and saved with the given name.
            private String keyName = null;
           
            // Id attribute of Main structure
            private String encId = null;

            // It will be used to get New Document Objects.
            private DocumentBuilder docBuilder = null;

            // Default Constructor
            public XmlEncryption() {
                        // Create DocumentBuilder object from DocumentBuilderFactory.
                        try {
                                     docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
                        } catch (ParserConfigurationException e){ docBuilder = null; }
            }
           
            // Get the new Document object for DocumentBuilder
            private Document getNewDocument() {
                        if (docBuilder != null)
                                     return docBuilder.newDocument();
                        else
                                     return null;         
            }
           
            // Generate Complete XML Encrypted File.
            public void encryptCompleteXmlFile(){
                        // Take an Object of EncryptedData Class.
                        // It represents EncryptedData Element.
                        EncryptedData encDataObj = this.getEncryptedDataDoc(this.encId, "DOCUMENT");

                        // Get XML Structure for EncryptionMehtod element.
                        Document encMethodDoc = this.getEncryptionMethodDoc(this.algoName);          

                        // Get XML Structure for KeyInfo element.                
                        Document encKeyInfoDoc = this.getKeyInfoDoc(this.keyName);

                        // Read the given file data which will be encrypted.
                        String plainData = this.readFile(fileSource);

                        // Use of JCA/JCE to get encrypted data.
                        String cipherData = this.getEncryptedData(plainData);

                        // Get XML Structure for CipherData element.                                    
                        Document cipherDataDoc = this.getCipherDataDoc(cipherData);
                       

                        // Join these XML Structures.
                        encDataObj.addChild(encMethodDoc);
                        encDataObj.addChild(encKeyInfoDoc);
                        encDataObj.addChild(cipherDataDoc);
                       
                        // Now Save this Document as an XML File
                        this.saveEncryptedFile(this.fileResult, encDataObj.getEncData());                      
            }// End encryptCompleteXmlFile()
           
           
            //********** All Set/Get methods to related fields.
           
            public void setFileSource(String file) {
                        this.fileSource = file;
            }// End setFileSource()
           
            public String getFileSource() {
                        return this.fileSource;
            }// End getFileSource()

            public void setFileResult(String file) {
                        this.fileResult = file;
            }// End setFileResult()
           
            public String getFileResult() {
                        return this.fileResult;
            }// End getFileResult()
           
            public void setAlgoName(String name) {
                        this.algoName = name;
            }// End setAlgoName()

            public String getAlgoName() {
                        return this.algoName;
            }// End getAlgoName()
           
            public void setKeyName (String key) {
                        this.keyName = key;
            }// End setKeyName()
           
            public String getKeyName() {
                        return this.keyName;
            }// End getKeyName()

            public void setEncId (String id) {
                        this.encId = id;
            }// End setEncId()

            public String getEncId() {
                        return this.encId;
            }// End setEncId()

            //**************

            // Reads the given file and returns it as string.                       
            public String readFile(String fileName){
                        String xml = "";
                        try {
                                     FileInputStream in = new FileInputStream(fileName);
                                     byte [] data = new byte[in.available()];
                                     in.read(data);
                                     xml = new String(data);
                        } catch (IOException e) { }
                        return xml;
            }// End readFile()
           
            // Saves the given document as an XML (Text) file with given name.
            public void saveEncryptedFile (String fileName, Document doc) {
                        XmlDocument xmlDoc = (XmlDocument)doc;
                        try {
                                     OutputStream out = new FileOutputStream(fileName);
                                     xmlDoc.write(out);
                                     out.close();
                        } catch (IOException e) { }

            }// End saveEncryptedFile()
           
            // Returns the EncryptedData Object.
            public EncryptedData getEncryptedDataDoc(String Id, String encType) {
                        EncryptedData ed = new EncryptedData(this.getNewDocument());
                        ed.setId(Id);
                        if (encType.equals("DOCUMENT"))
                                     ed.setType(AlgoNames.DOCUMENT);
           
                        return ed;
            }// End getEncryptedDataDoc()

            // Returns the EncryptionMehtod Structure.
            public Document getEncryptionMethodDoc (String algoName) {
                        EncryptionMethod em = new EncryptionMethod(this.getNewDocument());
                        if (algoName.equals("TripleDes-cbc"))
                                     em.setAlgorithm(AlgoNames.TRIPLE_DES);
                        return em.getEncMethod();
            }// End getEncryptionMethodDoc()

            // Returns the KeyInfo Structure.
            public Document getKeyInfoDoc (String keyName) {
                        GenericKeyInfo ki = new GenericKeyInfo(this.getNewDocument(),"ds", AlgoNames.XML_DSIG);
                        ki.setKeyName(keyName);
                        return ki.getKeyInfo();      
            }// End getKeyInfoDoc()
           
            // Returns the CipherData Structure.
            public Document getCipherDataDoc (String data) {
                        CipherData cd = new CipherData(this.getNewDocument());
                        cd.setValue(data);
                        return cd.getCipherData();
            }// getCipherDataDoc()
           
            // In the future, all JCA/JCE related classes will be used here.
            // It will take plain text and return its encrypted form.
            // All necessary Infromation about keys and algos will be
            // taken from the fields representing them.
            // For the time being it is not doing any thing.
            public String getEncryptedData(String data) {
                        return "This is Cipher Data";
            }// End getEncryptedData()
           
            // This main method is only included to demonstrate functionality.
            public static void main (String args[]) {
                        XmlEncryption xmlEnc = new XmlEncryption();
                        xmlEnc.setFileSource("Order.xml");
                        xmlEnc.setFileResult("EncryptedOrder.xml");
                        xmlEnc.setAlgoName("TripleDes-cbc");
                        xmlEnc.setKeyName("ImranAli");
                        xmlEnc.setEncId("Test");
                        xmlEnc.encryptCompleteXmlFile();
            }// End main()
}// End Class DemoApplication

Listing 12. Authors the EncryptedData element

/*
            DW/BS
            20020204
            EncryptedData.java
            Listing 12
            Authors the EncryptedData element which is the parent of
            all XML Encryption structures except EncryptedData element.
 */

import org.w3c.dom.*;

public class EncryptedData{
           
            // Element to hold complete XML Structure.
            Element encData = null;
            Document doc = null;

            // Element will be appended in Document only once.
            private boolean elementAppendedToDoc = false;

            // Default Constructor
            public EncryptedData(Document document) {
                        doc = document;
                        encData = doc.createElement("EncryptedData");
                       
                        // Add the namespace attribute
                        encData.setAttribute("xmlns","http://www.w3.org/2001/04/xmlenc#");
            }// End EncryptedData()

            // Specify the ID of this EncryptedData as there
            // can be many EncryptedData elements in the same XML file.
            public void setId(String id){
                        encData.setAttribute("Id", id);
            }// End setId()
           
            // There can be three types:
            // 201 for ELEMENT
            // 202 for CONTENT
            // 303 for DOCUMENT
            public void setType(int type){
                        encData.setAttribute("Type", AlgoNames.getAlgoNSValue(type));
            }// end setType()
           

            // If an Arbitrary type is to be Encrypted, specify its mimeType.
            public void setArbitraryType(String mimeType){
                        String typeValue = "http://www.isi.edu/in-notes/iana/assignments/media-types/" + mimeType;
                        encData.setAttribute("Type", typeValue);                 
            }// End setArbitraryType()
           
            // Add any of these XML Documents KeyInfo | CipherData | Transforms | EncryptionMethod.
            public void addChild(Document document){
                        NodeList nList = document.getChildNodes();

                        for (int i=0 ; i<nList.getLength(); i++){
                                     Node tempNode = nList.item(i);
                                     // If it is a Root Element 
                                     if (tempNode.getNodeType() == Node.ELEMENT_NODE) {
                                                 Node importedNode = (Node)doc.importNode(tempNode,
                                                                                                                                                  true /* import all childern*/);
                                                 encData.appendChild((Element)importedNode);
                                                 return;
                                     }// end if (tempNode.getNodeType() == Node.ELEMENT_NODE)
                        }// end for (int i=0 ; i<nList.getLength(); i++)
            }// End addChild()           
           
            // Return the complete XML structure as a Document Object.
            public Document getEncData(){
                        if (elementAppendedToDoc == false) {
                                     doc.appendChild(encData);
                                     elementAppendedToDoc = true;
                        }
                        return doc;
            }// end getEncData()
}// End class EncryptedData

Listing 13. Authors the EncryptionMethod element

/*
            DW/BS
            20020204
            EncryptionMethod.java
            Listing 13
            Authors the EncryptionMethod element.
 */

import org.w3c.dom.*;
import javax.xml.parsers.*;

public class EncryptionMethod{
           
            // Element to hold complete XML Structure.
            private Element encMethod = null;
            private Document doc = null;

            // Element will be appended in Document only once.
            private boolean elementAppendedToDoc = false;

            // Constructor
            public EncryptionMethod (Document document) {
                        doc = document;
                        encMethod = doc.createElement("EncryptionMethod");
            }// End EncryptionMethod()
           
            // Set the name of Algorithm.
            public void setAlgorithm(int algoNo){
                        encMethod.setAttribute("Algorithm", AlgoNames.getAlgoNSValue(algoNo));
            }// End setAlgorithm()
           
            // Get the complete Document Sturcture.
            public Document getEncMethod() {
                        if (elementAppendedToDoc == false) {
                                     doc.appendChild(encMethod);
                                     elementAppendedToDoc = true;
                        }
                        return doc;
            }// End getEncMethod()
}// End Class EncryptionMethod

Listing 14. Authors the KeyInfo element

/*
            DW/BS
            20020204
            GenericKeyInfo.java
            Listing 14
            Authors the KeyInfo element.
 */

import org.w3c.dom.*;

public class GenericKeyInfo {

            // Element to hold complete XML Structure.
            protected Element keyInfo = null;
            protected Document doc = null;

            // Element will be appended in Document only once.
            protected boolean elementAppendedToDoc = false;

           
            // Default constructor.
            public GenericKeyInfo (Document document, String nsQlif, int typeNo) {
                        doc = document;
                       
                        keyInfo = doc.createElement(nsQlif + ":KeyInfo");
                       
                        // Add the namespace attribute.
                        keyInfo.setAttribute("xmlns:" + nsQlif, AlgoNames.getAlgoNSValue(typeNo));
            }// End GenericKeyInfo
           
            // Add KeyName child in KeyInfo
            public void setKeyName(String keyName) {
                        Element tempElem = doc.createElement("KeyName");
                        tempElem.appendChild(doc.createTextNode(keyName));
                        keyInfo.appendChild(tempElem);
            }// End setKeyName()
           
            // Add KeyValue child in KeyInfo
            public void setKeyValue (String keyValue){
                        Element tempElem = doc.createElement("KeyValue");
                        tempElem.appendChild(doc.createTextNode(keyValue));
                        keyInfo.appendChild(tempElem);
            }// End setKeyValue()
           
            // Set retrieval Method URI and and Its type.
            public void setRetrievalMethod (String uriValue, int typeNo) {
                        Element tempElem = doc.createElement("RetrievalMethod");
                        tempElem.setAttribute("URI", uriValue);
                        tempElem.setAttribute("Type", AlgoNames.getAlgoNSValue(typeNo));
                        keyInfo.appendChild(tempElem);
            }// End setRetrievalMethod()
           
            // Return the complete XML structure as a Document Object.
            public Document getKeyInfo() {
                        if (elementAppendedToDoc == false ) {
                                     doc.appendChild(keyInfo);
                                     elementAppendedToDoc = true;
                        }
                        return doc;
            }// End getKeyInfo()
} // end class KeyInfo

Listing 15. Authors the CipherData element

/*
            DW/BS
            20020204
            CipherData.java
            Listing 15
            Authors the CipherData element.
 */

import org.w3c.dom.*;

public class CipherData {
           
            // We will create child elements within this document.
            private Document doc = null;
           
            // The main structure.
            private Element cipherData = null;

            // Element will be appended in Document only once.
            private boolean elementAppendedToDoc = false;
           
            // Constructor
            public CipherData(Document document){
                        doc = document;
                        cipherData = doc.createElement("CipherData");

                        elementAppendedToDoc = false;
            }// End CipherData()

            // Sets the encrypted Data inside CipherValue Child tag.
            public void setValue(String value){
                        Element tempElem = doc.createElement("CipherValue");
                        tempElem.appendChild(doc.createTextNode(value));
                        cipherData.appendChild(tempElem);
            }// End setValue()

            // Adds CipherReference element inside CipherData element.
            // Its Attribute URI is passed as parameter.
            // Transform element is optional.
            // If want to set only URI then pass NULL in place of transforms Element
            public void setCipherReference (String uriValue, Element transforms) {
                        Element tempElem = doc.createElement("CipherReference");
                        tempElem.setAttribute("URI", uriValue);
                       
                        if ( transforms != null )
                                     tempElem.appendChild(transforms);
                       
                        cipherData.appendChild(tempElem);
            }// End setCipherReference()
           
            // Retuns the completed CipherData structure.
            public Document getCipherData() {
                        if (elementAppendedToDoc == false ) {
                                     doc.appendChild(cipherData);
                                     elementAppendedToDoc = true;
                        }
                        return doc;
            }// End getCipherData()
}// end Class CipherData

Listing 16. AlgoNames.java

 /*
            DW/BS
            20020204
            AlgoNames.java
            Listing 16
            This class is only for convenience of use.
            It contains names of Algorithms as static integers
            and their corresponding namespaces as strings.
 */

public class AlgoNames {

            public static final int TRIPLE_DES    =  1;
            public static final int AES_128               =  2;
            public static final int          AES_256       =  3; 
            public static final int RSA_V1_5      =  4; 
            public static final int RSA_OAEP      =  5; 
            public static final int DH                       =  6;
            public static final int          KW_TRIPLE_DES =  7;  
            public static final int KW_AES_128    =  8; 
            public static final int          KW_AES_256    =  9; 
            public static final int          SHA1           = 10;
            public static final int          SHA256        = 11;

            public static final int          XPATH         = 100;
            public static final int BASE_64                       = 101;
            public static final int ENC_KEY                       = 102;
            public static final int XML_DSIG         = 103;

            // Fields to represent what type of Data to be encrypted.
            public static final int ELEMENT          = 201;
            public static final int CONTENT          = 202;
            public static final int DOCUMENT        = 203;
           
           
           
            public static String getAlgoNSValue(int algoNo){
                        String algoNS = "";
                        switch (algoNo){
                                     case TRIPLE_DES :  algoNS = "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"; break;
                                     case AES_128      :  algoNS = "http://www.w3.org/2001/04/xmlenc#aes128-cbc";    break;
                                     case AES_256      :  algoNS = "http://www.w3.org/2001/04/xmlenc#aes256-cbc";    break;
                                     case RSA_V1_5    :  algoNS = "http://www.w3.org/2001/04/xmlenc#rsa-1_5";        break;
                                     case RSA_OAEP   :  algoNS = "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p";break;
                                     case DH                          :  algoNS = "http://www.w3.org/2001/04/xmlenc#dh";                           break;
                                     case KW_TRIPLE_DES:algoNS = "http://www.w3.org/2001/04/xmlenc#kw-tripledes";  break;
                                     case KW_AES_128            :  algoNS = "http://www.w3.org/2001/04/xmlenc#kw-aes128";        break;
                                     case KW_AES_256            :  algoNS = "http://www.w3.org/2001/04/xmlenc#kw-aes256";        break;
                                     case SHA1                      :  algoNS = "http://www.w3.org/2000/09/xmldsig#sha1";                           break;
                                     case SHA256                   :  algoNS = "http://www.w3.org/2000/09/xmldsig#sha256";                        break;
                                     case XPATH                     :  algoNS = "http://www.w3.org/TR/1999/REC-xpath-19991116";   break;
                                     case BASE_64      :  algoNS = "http://www.w3.org/2000/09/xmldsig#base64";                    break;
                                     case ENC_KEY     :  algoNS = "http://www.w3.org/2001/04/xmlenc#EncryptedKey";  break;
                                     case XML_DSIG    :  algoNS = "http://www.w3.org/2000/09/xmldsig#";                              break;
                                     case ELEMENT     :  algoNS = "http://www.w3.org/2001/04/xmlenc#Element";                    break;
                                     case CONTENT     :  algoNS = "http://www.w3.org/2001/04/xmlenc#Content";                   break;
                                     case DOCUMENT  :  algoNS = "http://www.isi.edu/in-notes/iana/assignments/media-types/text/xml";  break;
           
                        } // end switch(algoNo)
                        return algoNS;
            }// End getAlgoNsValue()
}// End Class

参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
易语言是一种编程语言,它提供了一些简单的函数和工具来进行XML加密和解密操作。 在易语言中,可以使用`xml编码文件读取`函数来读取XML文件的内容。读取后的XML内容可以使用`编码`函数进行加密处理。加密后的内容可以存储到文件或在网络中传输。 对于加密后的XML内容,我们可以使用`解码`函数进行解密操作,并将解密后的内容保存到字符串变量中。解密后的内容就可以进行正常的XML处理操作。 下面是一个使用易语言进行XML加密和解密的示例代码: ``` 文件编码模式设置为空编码模式 文件编码模式设置为空编码模式 '设置文件操作编码模式为默认编码模式 字符编码模式推入空编码模式 字符编码模式推入空编码模式 '设置字符操作编码模式为空编码模式 '加密XML文档 xml内容 = xml编码文件读取("input.xml") '读取XML文件内容 加密内容 = 编码(xml内容) '加密XML内容 文件编码模式设置为UTF-8编码模式 文件编码模式设置为UTF-8编码模式 '设置文件操作编码模式为UTF-8编码模式 文件编码模式推入UTF-8编码模式 文件编码模式推入UTF-8编码模式 '设置字符操作编码模式为UTF-8编码模式 '保存加密后的XML文档 xml编码文件保存("encrypted.xml", 加密内容) '解密XML文档 加密内容 = xml编码文件读取("encrypted.xml") '读取加密后的XML内容 解密内容 = 解码(加密内容) '解密XML内容 '保存解密后的XML文档 xml编码文件保存("decrypted.xml", 解密内容) ``` 以上代码演示了如何使用易语言实现XML加密和解密。通过使用`编码`函数对XML内容进行加密,再使用`解码`函数对加密后的内容进行解密,可以保护XML的机密信息并确保安全传输和存储。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值