使用.NET 4.5(System.IdentityModel)/ WIF解密SAML 2断言

我正在尝试解密从基于Java的身份提供程序发出的加密SAML 2.0断言。

鉴于以下安全令牌处理程序的设置:

X509Certificate2 cert = ... // Contains private key var serviceTokens = new List(); serviceTokens.Add(new X509SecurityToken(cert)); var issuers = new ConfigurationBasedIssuerNameRegistry(); issuers.AddTrustedIssuer("...thumbprint...", "nottherealname"); var configuration = new SecurityTokenHandlerConfiguration { AudienceRestriction = { AudienceMode = AudienceUriMode.Never }, CertificateValidationMode = X509CertificateValidationMode.None, RevocationMode = X509RevocationMode.NoCheck, IssuerNameRegistry = issuers, MaxClockSkew = TimeSpan.FromMinutes(5), ServiceTokenResolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(serviceTokens.AsReadOnly(), false) }; var tokenHandlers = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection(configuration); 

我得到一个加密的SAML断言,例如:

        Fwhv/zEVi3eQvQN372L1S+pVDM5JKs1Kc2I25djuiOPdwKReCXRhnd5QL4Y8wJDWZ5vAlOxHkNAZ OwOg4NsSI8KssrygNk4fwvNdVAGMB5ytI1QTGRqG6WwP4Em+uLN3VXbqiLWA9D6uO0BwATF9HdTb j/IMhGCxZ1ZKrKQF5OL2PHKf4DqyNa5d9CNZenhYyYghgYrhgZtQVl/VARAp9VKsM/lbkPsEU8Ty ow4LnTlYqBnykrOEJowN5B+HXGvfhbIBHyGzdCC+WbcEbI898zy/VhZ63VyFL2GSTdDWv10IEMy5 CHom4Qruer1xpyQMrxJ6EK30HMhVppToivgoFQ==     ...    

当我尝试读取令牌时:

 var tokenReader = new XmlNodeReader(xmlDoc); // XML document with root element <saml:EncryptedAssertion .... if (!tokenHandlers.CanReadToken(tokenReader)) throw new Exception("Unreadable token"); var token = tokenHandlers.ReadToken(tokenReader); 

然后我在最后一个代码行上得到以下exception:

  ID4022: The key needed to decrypt the encrypted security token could not be resolved. Ensure that the SecurityTokenResolver is populated with the required key. 

根据身份提供者,用于加密有效载荷的对称密钥使用我的公钥加密。 但是,似乎无法使用X509证书中的私钥来解密密钥。 这是我对错误消息的解释。 可能是错误信息错了吗? 还有什么可能是错的? 我的配置不完整吗?

我也有这个问题,我最终得到的东西就像这个问题的答案: 如何在SecurityTokenResolver中禁用主题密钥标识符

更改现有行

 ServiceTokenResolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(serviceTokens.AsReadOnly(), false) 

 ServiceTokenResolver = new Saml2SSOSecurityTokenResolver(serviceTokens) 

并添加这样的类:

 private class Saml2SSOSecurityTokenResolver : SecurityTokenResolver { List _tokens; public Saml2SSOSecurityTokenResolver(List tokens) { _tokens = tokens; } protected override bool TryResolveSecurityKeyCore(System.IdentityModel.Tokens.SecurityKeyIdentifierClause keyIdentifierClause, out System.IdentityModel.Tokens.SecurityKey key) { var token = _tokens[0] as X509SecurityToken; var myCert = token.Certificate; key = null; var ekec = keyIdentifierClause as EncryptedKeyIdentifierClause; if (ekec != null) { if (ekec.EncryptionMethod == "http://www.w3.org/2001/04/xmlenc#rsa-1_5") { var encKey = ekec.GetEncryptedKey(); var rsa = myCert.PrivateKey as RSACryptoServiceProvider; var decKey = rsa.Decrypt(encKey, false); key = new InMemorySymmetricSecurityKey(decKey); return true; } var data = ekec.GetEncryptedKey(); var id = ekec.EncryptingKeyIdentifier; } return true; } protected override bool TryResolveTokenCore(System.IdentityModel.Tokens.SecurityKeyIdentifierClause keyIdentifierClause, out System.IdentityModel.Tokens.SecurityToken token) { throw new NotImplementedException(); } protected override bool TryResolveTokenCore(System.IdentityModel.Tokens.SecurityKeyIdentifier keyIdentifier, out System.IdentityModel.Tokens.SecurityToken token) { throw new NotImplementedException(); } } 

我尝试以不同的方式解密EncryptedAssertion,最后使用https://www.nuget.org/packages/SAML2.Core(github:https://github.com/elerch/SAML2 )。

我按照以下步骤操作:

  1. 创建一个包含公共证书和私钥的pfx文件(PKCS#12),如下所示:

openssl pkcs12 -export -in -inkey -out cert_key.p12

  1. 使用saml打开文档:EncryptedAssertion作为根元素

  2. 阅读证书pkcs12容器

  3. 设置文档和密钥

  4. 解密文件

完整代码:

  var doc = LoadXmlDocument(@"path\to\xml\withencryptedassertion"); var cert = new X509Certificate2(@"path\to\cert_key.p12", ""); var encryptedAssertion = new SAML2.Saml20EncryptedAssertion((RSA)cert.PrivateKey, doc); encryptedAssertion.Decrypt(); var decryptedContent = encryptedAssertion.Assertion.InnerXml; 

LoadXmlDocument是一个基本的文件阅读器:

  public static XmlDocument LoadXmlDocument(string assertionFile) { using (var fs = File.OpenRead(assertionFile)) { var document = new XmlDocument { PreserveWhitespace = true }; document.Load(fs); fs.Close(); return document; } } 

我使用https://developers.onelogin.com/saml/online-tools/生成证书和示例数据来测试此代码