SSL/TLS原理详解与WCF中的WS-Security
Posted chary
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SSL/TLS原理详解与WCF中的WS-Security相关的知识,希望对你有一定的参考价值。
SSL/TLS作为一种互联网安全加密技术
1. SSL/TLS概览
1.1 整体结构
SSL是一个介于HTTP协议与TCP之间的一个可选层,其位置大致如下:
- SSL:(Secure Socket Layer,安全套接字层),为Netscape所研发,用以保障在Internet上数据传输之安全,利用数据加密(Encryption)技术,可确保数据在网络上之传输过程中不会被截取。当前版本为3.0。它已被广泛地用于Web浏览器与服务器之间的身份认证和加密数据传输。
SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。SSL协议可分为两层: SSL记录协议(SSL Record Protocol):它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能的支持。 SSL握手协议(SSL Handshake Protocol):它建立在SSL记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。 - TLS:(Transport Layer Security,传输层安全协议),用于两个应用程序之间提供保密性和数据完整性。
TLS 1.0是IETF(Internet Engineering Task Force,Internet工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本,可以理解为SSL 3.1,它是写入了?RFC?的。该协议由两层组成: TLS 记录协议(TLS Record)和 TLS 握手协议(TLS Handshake)。较低的层为 TLS 记录协议,位于某个可靠的传输协议(例如 TCP)上面。
SSL/TLS协议提供的服务主要有:
- 认证用户和服务器,确保数据发送到正确的客户机和服务器;
- 加密数据以防止数据中途被窃取;
- 维护数据的完整性,确保数据在传输过程中不被改变。
1.2 TLS与SSL的差异
- 版本号:TLS记录格式与SSL记录格式相同,但版本号的值不同,TLS的版本1.0使用的版本号为SSLv3.1。
- 报文鉴别码:SSLv3.0和TLS的MAC算法及MAC计算的范围不同。TLS使用了RFC-2104定义的HMAC算法。SSLv3.0使用了相似的算法,两者差别在于SSLv3.0中,填充字节与密钥之间采用的是连接运算,而HMAC算法采用的是异或运算。但是两者的安全程度是相同的。
- 伪随机函数:TLS使用了称为PRF的伪随机函数来将密钥扩展成数据块,是更安全的方式。
- 报警代码:TLS支持几乎所有的SSLv3.0报警代码,而且TLS还补充定义了很多报警代码,如解密失败(decryption_failed)、记录溢出(record_overflow)、未知CA(unknown_ca)、拒绝访问(access_denied)等。
- 密文族和客户证书:SSLv3.0和TLS存在少量差别,即TLS不支持Fortezza密钥交换、加密算法和客户证书。
- certificate_verify和finished消息:SSLv3.0和TLS在用certificate_verify和finished消息计算MD5和SHA-1散列码时,计算的输入有少许差别,但安全性相当。
- 加密计算:TLS与SSLv3.0在计算主密值(master secret)时采用的方式不同。
- 填充:用户数据加密之前需要增加的填充字节。在SSL中,填充后的数据长度要达到密文块长度的最小整数倍。而在TLS中,填充后的数据长度可以是密文块长度的任意整数倍(但填充的最大长度为255字节),这种方式可以防止基于对报文长度进行分析的攻击。
TLS的主要增强内容
TLS的主要目标是使SSL更安全,并使协议的规范更精确和完善。TLS 在SSL v3.0 的基础上,提供了以下增强内容:
- 更安全的MAC算法
- 更严密的警报
- "灰色区域"规范的更明确的定义
TLS对于安全性的改进
- 对于消息认证使用密钥散列法:TLS 使用"消息认证代码的密钥散列法"(HMAC),当记录在开放的网络(如因特网)上传送时,该代码确保记录不会被变更。SSLv3.0还提供键控消息认证,但HMAC比SSLv3.0使用的(消息认证代码)MAC 功能更安全。
- 增强的伪随机功能(PRF):PRF生成密钥数据。在TLS中,HMAC定义PRF。PRF使用两种散列算法保证其安全性。如果任一算法暴露了,只要第二种算法未暴露,则数据仍然是安全的。
- 改进的已完成消息验证:TLS和SSLv3.0都对两个端点提供已完成的消息,该消息认证交换的消息没有被变更。然而,TLS将此已完成消息基于PRF和HMAC值之上,这也比SSLv3.0更安全。
- 一致证书处理:与SSLv3.0不同,TLS试图指定必须在TLS之间实现交换的证书类型。
- 特定警报消息:TLS提供更多的特定和附加警报,以指示任一会话端点检测到的问题。TLS还对何时应该发送某些警报进行记录。
2. 密钥协商过程——TLS握手
SSL协议分为两部分:Handshake Protocol和Record Protocol。其中Handshake Protocol用来协商密钥,协议的大部分内容就是通信双方如何利用它来安全的协商出一份密钥。 Record Protocol则定义了传输的格式。
由于非对称加密的速度比较慢,所以它一般用于密钥交换,双方通过公钥算法协商出一份密钥,然后通过对称加密来通信,当然,为了保证数据的完整性,在加密前要先经过HMAC的处理。
SSL缺省只进行server端的认证,客户端的认证是可选的。以下是其流程图(摘自TLS协议)。
2.1 客户端发出请求(ClientHello)
由于客户端(如浏览器)对一些加解密算法的支持程度不一样,但是在TLS协议传输过程中必须使用同一套加解密算法才能保证数据能够正常的加解密。在TLS握手阶段,客户端首先要告知服务端,自己支持哪些加密算法,所以客户端需要将本地支持的加密套件(Cipher Suite)的列表传送给服务端。除此之外,客户端还要产生一个随机数,这个随机数一方面需要在客户端保存,另一方面需要传送给服务端,客户端的随机数需要跟服务端产生的随机数结合起来产生后面要讲到的 Master Secret 。
综上,在这一步,客户端主要向服务器提供以下信息:
- 支持的协议版本,比如TLS 1.0版
- 一个客户端生成的随机数,稍后用于生成"对话密钥"
- 支持的加密方法,比如RSA公钥加密
- 支持的压缩方法
2.2 服务器回应(SeverHello)
上图中,从Server Hello到Server Done,有些服务端的实现是每条单独发送,有服务端实现是合并到一起发送。Sever Hello和Server Done都是只有头没有内容的数据。
服务端在接收到客户端的Client Hello之后,服务端需要将自己的证书发送给客户端。这个证书是对于服务端的一种认证。例如,客户端收到了一个来自于称自己是www.alipay.com的数据,但是如何证明对方是合法的alipay支付宝呢?这就是证书的作用,支付宝的证书可以证明它是alipay,而不是财付通。证书是需要申请,并由专门的数字证书认证机构(CA)通过非常严格的审核之后颁发的电子证书。颁发证书的同时会产生一个私钥和公钥。私钥由服务端自己保存,不可泄漏。公钥则是附带在证书的信息中,可以公开的。证书本身也附带一个证书电子签名,这个签名用来验证证书的完整性和真实性,可以防止证书被串改。另外,证书还有个有效期。
在服务端向客户端发送的证书中没有提供足够的信息(证书公钥)的时候,还可以向客户端发送一个 Server Key Exchange,
此外,对于非常重要的保密数据,服务端还需要对客户端进行验证,以保证数据传送给了安全的合法的客户端。服务端可以向客户端发出 Cerficate Request 消息,要求客户端发送证书对客户端的合法性进行验证。比如,金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供USB密钥,里面就包含了一张客户端证书。
跟客户端一样,服务端也需要产生一个随机数发送给客户端。客户端和服务端都需要使用这两个随机数来产生Master Secret。
最后服务端会发送一个Server Hello Done消息给客户端,表示Server Hello消息结束了。
综上,在这一步,服务器的回应包含以下内容:
- 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信
- 一个服务器生成的随机数,稍后用于生成"对话密钥"
- 确认使用的加密方法,比如RSA公钥加密
- 服务器证书
2.3 客户端回应(Certificate Verify)
Client Key Exchange
如果服务端需要对客户端进行验证,在客户端收到服务端的 Server Hello 消息之后,首先需要向服务端发送客户端的证书,让服务端来验证客户端的合法性。
Certificate Verify
接着,客户端需要对服务端的证书进行检查,如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。如果证书没有问题,客户端就会从服务器证书中取出服务器的公钥。然后,向服务器发送下面三项信息:
- 一个随机数。该随机数用服务器公钥加密,防止被窃听
- 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送
- 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验
上面第一项的随机数,是整个握手阶段出现的第三个随机数,它是客户端使用一些加密算法(例如:RSA, Diffie-Hellman)产生一个48个字节的Key,这个Key叫 PreMaster Secret,很多材料上也被称作 PreMaster Key。
ChangeCipherSpec
ChangeCipherSpec是一个独立的协议,体现在数据包中就是一个字节的数据,用于告知服务端,客户端已经切换到之前协商好的加密套件(Cipher Suite)的状态,准备使用之前协商好的加密套件加密数据并传输了。
在ChangecipherSpec传输完毕之后,客户端会使用之前协商好的加密套件和Session Secret加密一段 Finish 的数据传送给服务端,此数据是为了在正式传输应用数据之前对刚刚握手建立起来的加解密通道进行验证。
2.4 服务器的最后回应(Server Finish)
服务端在接收到客户端传过来的 PreMaster 加密数据之后,使用私钥对这段加密数据进行解密,并对数据进行验证,也会使用跟客户端同样的方式生成 Session Secret,一切准备好之后,会给客户端发送一个 ChangeCipherSpec,告知客户端已经切换到协商过的加密套件状态,准备使用加密套件和 Session Secret加密数据了。之后,服务端也会使用 Session Secret 加密一段 Finish 消息发送给客户端,以验证之前通过握手建立起来的加解密通道是否成功。
根据之前的握手信息,如果客户端和服务端都能对Finish信息进行正常加解密且消息正确的被验证,则说明握手通道已经建立成功,接下来,双方可以使用上面产生的Session Secret对数据进行加密传输了。
2.5 几个secret
Secret Keys
上面的分析和讲解主要是为了突出握手的过程,所以PreMaster secret,Master secret,session secret都是一代而过,但是对于Https,SSL/TLS深入的理解和掌握,这些Secret Keys是非常重要的部分。所以,准备把这些Secret Keys抽出来单独分析和讲解。
我们先来看看这些Secret Keys的生成过程以及作用流程图:
PreMaster secret
PreMaster Secret是在客户端使用RSA或者Diffie-Hellman等加密算法生成的。它将用来跟服务端和客户端在Hello阶段产生的随机数结合在一起生成 Master Secret。在客户端使用服务端的公钥对PreMaster Secret进行加密之后传送给服务端,服务端将使用私钥进行解密得到PreMaster secret。也就是说服务端和客户端都有一份相同的PreMaster secret和随机数。
PreMaster secret前两个字节是TLS的版本号,这是一个比较重要的用来核对握手数据的版本号,因为在Client Hello阶段,客户端会发送一份加密套件列表和当前支持的SSL/TLS的版本号给服务端,而且是使用明文传送的,如果握手的数据包被破解之后,攻击者很有可能串改数据包,选择一个安全性较低的加密套件和版本给服务端,从而对数据进行破解。所以,服务端需要对密文中解密出来对的PreMaster版本号跟之前Client Hello阶段的版本号进行对比,如果版本号变低,则说明被串改,则立即停止发送任何消息。
关于PreMaster Secret(Key)的计算请参考?Https SSL/TLS PreMaster/Master Secret(Key)计算。
Master secret
上面已经提到,由于服务端和客户端都有一份相同的PreMaster secret和随机数,这个随机数将作为后面产生Master secret的种子,结合PreMaster secret,客户端和服务端将计算出同样的Master secret。
Master secret是有系列的hash值组成的,它将作为数据加解密相关的secret的 Key Material 的一部分。Key Material最终解析出来的数据如下:
其中,write MAC key,就是session secret或者说是session key。Client write MAC key是客户端发数据的session secret,Server write MAC secret是服务端发送数据的session key。MAC(Message Authentication Code),是一个数字签名,用来验证数据的完整性,可以检测到数据是否被串改。
关于Session Secret(Key)的计算请参考?Https SSL/TLS Session Secret(Key)计算。
2.6 应用数据传输
在所有的握手阶段都完成之后,就可以开始传送应用数据了。应用数据在传输之前,首先要附加上MAC secret,然后再对这个数据包使用write encryption key进行加密。在服务端收到密文之后,使用Client write encryption key进行解密,客户端收到服务端的数据之后使用Server write encryption key进行解密,然后使用各自的write MAC key对数据的完整性包括是否被串改进行验证。
2.7 总结
SSL客户端(也是TCP的客户端)在TCP链接建立之后,发出一个ClientHello来发起握手,这个消息里面包含了自己可实现的算法列表和其它一些需要的消息,SSL的服务器端会回应一个ServerHello,这里面确定了这次通信所需要的算法,然后发过去自己的证书(里面包含了身份和自己的公钥)。Client在收到这个消息后会生成一个秘密消息,用SSL服务器的公钥加密后传过去,SSL服务器端用自己的私钥解密后,会话密钥协商成功,双方可以用同一份会话密钥来通信了。
3. 附:密钥协商的形象化比喻
如果上面的说明不够清晰,这里我们用个形象的比喻,我们假设A与B通信,A是SSL客户端,B是SSL服务器端,加密后的消息放在方括号[]里,以突出明文消息的区别。双方的处理动作的说明用圆括号()括起。
A:我想和你安全的通话,我这里的对称加密算法有DES,RC5,密钥交换算法有RSA和DH,摘要算法有MD5和SHA。
B:我们用DES-RSA-SHA这对组合好了。
这是我的证书,里面有我的名字和公钥,你拿去验证一下我的身份(把证书发给A)。
目前没有别的可说的了。
A:(查看证书上B的名字是否无误,并通过手头早已有的CA的证书验证了B的证书的真实性,如果其中一项有误,发出警告并断开连接,这一步保证了B的公钥的真实性)
(产生一份秘密消息,这份秘密消息处理后将用作加密密钥,加密初始化向量(IV)和hmac的密钥。将这份秘密消息-协议中称为per_master_secret-用B的公钥加密,封装成称作ClientKeyExchange的消息。由于用了B的公钥,保证了第三方无法窃听)
我生成了一份秘密消息,并用你的公钥加密了,给你(把ClientKeyExchange发给B)
注意,下面我就要用加密的办法给你发消息了!
(将秘密消息进行处理,生成加密密钥,加密初始化向量和hmac的密钥)
[我说完了]
B:(用自己的私钥将ClientKeyExchange中的秘密消息解密出来,然后将秘密消息进行处理,生成加密密钥,加密初始化向量和hmac的密钥,这时双方已经安全的协商出一套加密办法了)
注意,我也要开始用加密的办法给你发消息了!
[我说完了]
A: [我的秘密是...]
B: [其它人不会听到的...]
4. SSL安全性
SecurityPortal在2000年底有一份文章《The End of SSL and SSH?》激起了很多的讨论, 目前也有一些成熟的工具如dsniff(http://www.monkey.org/~dugsong/dsniff/)可以通过man in the middle攻击来截获https的消息。
从上面的原理可知,SSL的结构是严谨的,问题一般出现在实际不严谨的应用中。常见的攻击就是middle in the middle攻击,它是指在A和B通信的同时,有第三方C处于信道的中间,可以完全听到A与B通信的消息,并可拦截,替换和添加这些消息。
- SSL可以允许多种密钥交换算法,而有些算法,如DH,没有证书的概念,这样A便无法验证B的公钥和身份的真实性,从而C可以轻易的冒充,用自己的密钥与双方通信,从而窃听到别人谈话的内容。
而为了防止middle in the middle攻击,应该采用有证书的密钥交换算法。 - 有了证书以后,如果C用自己的证书替换掉原有的证书之后,A的浏览器会弹出一个警告框进行警告,但又有多少人会注意这个警告呢?
- 由于美国密码出口的限制,IE,netscape等浏览器所支持的加密强度是很弱的,如果只采用浏览器自带的加密功能的话,理论上存在被破解可能。
5. 代理
下面探讨一下SSL的代理是怎样工作的
当在浏览器里设置了https的代理,而且里输入了https://www.example.com之后,浏览器会与proxy建立tcp链接,然后向其发出这么一段消息:
CONNECT server.example.com:443 HTTP/1.1
Host: server.example.com:443
然后proxy会向webserver端建立tcp连接,之后,这个代理便完全成了个内容转发装置。浏览器与web server会建立一个安全通道,因此这个安全通道是端到端的,尽管所有的信息流过了proxy,但其内容proxy是无法解密和改动的(当然要由证书的支持,否则这个地方便是个man in the middle攻击的好场所,见上面的安全部分)。
CA证书以及如何使用OpenSSL自签署,见文章OpenSSL自签署证书?。
6. 参考
- Https(SSL/TLS)原理详解
- SSL与TLS的区别以及介绍
- SSL/TLS协议运行机制的概述
- SSL/TLS/WTLS原理
- Transport Layer Security (TLS)
- 传输层安全协议
- Survival guides - TLS/SSL and SSL (X.509) Certificates
WS-* in WCF (5) – WS-Security in?WCF
Steps Overview to configure WS-Security in WCF
在WCF中配置WS-Security
Bindings and Behaviors
In general WCF security can be configured using Bindings and Behaviors.
- Using Bindings you can configure message protection and authentication types.
- Using Behaviors you can configure credentials to be used for message protection and authentication as well as credential validation settings
Security Configuration settings – just like the majority of WCF configurations – can be set in the configuration files or programmatically.?There are some exceptions to this rule where some configuration can be set only by code; for example, setting usernames and passwords can only be done programmatically in order not to allow developers to hard code these values in the configuration file.
绑定和行为
通常WCF安全性可以使用绑定和行为进行配置。
- 使用绑定您可以配置消息保护和身份验证类型。
- 使用行为,您可以配置用于消息保护和身份验证的凭证以及凭证验证设置
安全配置设置 - 就像大多数WCF配置 - 可以在配置文件中设置或以编程方式设置。这个规则有一些例外,其中一些配置只能由代码来设置;?例如,设置用户名和密码只能以编程方式完成,以免开发人员在配置文件中硬编码这些值。
Overview of steps to configure WS-Security
配置WS-Security的步骤概述
WCF provides a configuration model to set every aspect of WS-Security. This configuration can be achieved in 3 steps:
In Step1, we set the Basic Message Security Settings:
- First, you configure the service to use a binding that supports WS-Security. As is the case in most examples in this course, I will be using the WSHttpBinding
- You then set the service to use Message security. For some bindings, this is the default security mode anyway, but explicit configuration is required when you need to edit the default settings.
- Then you select the sensitive data you want to secure. Recall that a main advantage of message security over transport security is the ability to selectively secure parts of the message, thus reducing overhead.
WCF提供了一个配置模型来设置WS-Security的每个方面。这种配置可以通过3个步骤来实现:
在步骤1中,我们设置基本信息安全设置:
- 首先,您将服务配置为使用支持WS-Security的绑定。与本课程中的大多数示例一样,我将使用WSHttpBinding
- 然后您将该服务设置为使用消息安全性。对于某些绑定,无论如何都是默认安全模式,但在需要编辑默认设置时需要显式配置。
- 然后你选择你想保护的敏感数据。回想一下,消息安全性相对于传输安全性的一个主要优势是能够有选择地保护部分消息,从而减少开销。
Next step is selecting the service credentials. These credentials will be used to secure the message exchange with the client. For example, when the service credential is set to X.509 certificate, the public key is given to the client to encrypt messages, while the private key is used by the service to sign the message and authenticate itself to the client.
These credentials will also be used to authenticate the service to the client. This scenario is known as mutual authentication.
Final step is to configure the authentication mechanism the services requires from its clients.?This includes setting the type of credentials the service is expecting from the client?and how the service will verify these credentials.
Now that I have given a brief overview about the steps required to configure WS-Security in WCF, in the next three sections, I will show you these steps in detail.
下一步是选择服务凭证。这些证书将用于保护与客户端的消息交换。例如,当服务凭证被设置为X.509证书时,公共密钥被赋予客户端以加密消息,而服务使用该私钥来签署消息并向客户端验证其自身。
这些凭据也将用于向客户端验证服务。这种情况被称为相互认证。
最后一步是配置服务所需的来自客户端的认证机制。这包括设置服务期望来自客户端的凭证类型以及服务如何验证这些凭证。
现在我已经简要介绍了在WCF中配置WS-Security所需的步骤,在接下来的三节中,我将详细介绍这些步骤。
Step1: Basic Message Security Settings
Security Mode
第1步:基本信息安全设置
安全模式
The first setting that you‘ll typically have to set is the Security Mode of the service. This is a binding configuration where you specify what kind of Message or Transport security you want to use for your service.
Lets quickly review the options:
- None: means that no security is applied. No authentication is required, and neither message privacy nor message accuracy is applied
- Transport: means that transport security is applied. As I explained before, this relies on SSL\\TLS.
- Message: means that security is applied using the WS-Security standard. This is the mode I will use throughout this module.
- Both: is supported only by MSMQ bindings, and uses both security and transport security models.
- TransportWithMessageCredentials, also uses both security model for authentication, and transport model for message protection.
- And finally, TransportCredentialOnly, uses transport security for authentication and no message protection.
您通常必须设置的第一个设置是服务的安全模式。这是一个绑定配置,您可以指定要为您的服务使用哪种消息或传输安全性。
让我们快速回顾一下选项:
- 无:表示不应用安全性。不需要验证,也不会应用消息隐私和消息准确性
- 运输:意味着运输安全适用。正如我之前解释的,这依赖于SSL \\ TLS。
- 消息:表示使用WS-Security标准应用安全性。这是我将在整个模块中使用的模式。
- 两者:仅受MSMQ绑定支持,并使用安全和传输安全模型。
- TransportWithMessageCredentials也使用安全模型进行身份验证,使用传输模型进行消息保护。
- 最后,TransportCredentialOnly使用传输安全性进行身份验证,并且没有消息保护。
Protection Level
保护级别
When the Message security mode is set as I showed you before, by default, WCF encrypts and signs all message exchanges. However, as I explained before, one of the primary advantages of message security is the ability to select only sensitive portions of a message to secure. Therefore, WCF provides the ability to change the protection level.
Protection level can be set on a service contract, meaning that the setting you chose will apply on all operations within this contract.
当按照我之前向您展示的消息安全模式设置时,默认情况下,WCF将加密并签署所有消息交换。但是,正如我之前解释的,消息安全的主要优点之一是只能选择消息的敏感部分来保证安全。因此,WCF提供了更改保护级别的功能。
可以在服务合同上设置保护级别,这意味着您选择的设置将适用于本合同中的所有操作。
For more control, you can set it on the operation level, to selectively indicate which operation calls to be secured.
对于更多控制,您可以在操作级别上进行设置,以选择性地指示要保护哪些操作调用。
Now once you decide on the scope or level of the protection, you can set it into one of 3 options:
现在,一旦决定了保护的范围或级别,您可以将其设置为以下三种选项之一:
- None: turns off signing and encryption on the operation or the interface
- Sign: applies signature on the operation or the interface, without encryption
- And EncryptAndSign, which is the default option, applies both encryption and signature on the operation or the interface
Using these options, you can now select what sensitive data you want to secure. For example, here I applied the None protection level on a non-sensitive operation, while I used the EncryptAndSign protection level on an operation which will exchange sensitive data:
- 无:关闭操作或界面上的签名和加密
- 签名:在操作或界面上应用签名,不加密
- 而作为默认选项的EncryptAndSign在操作或界面上应用加密和签名
使用这些选项,您现在可以选择要保护的敏感数据。例如,在这里我将非保护级别应用于非敏感操作,而我将EncryptAndSign保护级别用于交换敏感数据的操作:
Algorithm Suite
算法套件
The algorithm suite setting sets the algorithm used to generate the keys required to implement encryption and signature.
As explained before, to get the best possible security with the least possible overhead, many of the practical implementations use a combination of symmetric and asymmetric algorithms to achieve message security. So the algorithm suite setting typically represents two algorithms: an asymmetric algorithm for deriving a symmetric key, and a symmetric algorithm for encrypting and signing messages using the derived symmetric key.
By default, WCF uses Basic256, which uses RSA-OAEP as the asymmetric algorithm, and AES256 as the symmetric one.
One note worth making here: as is the case in every interoperable scenario, in case your WCF application is exchanging messages with a non-WCF application, then make sure to use an algorithm suite that supported by the other platform. Using different algorithms will fail the message communication.
算法套件设置设置用于生成实现加密和签名所需的密钥的算法。
如前所述,为了以尽可能少的开销获得尽可能好的安全性,许多实际实现都使用对称算法和非对称算法的组合来实现消息安全性。因此,算法套件设置通常代表两种算法:用于派生对称密钥的非对称算法和用于使用导出的对称密钥对消息进行加密和签名的对称算法。
默认情况下,WCF使用Basic256,它使用RSA-OAEP作为非对称算法,AES256作为对称算法。
值得一提的是:在每个可互操作的场景中,如果您的WCF应用程序正在与非WCF应用程序交换消息,请确保使用其他平台支持的算法套件。使用不同的算法将导致消息通信失败。
Step2: Service Credentials
Why Service Credentials?
第2步:服务凭证
为什么凭证服务?
Having configured the service to use message security and what operations to secure, the next step is to configure the credentials the service will use to secure message exchanges as well as for the service to authenticate itself to the client.
将服务配置为使用消息安全性以及要保护哪些操作后,下一步是配置服务将用于保护消息交换的凭据以及服务向客户端验证身份。
Sharing public key with clients
与客户共享公钥
The service defines a service certificate. The (public portion) certificate is given to the client in one of two ways:
- Either by setting negotiateServiceCredential = "true" in which case, the certificate is transmitted to the client at the beginning of the communication. However, negotiation happens using TLSNego protocol which is WCF specific and not interoperable. Therefore, I will not use this option.
- The other way, is any out of band mechanism so that the client stores the certificate in its certificate store.
The client now, having the public portion of the certificate, will be able to authenticate the service typically by verifying that the service certificate is signed by a CA that the client trusts; this means the client has the CA stored in its trusted CAs store.
The client can point to the certificate to verify in different methods, for example, here the client says that its expecting a service certificate with subject name of ServerCert, and the client will search for this certificate in its local store. Which means that exchanging the certificate should have happened before any message exchange (again, because negotiateServiceCredential is false).
该服务定义了一个服务证书。(公共部分)证书通过以下两种方式之一提供给客户:
- 通过设置negotiateServiceCredential ="true",在这种情况下,证书在通信开始时传送给客户端。但是,使用WCF特定且不可互操作的TLSNego协议进行协商。因此,我不会使用这个选项。
- 另一种方式是任何带外机制,以便客户端将证书存储在其证书存储中。
现在,拥有证书公共部分的客户端将能够验证服务,通常通过验证服务证书是由客户端信任的CA签署的;?这意味着客户端将CA存储在其可信的CA商店中。
客户端可以指向证书以不同的方法进行验证,例如,在这里客户说它期望一个服务证书,其主题名称为ServerCert,客户端将在其本地商店中搜索该证书。这意味着交换证书应该在任何消息交换之前发生(再次,因为negotiateServiceCredential为false)。
Message security
消息安全
Now the exact flow of how message security is achieved, varies depending on whether we are using the symmetric or asymmetric binding, and whether derived keys are enabled or not.?But anyway recall that WCF defaults to the symmetric binding with derived keys enabled. So for the sake of completeness, in summary message security flow goes as follows:
- On each request, the WCF client randomly generates a symmetric key.
- The client then derives two keys from this symmetric key. It uses one key to encrypt the request, and another key to sign the request.
- Now, the client uses the public key of the service certificate to encrypt the derived keys.
- It then embeds these encrypted keys in the request header. So the final result, is a message encrypted and signed using the two derived keys, and the derived keys themselves are encrypted using the service certificate public key
- When the request reaches the service, it uses its own private key, to decrypt the derived keys
- It then uses these keys to decrypt and verify the signature
- Now to generate the response, the service again uses the same derived keys to encrypt and sign the response message
- The client remembers the derived keys, so it again use those to decrypt and verify the signature of the response
现在确定消息安全性的确切流程取决于我们是使用对称绑定还是非对称绑定,以及派生密钥是否启用。但无论如何回想起WCF默认为启用了派生键的对称绑定。所以为了完整起见,总结来说,消息安全流程如下:
- 在每个请求上,WCF客户端会随机生成一个对称密钥。
- 然后客户端从这个对称密钥中派生出两个密钥。它使用一个密钥对请求进行加密,并使用另一个密钥对请求进行签名。
- 现在,客户端使用服务证书的公钥来加密衍生的密钥。
- 然后它将这些加密的密钥嵌入到请求头中。因此,最终的结果是使用两个派生密钥对消息进行加密和签名,并使用服务证书公钥对派生密钥本身进行加密
- 当请求到达服务时,它使用自己的私钥来解密派生的密钥
- 然后它使用这些密钥来解密和验证签名
- 现在为了生成响应,服务再次使用相同的派生密钥来加密和签名响应消息
- 客户端会记住派生密钥,因此它会再次使用这些密钥来解密和验证响应的签名
Step3: Client Authentication
Client Credential Type
第3步:客户端身份验证
客户端凭据类型
As implied by its name, the Client Credential Type specifies the authentication mechanism the service expects from its clients.
正如其名称所暗示的那样,客户机证书类型指定了服务期望从客户端获得的认证机制。
Clearly the options here vary depending on whether the Security Mode is set to Message or Transport security. For example, when using Transport security, you‘d expect to have Basic, and Digest authentication among the options.
In our case, we‘re interested in Message security, in which case, there are the following client credential types:
- None: means that no authentication is required. This is the same as anonymous access
- Windows: indicates that clients are authenticated using traditional Windows authentication through Kerberos or NTLM
- Username: means that clients are authenticated using WS-Security username tokens
- Certificate, on the other hand, indicates that clients are authenticated using WS-Security X.509 tokens
- Finally, IssuedToken, indicates that clients are authenticated using a token issued by a third party. This is commonly used in federated authentication scenarios, which you will see in detail in the next module.
In this article, you will see authentication using username and certificate tokens.
显然,这里的选项取决于安全模式是设置为消息还是传输安全性。例如,使用传输安全性时,您希望在选项中包含基本身份验证和摘要身份验证。
在我们的案例中,我们对Message安全性感兴趣,在这种情况下,存在以下客户机凭证类型:
- 无:表示不需要认证。这与匿名访问相同
- Windows:表示客户端使用传统Windows身份验证通过Kerberos或NTLM进行身份验证
- 用户名:表示客户端使用WS-Security用户名令牌进行身份验证
- 另一方面,证书表示客户端使用WS-Security X.509令牌进行身份验证
- 最后,IssuedToken表示客户端使用第三方发布的令牌进行身份验证。这通常用于联合身份验证方案,您将在下一个模块中详细了解。
在本文中,您将看到使用用户名和证书令牌的身份验证。
Setting Certificate Authorities and Certificates
Setting up Sample Certificates
设置证书颁发机构和证书
设置示例证书
For working the next samples, you need service and client certificates.
In this section, I will show you how to set up these certificates as well as the certificate authorities used to sign them.?Of course, I won‘t be using any production certificates. Instead I will use makecert tool to create self-signed CAs, and then create certificates that are signed by these CAs.
To simulate a production deployment, I will use:
- one CA and one certificate for the service
- and another CA and certificate to the client
为了处理下一个样品,您需要服务和客户证书。
在本节中,我将向您介绍如何设置这些证书以及用于签名的证书颁发机构。当然,我不会使用任何生产证书。相反,我将使用makecert工具创建自签名CA,然后创建由这些CA签名的证书。
要模拟生产部署,我将使用:
- 一个CA和一个服务证书
- 并向客户提供另一个CA和证书
Service Certificates
To create the service CA, use the following command:
服务证书
要创建服务CA,请使用以下命令:
makecert -pe -n "CN=ServerCA" -ss my -sr LocalMachine -a sha1 -sky signature -r "ServerCA.cer"
- -pe: specifies that the private key is generated in the certificate and installed with it in the certificate store
- -n: specifies the subject name of the certificate
- -ss: specifies the store name. Here I‘m storing the certificate in the personal store
- -sr: specifies the store location. Here I‘m storing the certificate in the local machine store.?Together the –ss and –sr options means that I will be storing my certificate in the local machine store, in the personal store name
- The –a option specifies the hashing algorithm
- While the –sky option, specifies that this certificate will be used for digital signatures. Since this certificate will be acting as a CA, its purpose is to sign other certificates. That is also why I used option –pe to have the private key generated in the certificate; because it‘s the private key that will be used for signing.
- Finally, the –r option specifies that the certificate file will be self-signed
makecert -pe -n"CN = ServerCA"-ss my -sr LocalMachine -a sha1 -sky签名-r"ServerCA.cer"
- -pe:指定在证书中生成私钥并将其与证书存储一起安装
- -n:指定证书的主题名称
- -ss:指定商店名称。在这里,我将证书存储在个人商店中
- -sr:指定商店的位置。在这里,我将证书存储在本地机器商店中。-ss和-sr选项一起意味着我将在本地机器商店中以个人商店名称存储我的证书
- -a选项指定散列算法
- 而-sky选项指定此证书将用于数字签名。由于此证书将充当CA,其目的是签署其他证书。这也是为什么我使用选项-pe在证书中生成私钥的原因;?因为这是用于签名的私钥。
- 最后,-r选项指定证书文件将是自签名的
Now to create the service certificate, use the following command:
makecert -pe -n "CN=ServerCert" -ss my -sr LocalMachine -a sha1 -sky exchange -in "ServerCA" -is MY -ir LocalMachine?ServerCert.cer
I already explained many of the options in the previous command, so I will now only explain the new ones:
- The –sky option is set to exchange; this makes the certificate capable of signing and encrypting messages
- The –in option specifies the common name of the CA signing this certificate. Here I am using the ServerCA I created previously
现在要创建服务证书,请使用以下命令:
makecert -pe -n"CN = ServerCert"-ss my -sr LocalMachine -a sha1 -sky exchange -in"ServerCA"-is MY -ir LocalMachine ServerCert.cer
我已经在前面的命令中解释了许多选项,所以现在我只解释新的命令:
- -sky选项设置为交换;?这使证书能够对消息进行签名和加密
- -in选项指定签署此证书的CA的公用名称。这里我使用的是我之前创建的ServerCA
Client Certificates
Now using the same set of command, I create a ClientCA certificate:
makecert -pe -n "CN=ClientCA" -ss my -sr LocalMachine -a sha1 -sky signature -r "ClientCA.cer"
And use it to sign a ClientCert certificate.
makecert -pe -n "CN=ClientCert" -ss my -sr LocalMachine -a sha1 -sky exchange -in "ClientCA" -is MY -ir LocalMachine?ClientCert.cer
For this sake of simple testing, I could have just created a single CA and a single certificate; but to simulate a real scenario where the client will be running on a different machine than the service, I created separate CA and certificate for the client.
客户证书
现在使用相同的一组命令,我创建了一个ClientCA证书:
makecert -pe -n"CN = ClientCA"-ss my -sr LocalMachine -a sha1 -sky签名-r"ClientCA.cer"
并用它来签署ClientCert证书。
makecert -pe -n"CN = ClientCert"-ss my -sr LocalMachine -a sha1 -sky exchange -in"ClientCA"-is MY -ir LocalMachine ClientCert.cer
为了简单测试的缘故,我可以创建一个CA和一个证书;?但为了模拟客户端运行在与服务不同的机器上的真实场景,我为客户端创建了单独的CA和证书。
Sample: Username Authentication over Message Security
For this sample you will need three projects from the solution:
- SecurityService: This is a WCF service configured to use username token authentication and message security
- CustomUsernameValidator: Component used to provide dummy validation. In your projects, you can use a variety of verification methods, such SqlMembershipProvider for example.?The point is that, credentials verification is implementation specific and not related to WS-Security.
- SecurityClient: A WCF client that invokes the SecurityService
示例:通过邮件安全的用户名认证
对于此示例,您需要解决方案中的三个项目:
- SecurityService:这是一个配置为使用用户名令牌认证和消息安全的WCF服务
- CustomUsernameValidator:用于提供虚拟验证的组件。在您的项目中,您可以使用各种验证方法,例如SqlMembershipProvider。重点在于,凭据验证是特定于实现的,与WS-Security无关。
- SecurityClient:调用SecurityService的WCF客户端
Note: in the sample I invoke two methods, one with "None" protection level and the other with "EncryptAndSign" protection level. When you run the same and examine Fiddler, you will notice that the call for the "None" protected method still contains a security header with XML encryption/signature elements; even though the message payload itself is transmitted in clear text.?The reason we have security, is because the username token is never by default transmitted in plain text. WCF applied message security, to secure the transmission of the username token.?So even though we transmitted the operation itself without message security, WCF applied the appropriate security on the username token.
Tip: Examine the svc Trace Viewer as you will get to see the flow of message security.
注意:在示例中,我调用两个方法,一个使用"无"保护级别,另一个使用"EncryptAndSign"保护级别。当您运行相同的程序并检查Fiddler时,您会注意到对"无"受保护方法的调用仍然包含具有XML加密/签名元素的安全性头文件;?即使消息有效载荷本身以明文形式传输。我们拥有安全性的原因是因为用户名令牌永远不会以纯文本形式传输。WCF应用消息安全性,以确保传输用户名令牌。因此,即使我们在没有消息安全的情况下传输操作本身,WCF也会在用户名令牌上应用适当的安全性。
提示:检查svc跟踪查看器,您将看到消息安全性的流程。
Sample: X.509 Authentication over Message Security
For this sample you will need the following projects from the solution:
- CertSecurityService: a service secured with certificate authentication and message security
- MyX509CertificateValidator:?I am supplying the simplest possible validation; just by checking that the subject name of the incoming certificate is "ClientCert" which is the client certificate sent from the client to the service
- SecurityClient: WCF client that calls the CertSecurityService
Tip: Examine the svc Trace Viewer as you will get to see the flow of message security.
示例:通过邮件安全性进行X.509身份验证
对于此示例,您需要解决方案中的以下项目:
- CertSecurityService:一种通过证书认证和消息安全保护的服务
- MyX509CertificateValidator:我提供了最简单的验证;?只需检查传入证书的主题名称是从客户端发送到服务的客户端证书"ClientCert"即可
- SecurityClient:调用CertSecurityService的WCF客户端
提示:检查svc跟踪查看器,您将看到消息安全性的流程。
Reducing Overhead with WS-SecureConversation
The Need for WS-SecureConversation
So as I said before, key generation can be an acceptable solution for a single client to service invocation.?However, in case a client is doing multiple invocations over the same session, then key generation can quickly impact performance.
WS-SecureConversation removes the overhead caused by the key generation process at each and every request from the client to the service.?WS-SecureConversation builds on WS-Security to establish and share a Security Context Token between clients and services. Session keys are then driven from this token and used throughout the life of the conversation without the need to derive new keys for each call.
To reduce the chance of attacks, this token has a lifetime of 15 minutes and must be re-issued if it is to be used beyond that time.
通过WS-SecureConversation降低开销
对WS-SecureConversation的需求
正如我之前所说的,密钥生成对于单个客户端来说是服务调用的可接受解决方案。但是,如果客户端在同一个会话中执行多个调用,则密钥生成可能会快速影响性能。
WS-SecureConversation消除了从客户端到服务的每个请求的密钥生成过程所造成的开销。WS-SecureConversation基于WS-Security建立并共享客户端和服务之间的安全上下文令牌。会话密钥随后从该令牌驱动,并在对话的整个生命周期中使用,无需为每个呼叫派生新的密钥。
为了减少攻击的可能性,该令牌的使用寿命为15分钟,如果超过该时间使用,则必须重新颁发该令牌。
Security Context Token (SCT)
The Security Context Token is defined by WS-SecureConversation as another WS-Security token type.
To issue the Security Context Token (or SCT), WS-SecureConversation builds on another standard (called WS-Trust) which you will see in detail in a?later article.
All what you need to know now, is that the SCT is issued using a WS-Trust message called Request Security Token (or RST), from the client to the service, ?and given back to the client using another WS-Trust message called Request Security Token Response (or RSTR)
安全上下文令牌(SCT)
安全上下文令牌由WS-SecureConversation定义为另一种WS-Security令牌类型。
要发布安全上下文令牌(或SCT),WS-SecureConversation建立在另一个标准(称为WS-Trust)上,您将在后面的文章中详细了解这些标准。
所有您现在需要知道的是,SCT是使用名为Request Security Token(或RST)的WS-Trust消息从客户端发送到服务的,并使用另一个名为Request的WS-Trust消息返回给客户端安全令牌响应(或RSTR)
WCF Secure Sessions
WS-SecureConversation is implemented using WCF secure sessions. A secure WCF session is established in message security by setting establishSecurityContext property to true, which is the default value.
WCF安全会话
WS-SecureConversation是使用WCF安全会话实现的。通过将establishSecurityContext属性设置为true(默认值),在消息安全性中建立一个安全的WCF会话。
WS-SecureConversation
The flow of WS-SecureCoversation messaging goes as follows:
- The client sends to the service an RST message which as I said is part of the WS-Trust specification. This message includes the client credentials.
- The service receives the message and authenticates the client credentials.
- Assuming a successful authentication, the service then creates a new session token of type Secure Context Token (SCT). The SCT references a derived symmetric key to encrypt and sign messages
- The service sends the SCT back to the client using a RequestSecurityTokenResponse (RSTR) which is another WS-Trust message.
- Now the actual message exchange can begin, and from this moment, the derived symmetric key included in the session token is used to encrypt and sign the message, and the session token itself can be used by the client as its credentials
WS-SecureCoversation消息传递流程如下:
- 客户端向服务发送RST消息,正如我所说,它是WS-Trust规范的一部分。此消息包含客户端凭据。
- 该服务接收消息并对客户端凭证进行身份验证。
- 假设认证成功,则服务会创建一个类型为安全上下文令牌(SCT)的新会话令牌。SCT引用派生的对称密钥来加密和签名消息
- 该服务使用另一个WS-Trust消息RequestSecurityTokenResponse(RSTR)将SCT发送回客户端。
- 现在可以开始实际的消息交换,并且从此刻开始,包含在会话令牌中的派生对称密钥被用于对消息进行加密和签名,并且会话令牌本身可以被客户端用作其凭证
Sample: WS-SecureConversation
For this sample, use the same service secured via username/password but set the?establishSecurityContext to true.
When you do so and examine Fiddler, you will notice you will have 3 requests instead of 2. The third request (or the first in the flow actually) is the Request Security Token (RST) message I talked about.
示例:WS-SecureConversation
对于此示例,请使用通过用户名/密码保护的相同服务,但将establishSecurityContext设置为true。
当你这样做并且检查Fiddler时,你会注意到你将会有3个请求而不是2个。第三个请求(或者实际流程中的第一个请求)是我谈到的请求安全令牌(RST)消息。
以上是关于SSL/TLS原理详解与WCF中的WS-Security的主要内容,如果未能解决你的问题,请参考以下文章
HTTPS详解二:SSL / TLS 工作原理和详细握手过程
asp.net core 2.0 中的 WCF - 无法为具有权限的 SSL/TLS 安全通道建立信任关系
SSL WCF“无法为具有权限‘localhost’的 SSL/TLS 安全通道建立信任关系
WCF 服务无法为具有权限的 SSL/TLS 安全通道建立信任关系