2015-02-11 19 views
5

Próbuję odszyfrować zaszyfrowane potwierdzenie SAML 2.0 wydane przez dostawcę tożsamości opartego na języku Java.Odszyfrowywanie asercji SAML 2 przy użyciu .NET 4.5 (System.IdentityModel)/WIF

Biorąc pod uwagę następujące konfiguracja zabezpieczeń obsługą tokenów:

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

mam zaszyfrowany SAML twierdzenie takie jak to:

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

Kiedy próbuję odczytać token:

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

Następnie otrzymuję następujący wyjątek na ostatniej linii kodu:

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

Według dostawcy tożsamości klucz symetryczny służący do szyfrowania ładunku jest szyfrowany przy użyciu mojego klucza publicznego. Mimo to wydaje się, że nie można użyć klucza prywatnego z certyfikatu X509 do odszyfrowania klucza. To jest moja interpretacja komunikatu o błędzie. Czy to możliwe, że komunikat o błędzie jest błędny? Co jeszcze może być nie tak? Czy moja konfiguracja jest niepełna?

+0

można udostępnić swój pełny kod –

+0

mam następujący ERROR Podczas przetwarzania instrukcji atrybutu napotkano . Aby obsłużyć zaszyfrowane atrybuty, rozszerz rozszerzenie Saml2SecurityTokenHandler i nadpisuj ReadAttributeStatement. –

Odpowiedz

3

miałem ten problem, zbyt, a skończyło się obok niego z czymś w odpowiedzi na to pytanie: How to disable Subject Key Identifier in SecurityTokenResolver

Zmiana istniejącej linii

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

do

ServiceTokenResolver = new Saml2SSOSecurityTokenResolver(serviceTokens) 

i dodaj taką klasę:

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

Doskonale, dzięki @diana –

0

Próbowałem odszyfrować EncryptedAssertion na różne sposoby i zakończyłem z tym podejściem przy użyciu https://www.nuget.org/packages/SAML2.Core (github: https://github.com/elerch/SAML2).

Śledziłem kroki:

  1. stworzyć plik pfx (PKCS # 12) zawierające zarówno certyfikat publiczny i klucz prywatny tak:

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

  1. Otwórz dokument z SAML: EncryptedAssertion jako elementu głównego

  2. Czytaj pojemnik certyfikat pkcs12

  3. Ustaw dokument i klucz

  4. Odszyfruj dokument

Cały kod:

 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 to podstawowy czytnik plików:

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

użyłem https://developers.onelogin.com/saml/online-tools/ do generowania certyfikatów i przykładowe dane, aby przetestować ten kod

Powiązane problemy