xml 加密
当前,传输层安全性(TLS)是用于Internet上安全通信的事实上的标准。 TLS是遵循著名的安全套接字层(SSL)的端到端安全协议。 SSL最初由Netscape设计,后来由Internet工程任务组(IETF)在设计TLS时对其版本3.0进行了修改。 这是一个非常安全可靠的协议,可在两方之间提供端到端的安全会话。 XML加密无意替代或取代SSL / TLS。 而是,它提供了SSL未涵盖的安全要求机制。 以下是SSL未解决的两个重要领域:
- 加密部分要交换的数据
- 超过两方之间的安全会话
使用XML加密,各方可以与任何通信方保持安全或不安全的状态。 安全和非安全数据都可以在同一文档中交换。 例如,考虑一个安全的聊天应用程序,其中包含多个聊天室,每个聊天室中都有几个人。 可以在聊天伙伴之间交换XML加密的文件,以便发送给一个房间的数据对其他房间不可见。
XML加密可以处理XML和非XML(例如二进制)数据。 现在,我们将演示一个简单的数据交换,通过XML加密使其安全。 然后,我们将慢慢增加安全要求的复杂性,并说明XML加密模式及其不同元素的用法。
安全交换XML数据的简单示例
假设您要将清单1中的XML文件发送给出版公司。 该文件包含您要购买的书籍的详细信息。 此外,它还包含您的信用卡信息以进行付款。 自然,您想对这些敏感数据使用安全通信。 一种选择是使用SSL,以确保整个通信的安全。 替代方法是使用XML加密。 如前所述,XML加密不能替代SSL / TLS。 如果应用程序要求整个通信安全,则将使用SSL。 另一方面,如果应用程序需要安全和不安全的通信组合(这意味着某些数据将被安全地交换而其余的将被原样交换),则XML加密是最佳选择。
清单1.要加密的示例XML文件
<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文件的结构类似,但更为冗长。 WSDL(Web服务定义语言)和SOAP(简单对象访问协议)是基于XML的语法,在B2B集成中经常使用。 WSDL和SOAP都可以使用XML加密来提供跨企业的安全通信。 访问W3C了解有关它们的详细信息(请参阅参考资料 )。
使用XML加密对完整文档进行加密
XML加密提供各种选项。 清单2 , 清单3和清单4展示了不同的加密结果。 让我们一一详细地研究它们。
清单2显示了生成的XML加密文件,以防您决定对清单1中的整个XML文档进行加密。 注意<CipherData>
和<CipherValue>
标记。 实际的加密数据将显示为<CipherValue>
标记的内容。 完整的CipherData
元素出现在EncryptedData
元素内。 EncryptedData
元素包含用于加密的XML名称空间。 例如,加密之前您的原始数据是XML,Internet号码分配机构(IANA)对XML的正式类型定义是http://www.isi.edu/in-notes/iana/assignments/media-types/text / xml。 这显示为“ Type
属性的值。 XML加密使用IANA的类型定义来定义各种流行的数据格式,例如RTF,PDF和JPG。 请访问其网站以获取完整的详细信息(请参阅参考资料 )。 如果您有特殊的应用程序数据类型(也许您自己的DTD或XSD属于公司的内容管理系统),则可以在EncryptedData
元素的Type
属性中指定它们。 另一个属性xmlns指定用于加密XML数据的XML加密名称空间。
使用XML加密对单个元素进行加密
您可能只希望加密清单1中的一个元素,例如Payment
元素。 在这种情况下,结果如清单3所示 。 比较清单2和清单3 ,您会发现以下差异:
- 清单2仅包含XML Encryption的模式,而清单3包含XML Encryption以及清单1中原始数据的元素。 在清单3中 ,XML加密被嵌入到用户的XML中。
- 清单3在
<EncryptedData>
也具有Type
属性,但是其值为http://www.w3.org/2001/04/xmlenc#Element。 我们不再使用IANA类型; 相反,我们使用XML加密指定的类型。 - 尤其要注意片段#Element的末尾,它表示EncryptedData -这表示一个元素。
加密元素的内容
如果只想加密CardId
( 清单1中的元素)中的内容,则清单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中,我们演示了加密,如果没有密钥,则无法实现加密(请参见侧栏的Public,private和secret密钥 )。 使用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
元素( 清单7 )内的CipherData
和CipherValue
元素将传输秘密(加密)密钥。 还要注意, EncryptedKey
元素始终包含CarriedKeyName
属性,以指定其携带的密钥的名称。
使用我们过去已经交换过的密钥
在上一节中,我们交换了一个密钥。 现在,我们将使用该密钥来加密数据。 我们将假定Imran响应清单7发送了XML消息( 清单8 )(回想清单7包含一个名为“ Imran Ali”的加密密钥)。 Imran将使用其(Imran自己的)私有密钥解密此密钥(因为Ali使用Imran的公共密钥加密了此密钥)。 Imran可以使用此密钥对要发送给Ali的数据进行加密,并将其放入清单8的CipherValue
元素中。
清单8中的ds:KeyInfo
元素包含一个KeyName
元素。 此组合指的是Imran用于数据加密的密钥的名称。
图1是显示用于安全数据交换的XML文件交换的直观视图。
图1.使用XML加密进行密钥和数据交换的顺序
从我们的XML加密文件引用外部加密数据
在清单5和7中 , CipherData
元素可以出现在EncryptedData
元素或EncryptedKey
元素内。 我们使用CipherData
元素引用加密的数据(当它出现在EncryptedData
元素内部时)或加密的密钥(当它出现在EncryptedKey
元素内部时)。 在清单5和7中 , CipherData
元素内有一个CipherValue
子元素,其中包含实际的加密数据。
我们还可以引用外部加密数据或加密密钥。 这意味着实际的加密数据或密钥将存在于其他地方(也许在Internet上的某处),而不是在我们的XML加密文件中。 在这种情况下,我们将使用CipherReference
代替CipherData
中的CipherValue
子元素。 我们将通过URI引用实际的加密数据。 如清单9所示。
引用外部XML文件的特定元素
清单10展示了引用外部XML文件的变体。 在这里,我们仅引用了URI指向的外部文件的一部分。 CipherReference
元素内部有一个Transforms
子元素。 这个Transforms
元素可能包含许多Transform
元素,每个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方法来指定加密参数,其中包括:
- 要加密的文件名
- 生成的XML加密文件的名称
- 加密算法的名称
- 我们将用于加密的密钥名称
- 用于标识
<EncryptedData>
结构的ID
我们已经通过main ()
方法演示了XmlEncryption
类( 清单11 main ()
用法。 在main ()
方法中,我们创建了此类的实例。 构造函数实例化DOM,以便所有基础类都将使用同一对象。
此实现仅支持对完整文件进行加密,如清单2所示 。 EncryptCompleteXmlFile ()
方法将通过依次调用以下方法来完成此工作:
-
GetEncryptedDataDoc()
返回EncryptedData
类的对象( 清单12 )。 它包含EncryptedData
元素的结构。 -
GetEncryptionMethodDoc()
返回Document对象,其中包含与EncryptionMethod
元素相对应的XML结构。GetEncryptionMethodDoc()
使用EncryptionMethod
类( 清单13 )来编写XML。 -
GetKeyInfoDoc()
返回Document
对象,其中包含与KeyInfo元素对应的XML结构。GetKeyInfoDoc()
使用GenericKeyInfo
类的对象( 清单14 )来编写XML。 此类仅提供您将从GenericKeyInfo
类继承的最低必需功能(支持KeyName
和KeyValue
元素),以提供完整功能,其中包括对X509证书,PGP数据等的支持。 -
ReadFile()
获取我们要加密的数据(完整的XML文件)。 -
GetEncryptedData()
暂时没有做任何事情。 我们将在本文的下一部分中实现此方法。 它应该创建在步骤4中获取的XML数据的加密形式。我们在上一节(Java密码体系结构)中简要讨论了我们的加密策略。 -
GetCipherDataDoc()
将加密的数据作为参数,并返回包含CipherData
元素的文档对象。GetCipherDataDoc()
使用CipherData
对象类( 清单12 )来编写XML。 - 最后,将
EncryptedData
的Object( 清单15 )的addChild()
方法称为三次,它将采用步骤2、3和6的Document Objects,并将它们添加到<EncryptedData>
结构中,该结构是所有对象的父级。其中。 -
SaveEncryptedFile()
保存完成的XML加密文件。
AlgoNames
( 清单16 )是一个帮助程序类,仅指定XML加密所需的名称空间声明。
XmlEncryption
类( 清单11 )也可以用作服务器端组件。 在本系列的下一部分中,我们将演示其在独立以及服务器端应用程序中的使用。
我们开发的一组类仅执行基于DOM的XML创作。 我们还需要实现加密功能。 现在,我们将尝试形成加密支持策略。 为此,我们需要研究Java加密体系结构(JCA)。
Java加密架构(JCA)
Java提供了对加密的完全支持。 为此,J2SE内有几个软件包,涵盖了安全体系结构的所有主要功能,例如访问控制,签名,证书,密钥对,密钥存储和消息摘要。
JCA设计的主要原理是将加密概念与算法实现分开,以便不同的供应商可以在JCA框架内提供其工具。
JCA Engine类
JCA定义了一系列Engine类,其中每个Engine提供一个加密功能。 例如,MD(消息摘要)算法有几种不同的标准。 所有这些标准的实现方式都不同,但是在引擎API级别上,它们都是相同的。 不同的供应商可以自由提供特定算法的实现。
Java密码扩展(JCE)
密码算法的所有独立(第三方)供应商实现均称为Java密码扩展(JCE)。 Sun Microsystems还提供了JCE的实现。 每当我们使用JCE时,都需要使用JCA对其进行配置。 为此,我们需要执行以下操作:
1.添加jar文件的地址,以在CLASSPATH
环境变量中配置提供程序(所有JCE实现都称为提供程序)。
2.通过编辑java.security文件,在批准的提供程序列表中配置提供程序。 该文件位于JavaHome / jre / lib / security文件夹中。 以下是指定优先级的语法: security.provider.<n>=<masterClassName>
。 在此,n是优先级编号(1、2、3等)。 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编写包装器类之后,我们将处理此方法中所有与算法和密钥有关的问题。
下一次:在本系列文章的下一部分中,我们将讨论并实现加密技术的详细信息。 我们将演示加密和解密类的工作以及它们与解析逻辑的交互,并介绍XML加密在Web服务中的应用。
翻译自: https://www.ibm.com/developerworks/xml/library/x-encrypt/index.html
xml 加密