标签:transform detail vat canonical cep sign 完整 资源 entry
源码地址:https://github.com/sunrongxin7666/OpenSAML-ref-project-demo-v3.git本文将专注讨论OpenSAML中安全特性,包括如何管理密钥,如何对断言信息签名,如何对断言信息加密等。
相关阅读
证书对象(Credential)中包含密钥信息,密钥可以是对称的,也可以是非对称的,可能是一个也可能是多个,其重要的作用就作为密钥的容器存在。证书对象和我们通常说的数字证书不是一个概念。
证书对象Credential可以通过KeySupport工具自动生成。KeySupport可以生成对称密钥和非对称密钥对,下面的例子是生成RSA密钥对,并生成证书对象:
KeyPair keyPair = KeySupport.generateKeyPair("RSA", 1024, null); return CredentialSupport.getSimpleCredential(keyPair.getPublic(), keyPair.getPrivate());
如何读取已经存在的密钥到证书对象中?OpenSAML推荐的方法是去使用各种CredentialResolvers类对象把已经存在的密钥放入新创建的证书对象中。
比如密钥被存放在JavaKeyStore中,相应地久应该使用KeyStoreCredentialResolver,其构造函数需要key store和密钥别名与口令的Map。
Map<String, String> passwordMap = new HashMap<String, String>(); passwordMap.put(KEY_ENTRY_ID, KEY_STORE_ENTRY_PASSWORD); KeyStoreCredentialResolver resolver = new KeyStoreCredentialResolver(keystore, passwordMap);
通过带有key别名的criterion来查询credential resolver中的credentials。
Criterion criterion = new EntityIDCriterion(KEY_ENTRY_ID); CriteriaSet criteriaSet = new CriteriaSet(criterion); resolver.resolveSingle(criteriaSet);
除此之外还有如下常用CredentialResolver:
签名是密码学一个证明数据完整性的手段。OpenSAML中提供了工具来对短信信息经行签名以及验证签名。由于断言的表现形式是一种XML,所以其签名也是基于XML签名方法。
这里先简要介绍下XML文件的签名方法,具体关于细节可以参见以下文章:
其大致流程为:
核实和验证XML的签名:
在OpenSAML中,每一个实现SignableXMLObject接口的对象都可以被签名。签名的产生一共分为4步:
1. 创建签名类对象并赋予签名属性:
Signature signature = OpenSAMLUtils .buildSAMLObject(Signature.class); //设定证书对象,其中包含密钥 signature.setSigningCredential(credential); //设定签名算法 signature .setSignatureAlgorithm(SignatureConstants .ALGO_ID_SIGNATURE_RSA_SHA1); //设定XML规范化算法 signature .setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
2. 将SignableXMLObject对象和签名类对象绑定起来:
signableXMLObject.setSignature(signature);
3. 将SignableXMLObject对象序列化为XML对象
XMLObjectProviderRegistrySupport
.getMarshallerFactory()
.getMarshaller(object)
.marshall(object);
4. 使用Signer工具类生成签名
Signer.signObject(signature);
在一些情况下,OpenSAML会自动完成了签名的的过程,比如在传输SAML消息时,详见关于HTTPRedirectDeflateEncoder的内容。
在验证签名之前最好是判断该消息是否被签名:
if (!assertion.isSigned()) { throw new RuntimeException("The SAML Assertion was not signed"); }
验证签名的第一步是判断该签名是否符合SAML签名的标准声明,也就是是否应用了XML的规范化算法:
SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); profileValidator.validate(assertion.getSignature());
然后再进行真正密码学意义上的验证签名:
SignatureValidator sigValidator = new SignatureValidator(credential); sigValidator.validate(assertion.getSignature());
SignatureValidator对象中被设置了credential对象,其中包含密钥信息。
在OpenSAML中断言信息需要加密处理,要求使用一个对称密钥来来加密数据,同时用另外一个而非对称密钥用来加密这个对称密钥。断言的密文和密钥的密文都会在ArtifactResponse体现出来。
1. 为加密过程设置参数,即定义使用什么算法来加密断言数据:
DataEncryptionParameters encryptionParameters = new DataEncryptionParameters(); encryptionParameters .setAlgorithm(EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128);
2. 设定使用何种算法对上一步用来加密数据的对称密钥进行非对称加密:
KeyEncryptionParameters keyEncryptionParameters = new KeyEncryptionParameters(); keyEncryptionParameters .setEncryptionCredential(SPCredentials.getCredential()); keyEncryptionParameters.setAlgorithm( EncryptionConstants .ALGO_ID_KEYTRANSPORT_RSAOAEP);
3. 利用以上两个参数来生成加密对象:
Encrypter encrypter = new Encrypter(encryptionParameters, keyEncryptionParameters);
4. 设置被加密的对称密钥的位置,这里设置为ArtifactResponse中KeyInfo元素的内置元素,还可以设置为Peer模式就是和KeyInfo元素并列:
encrypter.setKeyPlacement(Encrypter.KeyPlacement.INLINE);
5. 使用Encrypter加密数据
EncryptedAssertion encryptedAssertion = encrypter.encrypt(assertion);
Encrypter不光可以加密Assertion,Attribute和NameID等XMLObject都可以被加密。
keyInfoCredentialResolver用于获得非对称密码要,该密钥用于解密对称密钥;再使用对称密钥获得数据。
StaticKeyInfoCredentialResolver keyInfoCredentialResolver = new StaticKeyInfoCredentialResolver( SPCredentials.getCredential()); Decrypter decrypter = new Decrypter( null, keyInfoCredentialResolver, new InlineEncryptedKeyResolver()); decrypter.decrypt(encryptedAssertion);
更多关于SAML协议的是实现的内容,请参见本人编写的一系列教程文章,其介绍如何使用OpenSAML,欢迎阅读指正:
作者:登高且赋
链接:https://www.jianshu.com/p/77bbc9758831
标签:transform detail vat canonical cep sign 完整 资源 entry
原文地址:https://www.cnblogs.com/wpcnblog/p/12718438.html