Web服务安全性(WS-Security)
作者:
Bob Atkinson,Microsoft
Giovanni Della-Libera,Microsoft
Satoshi Hada,IBM
Maryann Hondo,IBM
Phillip Hallam-Baker,VeriSign
Johannes Klein,Microsoft
Brian LaMacchia,Microsoft
Paul Leach,Microsoft
John Manferdelli,Microsoft
Hiroshi Maruyama,IBM
Anthony Nadalin,IBM
Nataraj Nagaratnam,IBM
Hemma Prafullchandra,VeriSign
John Shewchuk,Microsoft
Dan Simon,Microsoft
编辑:
Chris Kaler,Microsoft
Copyright? 2002-2002 International Business Machines Corporation, Microsoft Corporation, VeriSign, Inc. All rights reserved. 这篇文档中所包含信息的表达、分发或其它形式的传播并不是(无论明示的还是默示的)IBM 或 Microsoft 和/或其他第三方所拥有或控制的知识产权的许可证。IBM、Microsoft 和/或其他第三方可能拥有涵盖本文档中主题的专利权、专利应用程序、商标、版权或其他知识产权。提供这篇文档并没给予您 IBM 或 Microsoft 或任何其他第三方的专利权、商标、版权或其它知识产权的许可证。这里描述的示例公司、组织、产品、域名、电子邮件地址、徽标、人物、地点和事件纯属虚构。如与任何真实的公司、组织、产品、域名、电子邮件地址、徽标、任务、地点或时间有关纯属无意,请勿妄加推测。这里包含的这篇文档和信息以“仅此状态”提供,并被适当的法律最大程度地许可,IBM 和 Microsoft 以“仅此状态和未消除任何错误”的状态提供本文档,因此对所有关于本文档的其它保证和条件(无论是明示的、默示的、还是法定的)不负任何责任,这些保证和条件包括(但不限于)任何(如果有的话)对适销性、适用于某特定用途、准确性、完全负责、结果、技艺精湛的成果、确认无病毒、无疏忽等保证和条件。另外,对于标题、安静享用物业、拥有而不受干扰、与描述相符、不侵犯本文档相关的知识产权也不提供任何保证或条件。在任何情况下,IBM 或 MICROSOFT 都不对任何第三方受到的生产替代品或服务损失、利润亏损、使用上的损失、数据损失、或者任何意外的、相应产生的、直接的、间接的、或特殊的损害负责,不管是有合同、民事侵权行为、保证还是其它条件、由此引起还是由与本文档相关的任何其它协议引起、也不管第三方是否已经提醒可能会有这种损害。
摘要
WS-Security 描述通过消息完整性、消息机密性和单独消息认证提供保护质量对 SOAP 消息传递的增强。这些机制可以用于提供多种安全性模型和加密技术。
WS-Security 还提供关联安全性令牌和消息的通用机制。WS-Security 不需要特定类型的安全性令牌。它在设计上就是可扩展的(例如支持多安全性令牌格式)。举例来说,客户机可能会提供身份证明和他们有特定商业认证的证明。
另外,WS-Security 还描述如何对二进制安全性令牌编码。此规范特别描述如何对 X.509 证书和 Kerberos 票据编码以及如何加入难于理解的加密密钥。它还包括可以用于进一步描述消息中包含的凭证特征的扩展性机制。
可组成的体系结构
通过使用 SOAP 扩展性模型,基于 SOAP 的规范被设计成与其它规范组合起来提供丰富的消息传递环境。WS-Security 自身并不保证安全性,也不提供完整的安全性解决方案。WS-Security 是一种构件,它可以与其它 Web 服务扩展和更高级的特定于应用程序的协议联合使用,以适应多种安全性模型和加密技术。实现 WS-Security 并不意味着应用程序不会受到攻击或者安全性不会受到威胁。
本文档的情况
WS-Security 和相关规范只按现状提供,作为回顾和评价。IBM 和 Microsoft 以及 VeriSign 都希望在不久的将来能得到您的投稿和建议。IBM、Microsoft 和 Versign 不以任何方式作出关于规范的保证或陈述。
1. 引言
本规范提出了一套标准的 SOAP 扩展,可以在构建安全的 Web 服务以实现完整性和机密性时使用。我们将这套扩展称为“Web 服务安全性语言(Web Services Security Language)”或“WS-Security”。
WS-Security 很灵活,它被设计成用来构建多种安全性模型(包括 PKI、Kerberos 和 SSL)的基础。WS-Security 特别为多安全性令牌、多信任域、多签名格式和多加密技术提供支持。
本规范提供了三种主要的机制:安全性令牌传播、消息完整性和消息机密性。这些机制本身并不提供完整的安全性解决方案。相反,WS-Security 是一种构件,它可以与其它 Web 服务扩展和更高级的特定于应用程序的协议联合使用,以适应多种安全性模型和加密技术。
这些机制可以独立使用(例如传送安全性令牌),或以紧密集成的方式使用(例如,对消息签名和加密,并提供与用于签名和加密的密钥相关的安全性令牌层次结构)。
本文档的推出紧接着 IBM 和 Microsoft 现有的 Web 服务安全性规范,包括 SOAP-SEC;Microsoft 的 WS-Security 和 WS-License;还有 IBM 的安全性令牌和加密文档。
请注意,第 1 部分是非标准的。
1.1. 目标和需求
WS-Security 的目标是使应用程序能构建安全的 SOAP 消息交换。
本规范旨在提供一套可以用于构建一系列安全性协议的灵活的机制;换句话说,本规范刻意不去描述显式确定的安全性协议。
与每个安全性协议相同,要确保使用 WS-Security 构建的安全性协议不易受到各种形式的攻击,必须作出很多努力。
概括地说,本规范的重点就是描述一种为消息安全性准备的单消息安全性语言,这种消息安全性可以假定已经建立的会话、安全性环境和/或策略协议。
支持安全的消息交换需要的东西如下所示:
1.1.1. 需求
Web 服务安全性语言必须支持多种安全性模型。下面的清单表明了本规范的关键驱动性需求:
用于认证或授权的多安全性令牌
多信任域
多加密技术
端对端消息级安全性而非仅仅传输级安全性
1.1.2. 非目标
下面的主题超过了本文档的讨论范围:
建立需要多交换的安全性环境或认证机制。
密钥交换和派生出的密钥
信任是如何建立或决定的。
1.2. 示例
下面的示例将说明一个带有用户名安全性令牌的消息:
(001)
(002)
http://www.w3.org/2001/12/soap-envelope
开头两行将启动 SOAP 信封。行(003)启动与此 SOAP 消息相关的报头。行(004)到(008)指定如何路由此消息(如 WS-Routing 中定义的那样)。"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
(003)
(004)
http://schemas.xmlsoap.org/rp/
(009)
(030)
(031)
(032)
http://fabrikam123.com/payloads
(033)
(034) " designtimesp=28799>
(005)
http://fabrikam123.com/getQuote
(006)
http://fabrikam123.com/stocks
(007)
uuid:84b9f5d0-33fb-4a81-b02b-5b760641c1d6
(008) http://schemas.xmlsoap.org/ws/2002/04/secext">
(010) wsse:UsernameToken Id="MyID">
(011)
Zoe
(012)
(013)
(014)
(015)
(022)
DJbchm5gK...
(023)
(024)
(025)
(026)
(027)
(028)
http://www.w3.org/2001/10/xml-exc-c14n#"/>
(016)
Algorithm=
"
(029) http://www.w3.org/2000/09/xmldsig#hmac-sha1"/>
(017)
(018)
Algorithm=
"
(021) http://www.w3.org/2000/09/xmldsig#sha1"/>
(019)
LyLsF0Pi4wPU...
(020) " designtimesp=28860>
QQQ
行(009)启动我们在本规范中定义的 报头。该报头包含预期接收方的安全性信息。该元素继续一直到行(029)为止。
行(010)到(012)指定与本消息相关的安全性令牌。这样,它就定义了使用 的客户机的用户名。请注意,我们在这里假定服务知道密码 — 换句话说,这是个共享的秘密。
行(013)到(028)指定数字签名。该签名确保了被签署元素的完整性(也就是它们不被修改)。签名使用了 XML 签名规范。在本示例中,签名是根据从用户密码生成的密钥进行的;一般来说,应该使用更强大的签名机制(请参阅下面的扩展示例)。
行(014)到(021)描述了数字签名。行(015)指定如何规范化(普通化)被签署的数据。
行(017)到(020)选择被签署的元素。行(017)特别指出 元素被签署。在本示例中,只有消息主体被签署;一般来说,消息的附加元素(如部分路由报头)应该被包括在签名中(请参阅下面的扩展示例)。
如 XML 签名规范中所定义,行(022)指定将被签署的标准化数据形式的签名值。
行(023)到(027)提供关于在何处能找到与此签名相关的安全性令牌的暗示。行(024)到(025)特别指出安全性令牌可以在特定 URL 找到(拉出)。
行(031)到(033)包含 SOAP 消息的主体(有效负载)。
2. 符号和术语
这一部分指定在本规范中使用的符号、名称空间和术语。
2.1. 符号转换
本文档中的关键字“MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY”和“OPTIONAL”应该用 RFC2119 中描述的方式来解释。
名称空间 URI(常规形式“some-URI”)表示某种依赖应用程序或依赖环境的 URI,就象 RFC2396 中定义的一样。
WS-Security 旨在与一般的 SOAP 消息结构和消息处理模型共同工作,而 WS-Security 对于任何版本的 SOAP 都应该是适用的。这里使用了当前的 SOAP 1.2 名称空间 URI,以提供详细示例,但我们无意将此规范的适用性限制在单个版本的 SOAP 中。
读者应该熟悉 Internet Security Glossary 中的术语。
2.2. 名称空间
该规范的实现一定要使用的 XML 名称空间 URI 是:
http://schemas.xmlsoap.org/ws/2002/04/secext
本文档中使用了下列名称空间:
前缀 | 名称空间 |
s | http://www.w3.org/2001/12/soap-envelope |
ds | http://www.w3.org/2000/09/xmldsig# |
xenc | http://www.w3.org/2001/04/xmlenc# |
m | http://schemas.xmlsoap.org/rp |
wsse | http://schemas.xmlsoap.org/ws/2002/04/secext |
2.3 术语
我们为本规范中使用的安全性术语提供了基本的定义。
声明 — 声明是客户进行的一条陈述(例如名称、身份、密钥、组、特权、能力等)。
安全性令牌 — 安全性令牌 代表声明的集合。
已签署的安全性令牌 — 签署的安全性令牌 是由特定机关声明并加密签署的安全性令牌(例如 X.509 证书或 Kerberos 票据)。
图 1
所有权证明 — 所有权证明信息是证明过程中用来说明发送方对信息的认识的数据,这些信息仅为安全性令牌的声明发送方所知。
完整性 — 完整性是保证信息在传输过程中不被修改的过程。
机密性 — 机密性是保护数据使得授权参与者或安全性令牌所有者才能够浏览数据的过程。
摘要 — 摘要是八位流的加密校验和。
签名 — 签名是所有权证明和摘要的加密绑定。这涵盖了基于对称密钥和基于公钥的签名。所以,并不总是能够达到不可抵赖性。
附件 — 附件是一个一般术语,指与 SOAP 消息一起传递的附加数据,但不属于 SOAP 信封的一部分。
3. 保护质量
为了保护 SOAP 消息的安全,您应该考虑两种类型的威胁:1) 消息可能被对手修改或阅读,或者 2) 对手可能将格式良好但缺乏适当安全性声明来保证处理过程的消息发送到服务。
为了理解这些威胁,我们定义了一个消息安全性模型。
3.1. 消息安全性模型
在本文档中,我们根据安全性令牌,与签名组合在一起作为安全性令牌(密钥)的所有权声明,指定了一个抽象的消息安全性模型。
安全性令牌发出声明,而签名为确认发送者对密钥的认识提供了一种机制。同时,签名能够用于“绑定”或“关联”签名和安全性令牌中的声明(假定令牌已被信任)。请注意,这种绑定被限制在签名涉及的元素中。另外还要注意,本文档并不指定特殊的认证方法,它只是表明安全性令牌可以被绑定到消息。
声明可以由被信任的机构签署或取消签署。一组被签署的声明一般由数字签署或被机构加密的签署过的安全性令牌表示。X.509 证书(声明身份和公钥之间绑定)就是签署过的安全性令牌的一个示例。签署过的声明也可以被表示为对某机构的引用,目的是让接收方可以从被引用的机构“拉”出声明。
如果发送方和接收方之间存在信任关系,没有签署的声明也可以信任。举例来说,如果发送方和接收方使用信任连接,而且它们之间存在特殊的信任关系,那么没有签署的对发送方为 Bob 的声明来说,特定接收方也足以相信发送方确实是 Bob。
非签署声明的一种特殊类型是所有权证明。这种声明将证明发送方具有可以被合适的参与者验证的特定知识。举例来说,用户名/密码就是带这种类型声明的安全性令牌。所有权证明声明有时候与其它安全性令牌联合使用来证明发送者的声明。请注意,用于消息完整性的数字完整性也可以用作所有权证明声明,尽管我们在本规范中不考虑把这种数字签名作为一种安全性令牌的情况。您应该注意,这种安全性模型本身就易于遭受多安全性攻击。请参阅安全性注意事项部分了解其它细节。
3.2. 消息保护
保护消息内容免遭拦截(机密性)或非法修改(完整性)是主要的安全性问题。本规范提供了一种通过对消息主体、报头、附件或它们的任何组合(或部分)进行加密和/或数字签署来保护消息的方法。
消息完整性是通过同时利用 XML 签名和安全性令牌来确保消息在传输过程中不被修改而实现的。完整性机制旨在支持多签名(可能是多参与者进行的),而且可以扩展为支持其它签名格式。
消息机密性同时利用 XML 加密和安全性令牌来保持部分 SOAP 消息是机密的。加密机制旨在支持多参与者的其它加密过程和操作。
3.3. 丢失或不合适的声明
消息接收方应该拒绝签名无效、声明丢失或不合适的消息,因为这种消息是非授权(或格式错误)的消息。本规范通过将零或多个安全性令牌与消息关联,为消息发送者声明安全性属性提供了一种灵活的方法。安全性声明的一个示例是发送方的身份;发送方可以声明他是 Bob,也就是某公司的职员,从而有发送消息的权力。
4. 安全性元素
报头块提供了一种机制,用来附加定位在特定接收方(SOAP 参与者)的有关安全性的信息。这可能是消息最终接收方或中介体。因此,该报头块可能在 SOAP 消息中多次被提出。消息路径上的中介体可能向已有的
报头块添加一个或多个新的子元素,如果它们的目标是同一个 SOAP 节点,否则中介体可能为其它目标添加一个或多个新的报头。
如上所述,如果消息报头定位在分开的接收方上,消息就可能有多个 报头块。然而,只有一个 报头块可以省略 S:actor 属性,两个 报头块不能有相同的 S:actor 值。定位在不同接收方上的消息安全性信息必须出现在不同的 报头块中。没有指定的 S:actor 的 报头块可以被任何人使用,但绝不能在 WS-Routing 决定的最终点之前删除。
因为元素被添加到 报头块中,所以在已有的元素中应该预先考虑它们。这样, 报头块表示消息发送方用来创建消息所采取的签名和加密步骤。这种预先考虑的规则将确保接收的应用程序可以按子元素在 报头块中出现的顺序处理它们,因为子元素之间不会有向前依赖性。请注意,该规范并不强制任何处理子元素的特定顺序。接收的应用程序可以使用任何所需的策略。
当子元素引用另一个子元素中带有的密钥时(例如引用包含用于签名的 X.509 证书的二进制安全性令牌子元素的签名子元素),应该在将添加的使用密钥的子元素之后预先考虑包含密钥的安全性令牌,这样密钥材料就会在使用密钥的子元素之前出现。
下面举例说明该报头的句法:
...
...
...
...
下面将描述上面示例列出的属性和元素:
/Security
这是向接收方传送与安全性相关的消息信息的报头块。
/Security/@S:actor
该属性允许标识一个特定的 SOAP 参与者。该属性不是必需的;然而,不能有两个报头块的实例可以省略参与者或指定相同的参与者。
/Security/{any}
这是一个允许根据模式传送不同(可扩展)类型的安全性信息的扩展性机制。
/Security/@{any}
这是一种允许根据模式向报头添加另外属性的扩展性机制。
下面的子节部分将概述要在 报头内使用的新的和已有的元素。
4.1. UsernameToken 元素
我们引入
是作为验证用户名和可选密码信息的方式。
下面举例说明该元素的句法:
...
...
下面将描述上面示例中列出的属性和元素:
/UsernameToken
该元素用于发送基本认证信息。
/UsernameToken/@Id
该安全性令牌的一个字符串标记。
/UsernameToken/Username
这个所需的元素指定认证方的用户名。
/UsernameToken/Username/@{any}
这是一种允许根据模式向报头添加另外属性的扩展性机制。
/UsernameToken/Password
这个可选元素提供密码信息。我们建议:只有在使用安全的传输时才传送该元素。
/UsernameToken/Password/@Type
这个可选属性将指定所提供的密码的类型。下面的表将说明预定义类型:
值 | 描述 |
wsse:PasswordText(缺省) | 用户名的实际密码。 |
wsse:PasswordDigest | 用户名密码摘要。值为 UTF8 编码的密码的 base64 编码的 SHA1 散列值。 |
UsernameToken/Password/@{any}
这是一种允许根据模式向报头添加另外属性的扩展性机制。
/UsernameToken/{any}
这是一种允许根据模式传送各种不同(可扩展)类型的安全性信息的扩展性机制。
/UsernameToken/@{any}
这是一种允许根据模式向报头添加其它属性的扩展性机制。
下面举例说明该元素的使用:
http://www.w3.org/2001/12/soap-envelope
"
xmlns:wsse="
http://schemas.xmlsoap.org/ws/2002/04/secext
">
...
Zoe
ILoveDogs
...
...
4.2. 编码二进制安全性令牌
任何基于 XML 的安全性令牌都可以在
报头中指定。然而,二进制(例如 X.509 证书和 Kerberos 票据)或其它非 XML 格式都需要特殊的编码格式进行包含。
一个二进制安全性令牌有两个用于解释自身的属性。ValueType 属性表明安全性令牌是什么,比如说 Kerberos 票据。EncodingType 表明安全性令牌如何被编码,例如使用 Base64Binary。
BinarySecurityToken 元素定义二进制编码的安全性令牌。编码过程用 EncodingType 属性指定,值类型和空间用 ValueType 属性指定。
下面是句法的大概情况:
EncodingType=...
ValueType=.../>
下面将描述上面示例中列出的属性和元素:
/BinarySecurityToken
该元素用于包括二进制编码的安全性令牌。
/BinarySecurityToken/@Id
该安全性令牌的一个可选字符串标签。
/BinarySecurityToken/@ValueType
ValueType 属性用于表明编码二进制数据(例如 X.509 证书)的“值空间”。ValueType 属性允许定义编码二进制数据的值类型和空间的限定名。该属性用 XML 名称空间时是可扩展的。
/BinarySecurityToken/@EncodingType
EncodingType 属性用于使用 QName 表明二进制数据的编码格式(例如 wsse:Base64Binary)。我们引入这个新属性是因为当前的情况使得在 XML 模式内对混合的简单和复杂类型进行派生变得困难。解释 EncodingType 属性是为了表明元素的编码格式。下面的编码格式是预定义的:
QName | 描述 |
wsse:Base64Binary | XML Schema base 64 编码 |
wsse:HexBinary | XML Schema 十六进制编码 |
这是一种允许根据模式添加其它属性的扩展性机制。
下面的值空间是为 @ValueType 定义的:
QName | 描述 |
wsse:X509v3 | X.509 v3 证书 |
wsse:Kerberosv5TGT | Kerberos 的 5.3.1 节中定义的 Kerberos v5 票据。这个 ValueType 在票据为赋予票据的票据(ticket granting ticket,TGT)时使用。 |
wsse:Kerberosv5ST | Kerberos 的 5.3.1 节中定义的 Kerberos v5 票据。这个 ValueType 在票据为服务票据(service ticket,ST)时使用。 |
请注意,XML 签名也提供对 X.509 证书编码的机制。带有 ValueType="wsse:X509v3" 的 BinarySecurityToken 可以在由于编码而需要灵活性的时侯使用。另一方面,使用 ds:KeyInfo 可以在使用情况中提供另外的灵活性。
下面举例说明 BinarySecurityToken 的使用:
当签名中使用
时(也就是说从
元素引用它),应该注意规范算法(例如 专用 XML 规范化(Exclusive XML Canonicalization))不允许对属性或元素值中 QName 的名称空间前缀进行非授权的替换。如果该令牌不带有签署密钥(而且它因此没有加密地绑定到签名上),我们就特别推荐在
元素内部声明这些名称空间前缀。举例来说,如果我们希望对前面的示例签名,那么我们就需要加入使用的名称空间定义。下面的示例中使用了一个定制的 ValueType。因此,这个 ValueType 的名称空间定义就包括在
元素中。请注意,与 wsse 在编码类型和元素中的使用相同,这里也包括它的定义。
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...
当 Kerberos 票据作为签名密钥引用时,签名算法应该是一个散列的消息认证码。我们特别推荐使用 HMAC-SHA1(XML 签名所需),它的票据中的会话密钥作为共享的密钥使用。
4.3. SecurityTokenReference 元素
安全性令牌传送一组声明。有时候这些声明驻留在其它某些地方,需要接收的应用程序将它们“拉”出来。
元素提供了一种引用安全性令牌的可扩展机制。
下面说明该元素的句法:
<SecurityTokenReference Id="...">
<Reference URI="..."/>
</SecurityTokenReference>
下面将描述上面定义的元素:
/SecurityTokenReference
该元素提供对安全性令牌的引用。
/SecurityTokenReference/@Id
此安全性令牌引用的一个字符串标签
/SecurityTokenReference/Reference
该元素用于标识定位安全性令牌的 URI 位置。
/SecurityTokenReference/Reference/@URI
该属性指定在何处查找安全性令牌的 URI。
/SecurityTokenReference/{any}
这是一种允许根据模式传送不同(可扩展)类型的安全性信息的扩展性机制。
/SecurityTokenReference/@{any}
这是一种允许根据模式向报头添加其它属性的扩展性机制。
下面举例说明该元素的使用:
xmlns:wsse="
http://schemas.xmlsoap.org/ws/2002/04/secext
">
URI="
http://www.fabrikam123.com/tokens/Zoe#X509token"/
>
该元素还可以被用作
的一个直接子元素,用来表明从其它某些地方的安全性令牌检索密钥信息的暗示。在使用 XML 签名和 XML 加密时,我们特别推荐将
元素放在
内来引用用于签名或加密的安全性令牌。
4.4. ds:KeyInfo
对于某些密钥类型(如 X.509 证书)来说,
元素(来自 XML 签名)和
元素都可以用于传送密钥信息。
元素虑及了不同密钥类型和将来的扩展性。然而,在本规范中,如果密钥类型在第 4.2 节中很好地定义过,那么使用
就是我们推荐用于传送密钥信息的方式。
下面的示例说明使用该元素获取命名过的密钥的过程:
http://www.w3.org/2000/09/xmldsig
#">
CN=Hiroshi Maruyama, C=JP
4.5. ds:Signature
消息发送方可能希望让消息接收方能够决定消息是否在传输过程中更改过,并验证消息是由特定安全性令牌持有人发送的。
当 XML 签名与 元素同时使用时,消息签署人的安全性令牌可能被关联,而安全性令牌声明和消息之间会以应用程序估计的方式产生映射。
由于某些 SOAP 报头的不稳定性,发送者绝不能使用 XML 签名中定义的封装的签名转换。相反,消息应该显式包括要签署的所需元素。类似地,发送方绝不能使用 XML 签名中定义的封装签名。
本规范虑及多个签名附加在消息中的情况,这时每个签名都引用不同、甚至重叠的消息部分。这对于很多分布式应用程序都是很重要的,在这些应用程序程序中,消息要经过多个处理阶段。举例来说,发送方可能提交一个包含 orderID 报头的订单。发送方签署 orderID 报头和请求的主体(订单的内容)。当订单处理子系统收到这个时,它可能向报头插入一个 shippingID。发出订单的子系统然后会签署(最少)orderID 和 shippingID,可能还有请求主体。然后当运输部门处理和交付该订单后,可能会附加一个 shippedInfo 报头。运输部门将签署(最少)shippedInfo 和 shippingID,可能还有请求主体,然后将消息转发给记帐部门进行处理。记帐部门可以验证签名并决定订单的有效信任链,以及各个角色所做的事情。
所有依从的实现都必须能够处理 元素。
4.5.1. 算法
WS-Security 规范建立在 XML 签名的基础之上,因此具有与 XML 签名规范中指定的相同的算法需求。
下面的表描述了 WS-Security 推荐的其它算法:
算法类型 | 算法 | 算法 URI |
规范化 | 专用 XML 规范化 | 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 应用程序必须满足下面的条件:
应用程序必须能够处理 XML 签名规范中定义的所需元素。
要向 <Security> 报头块添加签名,应该预先考虑与 XML 签名规范一致的 <ds:Signature> 元素,下来才是已有的 <Security> 报头块的内容。也就是说,新信息要在旧信息之前(优先)。签名中包含的所有 <ds:Reference> 元素都应该引用包含它的 SOAP 信封内(或附件中)的资源。
如 XML 签名规范中所示,XPath 过滤可以用于指定将签署的对象。然而,因为 SOAP 消息交换模型允许中介体应用程序修改信封(如添加或删除报头块),XPath 过滤在消息传递之后并不总能得到相同对象。使用 XPath 过滤时应该注意避免因为这种修改导致后来的验证失败。
中介体应用程序修改的问题不仅仅在 XPath 处理中才会发生。由于规范化和分类的原因,数字签名是这种关系的特别脆弱的例子。如果消息处理整体要保持健壮,中介体必须注意转换不会出现在数字签名组件的范围中。
鉴于和名称空间有关的安全性注意事项,本规范强烈推荐您使用提供相同或更多保护的“专用 XML 规范化(Exclusive XML Canonicalization)”算法或其它标准化算法。
4.5.3. 验证完整性
如果发生下列情况,<Security> 报头块中 <ds:Signature> 条目的验证就会失败:
条目内容的句法不遵守本规范,或者根据 XML 签名的核心验证,条目中包含的签名的验证失败,或者应用自己的信任策略的应用程序因为某种原因拒绝消息(例如,签名由非信任的密钥创建 — 验证前两个步骤只会执行对签名加密的验证)。
如果签名验证失败,那么应用程序可能会使用第 6 节中定义的错误代码向发送者报告失败情况。
4.5.4. 示例
下面的样本消息举例说明了完整性和安全性令牌的使用。对于本示例,我们使用了假定的“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">
<m:action>http://fabrikam123.com/getQuote</m:action>
<m:to>http://fabrikam123.com/stocks</m:to>
<m:from>mailto:johnsmith@fabrikam123.com</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>
<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 Encryption)标准。我们将特别描述如何在 <Security> 报头块中使用三个元素(下面列出的和 XML 加密中定义的)。当发送方或中介体使用 XML 加密对部分 SOAP 消息加密时,它们会向 <Security> 报头块添加子元素。此外,加密方还必须预先考虑在 <Security> 报头块中使用子元素作为应该对加密部分解密的目标接收方。组合加密部分消息和添加其中一个引用加密部分的子元素的过程以后就被称为加密步骤。子元素应该有足够信息,好让接收方可以识别消息的那些部分要由接收方解密。
4.6.1. xenc:ReferenceList
在加密 SOAP 消息内的元素或元素内容时,您可以使用 XML 加密的 <xenc:ReferenceList> 元素来创建加密部分的证明,它被表示为信封内的 <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 类型由附件使用时才适用)。
附件的内容必须被加密八位串代替。
被替换的 MIME 部分的媒体类型必须是 application/octet-stream。
附件的原始媒体类型必须在 <xenc:EncryptedData> 元素的 MimeType 属性中声明。
加密的 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>)。
创建新的 SOAP 信封。
根据加密类型,在 <Security> 报头块中创建 <xenc:ReferenceList> 子元素、<xenc:EncryptedKey> 子元素或 <xenc:EncryptedData> 子元素(请注意,SOAP “actor”和“mustUnderstand”属性是否不同,不同就需要一个新的报头表)。
定位要加密的数据项,也就是 XML 元素、目标 SOAP 信封中的元素内容和附件。
如下所示加密数据:对于目标 SOAP 信封中的每个 XML 元素或元素内容来说,根据 XML 加密规范的处理规则进行加密。每个已选择的原始元素或元素内容都由最后的 <xenc:EncryptedData> 元素删除和替换。对附件来说,内容则必须由加密的密码数据替换,如章节 4.5.3. 中所示。
<xenc:EncryptedData> 元素中可选的 <ds:KeyInfo> 可以引用另一个 <ds:KeyInfo> 元素。请注意,如果加密是基于附加的安全性令牌的,那么就应该向 <ds:KeyInfo> 元素添加一个 <SecurityTokenReference> 元素以便于定位它。
创建一个引用生成的 <xenc:EncryptedData> 元素的 <xenc:DataReference> 元素。向 <xenc:ReferenceList> 添加 <xenc:DataReference>。
解密
当收到带有加密报头条目的 SOAP 信封时,对于每个加密报头来说都应该进行下面的一般步骤(非标准的):
定位要解密的 <xenc:EncryptedData> 项(可能使用 <xenc:ReferenceList>)。
如下进行解密:对于目标 SOAP 信封中的每个元素,根据 XML 加密规范的处理规则和上面列出的处理规则进行解密。
如果解密数据是附件的一部分而且使用了 MIME 类型,那么将附件的 MIME 类型改为原始 MIME 类型(如果存在)。
如果因为某种原因解密失败,应用程序就可以使用第 6 节中定义的错误代码向发送方报告失败情况。
5. 扩展示例
下面的样本消息举例说明了安全性令牌、签名和加密的使用。对于本示例,我们使用了假定的“RoutingTransform”,它将选择不可变的路由报头以及消息主体。
(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:johnsmith@fabrikam123.com</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>d2FpbmdvbGRfE0lm4byV0...
(021) </xenc:CipherValue>
(022) </xenc:CipherData>
(023) <xenc:ReferenceList>
(024) <xenc:DataReference URI="#enc1"/>
(025) </xenc:ReferenceList>
(026) </xenc:EncryptedKey>
(027) <ds:Signature>
(028) <ds:SignedInfo>
(029) <ds:CanonicalizationMethod
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
(030) <ds:SignatureMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
(031) <ds:Reference>
(032) <ds:Transforms>
(033) <ds:Transform
Algorithm="http://...#RoutingTransform"/>
(034) <ds:Transform
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
(035) </ds:Transforms>
(036) <ds:DigestMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
(037) <ds:DigestValue>LyLsF094hPi4wPU...
(038) </ds:DigestValue>
(039) </ds:Reference>
(040) </ds:SignedInfo>
(041) <ds:SignatureValue>
(042) Hp1ZkmFZ/2kQLXDJbchm5gK...
(043) </ds:SignatureValue>
(044) <ds:KeyInfo>
(045) <wsse:SecurityTokenReference>
(046) <wsse:Reference URI="#X509Token"/>
(047) </wsse:SecurityTokenReference>
(048) </ds:KeyInfo>
(049) </ds:Signature>
(050) </wsse:Security>
(051) </S:Header>
(052) <S:Body>
(053) <xenc:EncryptedData
Type="http://www.w3.org/2001/04/xmlenc#Element"
Id="enc1">
(054) <xenc:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#3des-cbc"/>
(055) <xenc:CipherData>
(056) <xenc:CipherValue>d2FpbmdvbGRfE0lm4byV0...
(057) </xenc:CipherValue>
(058) </xenc:CipherData>
(059) </xenc:EncryptedData>
(060) </S:Body>
(061) </S:Envelope>
让我们来回顾本示例中一些关密钥的部分:
行(003)到(051)包含 SOAP 消息报头。
行(004)到(009)指定消息路由信息(如 WS-Routing 定义的)。在本示例中,我们发送消息到 http://fabrikam123.com/stocks 服务,请求“getQuote”操作。
行(010)到(050)表示 <Security> 报头块。它包含消息的与安全性相关的信息。
行(011)到(013)指定与消息关联的安全性令牌。在本示例中,它指定按 Base64 编码的 X.509 证书。行(012)指定该证书的实际 Base64 编码。
行(014)到(026)指定用于加密消息主体的密钥。因为这是一个对称密钥,所以它是以加密形式传送的。行(015)定义用于加密密钥的算法。行(016)到(018)指定用于加密对称密钥的密钥的名称。行(019)到(022)指定对称密钥实际的加密形式。行(023)到(025)识别消息中使用该对称密钥的加密块。在本示例中,它只用于加密消息主体(Id="enc1")。
行(027)到(047)指定数字签名。在本示例中,签名是基于 X.509 证书的。行(028)到(040)表明签署什么。行(029)表明规范化算法(本示例中是排它的)。行(030)表明签名算法(在本示例中是 sha1 上的 rsa)。
行(031)到(039)标识正在被签署的消息部分。行(033)特别标识"转换"。这个假定的转换将选择路由报头和消息主体不变的部分。行(034)指定行(033)所选择的消息部分上要使用的规范化算法。行(036)表明规范化数据上的分类算法使用。行(037)指定规范化数据上的指定算法得出的分类值。
行(041)到(043)表明实际的签名值 — 在行(042)指定。
行(044)到(048)表明用于签名的密钥。在本示例中,它是消息中包括的 X.509 证书。行(046)提供对行(011)到(013)的 URI 链接。
消息主体是由行(052)到(060)表示的。
行(053)到(059)表示加密的元数据和使用 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 |
7. 安全注意事项
强烈推荐消息包含数字化签署元素,以允许消息接收者在消息通过开放网络进行交换的时候检测消息的重播。这些元素可能是消息的一部分或从其它 SOAP 扩展定义的报头的一部分。四种典型的方式是:
时间戳
序列号
有效期
消息相关
本规范定义了 XML 签名和 XML 加密在 SOAP 报头中的使用。作为保证 SOAP 消息的安全的构件之一,它常常与其它安全技术联合使用。数字签名需要在其它安全机制的上下文中被理解,也需要在对实体的可能威胁的上下文中被理解。
仅仅数字签名并不提供消息认证。别人可以记录一条签名消息并将它重发(一个重演攻击)。为了预防这种类型的攻击,数字签名必须结合一种适当的办法来确保消息的唯一性,例如,时间戳或序列号(请参阅前面的部分了解更多细节)。
当用数字签名来验证发送方的身份时,发送者必须证明它拥有私钥。实现这一点的一种办法是使用问询-响应(challenge-response)类型的协议。这类协议已超出本文档的范围。
为了这个目标,开发者可以把时间戳、有效期和序列号附加到消息上。
实现者还应意识到,所有的安全问题都是普遍地使用数字签名和特殊地使用 XML 签名的结果。当要在基于数字签名的应用程序中构建信任时,还必须结合其它的技术(如证书评估),但这些已超出本文档的范围。
请求者应使用数字签名来签署不包含签名(或其它保护机制)的安全性令牌,以确保它们在传输中未被更改。
此外,如在 XML 加密中所述,我们注意到了在公共数据项上同时使用签署和加密可能会带来一些加密薄弱环节。例如,加密数字化签名数据,同时使数字签名不受攻击,可能会允许明文猜测攻击。应用程序设计者应该小心谨慎,不要引入这样的薄弱环节。