2015-02-11 72 views
5

我试图解密从基于Java的身份提供者发出的加密的SAML 2.0声明。使用.NET 4.5(System.IdentityModel)解密SAML 2断言/ WIF

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

X509Certificate2 cert = ... // Contains private key 
var serviceTokens = new List<SecurityToken>(); 
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断言像这样:

<saml:EncryptedAssertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> 
    <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Element"> 
    <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" /> 
    <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> 
     <xenc:EncryptedKey> 
     <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /> 
     <xenc:CipherData> 


    <xenc:CipherValue>Fwhv/zEVi3eQvQN372L1S+pVDM5JKs1Kc2I25djuiOPdwKReCXRhnd5QL4Y8wJDWZ5vAlOxHkNAZ 
OwOg4NsSI8KssrygNk4fwvNdVAGMB5ytI1QTGRqG6WwP4Em+uLN3VXbqiLWA9D6uO0BwATF9HdTb 
j/IMhGCxZ1ZKrKQF5OL2PHKf4DqyNa5d9CNZenhYyYghgYrhgZtQVl/VARAp9VKsM/lbkPsEU8Ty 
ow4LnTlYqBnykrOEJowN5B+HXGvfhbIBHyGzdCC+WbcEbI898zy/VhZ63VyFL2GSTdDWv10IEMy5 
CHom4Qruer1xpyQMrxJ6EK30HMhVppToivgoFQ==</xenc:CipherValue> 
     </xenc:CipherData> 
     </xenc:EncryptedKey> 
    </ds:KeyInfo> 
    <xenc:CipherData> 
     <xenc:CipherValue>...</xenc:CipherValue> 
    </xenc:CipherData> 
    </xenc:EncryptedData> 
</saml:EncryptedAssertion> 

当我尝试读取令牌:

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); 

然后我在最后一行代码上得到以下例外:

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证书中的私钥来解密密钥。这是我对错误信息的解释。难道是错误信息是错误的?还有什么可能是错的?我的配置不完整?

+0

你可以分享你的完整代码 – 2016-12-02 16:09:24

+0

我得到了以下错误处理属性语句时遇到。要处理加密属性,请扩展Saml2SecurityTokenHandler并重写ReadAttributeStatement。 – 2016-12-02 16:34:28

回答

3

我有这个问题,也和我最终得到过去,它与类似的回答了这个问题:How to disable Subject Key Identifier in SecurityTokenResolver

改变现有的线

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

ServiceTokenResolver = new Saml2SSOSecurityTokenResolver(serviceTokens) 

加入一个类似以分类为:

private class Saml2SSOSecurityTokenResolver : SecurityTokenResolver 
{ 
    List<SecurityToken> _tokens; 

    public Saml2SSOSecurityTokenResolver(List<SecurityToken> 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(); 
    } 
} 
+0

非常好,谢谢@diana – 2015-02-18 16:41:46

0

我试图以不同的方式解密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

  • 打开与SAML文档:EncryptedAssertion作为根元素

  • 阅读证书PKCS12容器

  • 设置文档和密钥

  • 解密文档
  • 完整代码:

     var doc = LoadXmlDocument(@"path\to\xml\withencryptedassertion"); 
         var cert = new X509Certificate2(@"path\to\cert_key.p12", "<container_password>"); 
    
         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/生成证书和样本数据来测试该代码