6.2.6. 提供加密密钥和签名密钥
概述
标准 WS-SecurityPolicy 策略是为了在一些详细信息中指定 安全要求 :例如,安全协议、安全算法、令牌类型、身份验证要求等等。但是,标准策略断言不提供指定相关安全数据的任何机制,如密钥和凭证。WS-SecurityPolicy 期望通过专有机制提供必要的安全数据。在 Apache CXF 中,相关的安全数据通过 Blueprint XML 配置提供。
配置加密密钥和签名密钥
您可以通过在客户端的请求上下文或端点上下文中设置属性来指定应用程序的加密密钥和签名密钥(请参阅 “为 Blueprint 配置添加加密和签名属性”一节)。您可以设置的属性显示在 表 6.1 “加密和签名属性” 中。
表 6.1. 加密和签名属性
属性 | 描述 |
---|---|
|
WSS4J 属性文件/对象,包含用于配置签名密钥存储(也用于解密)和 |
| (可选) 要使用的签名密钥存储中密钥的用户名或别名。若不指定,则使用属性文件中设置的别名。如果也未设置,并且密钥存储仅包含一个密钥,则将使用该密钥。 |
|
WSS4J 属性文件/对象,包含用于配置加密密钥存储(也用于验证签名)和 |
| (可选) 加密密钥存储中要使用的密钥的用户名或别名。若不指定,则使用属性文件中设置的别名。如果也未设置,并且密钥存储仅包含一个密钥,则将使用该密钥。 |
上述属性的名称不会被正确选择,因为它们无法准确反映它们的用途。由 security.signature.properties
指定的密钥实际上用于 签名和 解密。由 security.encryption.properties
指定的密钥实际上用于加密 和 验证签名。
为 Blueprint 配置添加加密和签名属性
在 Apache CXF 应用程序中使用任何 WS-Policy 策略前,您必须将策略功能添加到默认的 CXF 总线中。将 p:policies
元素添加到 CXF 总线,如以下 Blueprint 配置片段所示:
<beans xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:cxf="http://cxf.apache.org/core"
xmlns:p="http://cxf.apache.org/policy" ... >
<cxf:bus>
<cxf:features>
<p:policies/>
<cxf:logging/>
</cxf:features>
</cxf:bus>
...
</beans>
以下示例演示了如何在指定服务类型的代理中添加签名和加密属性(该服务名称通过 jaxws:client
元素的 name
属性指定)。这些属性存储在 WSS4J 属性文件中,其中 alice.properties
包含签名密钥的属性,bob.properties
包含加密密钥的属性。
<beans ... > <jaxws:client name="{http://InteropBaseAddress/interop}MutualCertificate10SignEncrypt_IPingService" createdFromAPI="true"> <jaxws:properties> <entry key="ws-security.signature.properties" value="etc/alice.properties"/> <entry key="ws-security.encryption.properties" value="etc/bob.properties"/> </jaxws:properties> </jaxws:client> ... </beans>
实际上,虽然属性名称没有明显,但每个密钥都用于客户端的两个不同的目的:
alice.properties
(即security.signature.properties
指定的密钥)在客户端中使用,如下所示:- 用于签名传出消息。
- 用于解密传入消息。
Bob.properties
(即security.encryption.properties
)在客户端中使用,如下所示:- 用于加密传出消息。
- 在传入信息中验证签名。
如果您发现这个混淆,请参阅 第 6.2.2 节 “基本签名和加密(cenario)” 以获得更详细的说明。
以下示例演示了如何在 JAX-WS 端点中添加签名和加密属性。属性文件 bob.properties
包含签名密钥和属性文件 alice.properties
的属性,包含加密密钥的属性(这是客户端配置不良)。
<beans ... > <jaxws:endpoint name="{http://InteropBaseAddress/interop}MutualCertificate10SignEncrypt_IPingService" id="MutualCertificate10SignEncrypt" address="http://localhost:9002/MutualCertificate10SignEncrypt" serviceName="interop:PingService10" endpointName="interop:MutualCertificate10SignEncrypt_IPingService" implementor="interop.server.MutualCertificate10SignEncrypt"> <jaxws:properties> <entry key="security.signature.properties" value="etc/bob.properties"/> <entry key="security.encryption.properties" value="etc/alice.properties"/> </jaxws:properties> </jaxws:endpoint> ... </beans>
每个密钥都用于服务器端的两个不同目的:
Bob.properties
(即security.signature.properties
指定的密钥)在服务器端使用,如下所示:- 用于签名传出消息。
- 用于解密传入消息。
alice.properties
(即security.encryption.properties
)在服务器端使用,如下所示:- 用于加密传出消息。
- 在传入信息中验证签名。
定义 WSS4J 属性文件
Apache CXF 使用 WSS4J 属性文件加载加密和签名所需的公钥和私钥。表 6.2 “WSS4J 密钥存储属性” 描述您可以在这些文件中设置的属性。
表 6.2. WSS4J 密钥存储属性
属性 | 描述 |
---|---|
|
指定
此表中的其余属性特定于 |
|
(可选) 要使用的 JSSE 密钥存储提供程序的名称。默认密钥存储提供程序是 Bouncy Castle。您可以通过将此属性设置为 |
|
Bouncy Castle 密钥存储提供程序支持以下密钥存储: |
| 指定要加载的密钥存储文件的位置,其位置相对于 Classpath。 |
|
(可选) 如果密钥存储类型为 |
| 此属性指定的密码用于两个目的: 解锁密钥存储(密钥存储密码)并解密存储在密钥存储中的私钥(私钥密码)。因此,密钥存储密码必须与私钥密码相同。 |
例如,etc/alice.properties
文件包含用于加载 PKCS#12 文件 certs/alice.pfx
的属性设置,如下所示:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin org.apache.ws.security.crypto.merlin.keystore.type=PKCS12 org.apache.ws.security.crypto.merlin.keystore.password=password org.apache.ws.security.crypto.merlin.keystore.file=certs/alice.pfx
etc/bob.properties
文件包含用于加载 PKCS#12 文件 certs/bob.pfx
的属性设置,如下所示:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin org.apache.ws.security.crypto.merlin.keystore.password=password # for some reason, bouncycastle has issues with bob.pfx org.apache.ws.security.crypto.merlin.keystore.provider=SunJSSE org.apache.ws.security.crypto.merlin.keystore.type=PKCS12 org.apache.ws.security.crypto.merlin.keystore.file=certs/bob.pfx
编程加密密钥和签名密钥
加载加密密钥和签名密钥的替代方法是使用 表 6.3 “指定 Crypto 对象的属性” 中显示的属性来指定加载相关键的 Crypto
对象。这要求您自己提供 WSS4J Crypto
接口的实施,即 org.apache.ws.security.components.crypto.Crypto
。
表 6.3. 指定 Crypto 对象的属性
属性 | 描述 |
---|---|
|
指定负责加载用于签名和解密消息的密钥的 |
|
指定 |
WSS4J Crypto 接口
例 6.7 “WSS4J Crypto 接口” 显示您可以实现的 Crypto
接口的定义(如果您想要按编程提供加密密钥和签名密钥)。如需更多信息,请参阅 WSS4J 主页。
例 6.7. WSS4J Crypto 接口
// Java package org.apache.ws.security.components.crypto; import org.apache.ws.security.WSSecurityException; import java.io.InputStream; import java.math.BigInteger; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; public interface Crypto { X509Certificate loadCertificate(InputStream in) throws WSSecurityException; X509Certificate[] getX509Certificates(byte[] data, boolean reverse) throws WSSecurityException; byte[] getCertificateData(boolean reverse, X509Certificate[] certs) throws WSSecurityException; public PrivateKey getPrivateKey(String alias, String password) throws Exception; public X509Certificate[] getCertificates(String alias) throws WSSecurityException; public String getAliasForX509Cert(Certificate cert) throws WSSecurityException; public String getAliasForX509Cert(String issuer) throws WSSecurityException; public String getAliasForX509Cert(String issuer, BigInteger serialNumber) throws WSSecurityException; public String getAliasForX509Cert(byte[] skiBytes) throws WSSecurityException; public String getDefaultX509Alias(); public byte[] getSKIBytesFromCert(X509Certificate cert) throws WSSecurityException; public String getAliasForX509CertThumb(byte[] thumb) throws WSSecurityException; public KeyStore getKeyStore(); public CertificateFactory getCertificateFactory() throws WSSecurityException; public boolean validateCertPath(X509Certificate[] certs) throws WSSecurityException; public String[] getAliasesForDN(String subjectDN) throws WSSecurityException; }