/// <summary> /// Decrypts an assertion we received from "fælles-offentlige brugerstyring". /// </summary> private static void DecryptFOBSAssertion(string file) { string assertionBase64 = File.ReadAllText(file); byte[] assertionBytes = Convert.FromBase64String(assertionBase64); XmlDocument doc = new XmlDocument(); doc.PreserveWhitespace = true; doc.Load( new MemoryStream(assertionBytes) ); XmlNodeList encryptedList = doc.GetElementsByTagName(EncryptedAssertion.ELEMENT_NAME, Saml20Constants.ASSERTION); Assert.That(encryptedList.Count == 1); // Do some mock configuration. FederationConfig config = FederationConfig.GetConfig(); config.AllowedAudienceUris.Audiences.Add("https://saml.safewhere.net"); SAML20FederationConfig descr = ConfigurationReader.GetConfig<SAML20FederationConfig>(); descr.Endpoints.metadataLocation = @"Saml20\Protocol\MetadataDocs\FOBS"; // Set it manually. Assert.That(Directory.Exists(descr.Endpoints.metadataLocation)); descr.Endpoints.Refresh(); X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\SafewhereTest_SFS.pfx", "test1234"); Saml20EncryptedAssertion encass = new Saml20EncryptedAssertion((RSA) cert.PrivateKey); encass.LoadXml((XmlElement) encryptedList[0]); encass.Decrypt(); // Retrieve metadata Saml20Assertion assertion = new Saml20Assertion(encass.Assertion.DocumentElement, null, false); IDPEndPoint endp = descr.FindEndPoint(assertion.Issuer); Assert.IsNotNull(endp, "Endpoint not found"); Assert.IsNotNull(endp.metadata, "Metadata not found"); try { assertion.CheckValid(AssertionUtil.GetTrustedSigners(assertion.Issuer)); Assert.Fail("Verification should fail. Token does not include its signing key."); } catch(InvalidOperationException) {} Assert.IsNull(assertion.SigningKey, "Signing key is already present on assertion. Modify test."); Assert.That(assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endp.metadata.GetKeys(KeyTypes.signing), endp))); Assert.IsNotNull(assertion.SigningKey, "Signing key was not set on assertion instance."); }
public void DecryptPingAssertion() { // Load the assertion XmlDocument doc = new XmlDocument(); doc.Load(File.OpenRead(@"c:\tmp\pingassertion.txt")); XmlElement xe = GetElement(EncryptedAssertion.ELEMENT_NAME, Saml20Constants.ASSERTION, doc); XmlDocument doc2 = new XmlDocument(); doc2.AppendChild(doc2.ImportNode(xe, true)); X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection coll = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, "CN=SafewhereTest_SFS, O=Safewhere, C=DK", true); Assert.That(coll.Count == 1); X509Certificate2 cert = coll[0]; Saml20EncryptedAssertion encass = new Saml20EncryptedAssertion((RSA)cert.PrivateKey, doc2); encass.Decrypt(); XmlTextWriter writer = new XmlTextWriter(Console.Out); writer.Formatting = Formatting.Indented; writer.Indentation = 3; writer.IndentChar = ' '; encass.Assertion.WriteTo(writer); writer.Flush(); Saml20Assertion assertion = new Saml20Assertion(encass.Assertion.DocumentElement, AssertionUtil.GetTrustedSigners(encass.Assertion.Attributes["Issuer"].Value), false); Assert.That(encass.Assertion != null); Console.WriteLine(); foreach (SamlAttribute attribute in assertion.Attributes) Console.WriteLine(attribute.Name + " : " + attribute.AttributeValue[0]); }
/// <summary> /// Performs the attribute query against the specified IdP endpoint and adds the resulting attributes to Saml20Identity.Current. /// </summary> /// <param name="context">The http context.</param> /// <param name="endPoint">The IdP to perform the query against.</param> /// <param name="nameIdFormat">The nameid format.</param> public void PerformQuery(HttpContext context, IDPEndPoint endPoint, string nameIdFormat) { Trace.TraceMethodCalled(GetType(), "PerformQuery()"); HttpSOAPBindingBuilder builder = new HttpSOAPBindingBuilder(context); NameID name = new NameID(); name.Value = Saml20Identity.Current.Name; name.Format = nameIdFormat; _attrQuery.Subject.Items = new object[] { name }; _attrQuery.SamlAttribute = _attributes.ToArray(); XmlDocument query = new XmlDocument(); query.XmlResolver = null; query.LoadXml(Serialization.SerializeToXmlString(_attrQuery)); var signingCertificate = FederationConfig.GetConfig().SigningCertificate.GetCertificate(); var shaHashingAlgorithm = SignatureProviderFactory.ValidateShaHashingAlgorithm(endPoint.ShaHashingAlgorithm); var signatureProvider = SignatureProviderFactory.CreateFromShaHashingAlgorithmName(shaHashingAlgorithm); signatureProvider.SignAssertion(query, ID, signingCertificate); if (query.FirstChild is XmlDeclaration) { query.RemoveChild(query.FirstChild); } Stream s; if (Trace.ShouldTrace(TraceEventType.Information)) { Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendAttrQuery, endPoint.metadata.GetAttributeQueryEndpointLocation(), query.OuterXml)); } try { s = builder.GetResponse(endPoint.metadata.GetAttributeQueryEndpointLocation(), query.OuterXml, endPoint.AttributeQuery); } catch (Exception e) { Trace.TraceData(TraceEventType.Error, e.ToString()); throw; } HttpSOAPBindingParser parser = new HttpSOAPBindingParser(s); Status status = parser.GetStatus(); if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success) { Trace.TraceData(TraceEventType.Error, string.Format(Tracing.AttrQueryStatusError, Serialization.SerializeToXmlString(status))); throw new Saml20Exception(status.StatusMessage); } bool isEncrypted; XmlElement xmlAssertion = Saml20SignonHandler.GetAssertion(parser.SamlMessage, out isEncrypted); if (isEncrypted) { Saml20EncryptedAssertion ass = new Saml20EncryptedAssertion( (RSA)FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey); ass.LoadXml(xmlAssertion); ass.Decrypt(); xmlAssertion = ass.Assertion.DocumentElement; } Saml20Assertion assertion = new Saml20Assertion(xmlAssertion, null, AssertionProfile.Core, endPoint.QuirksMode); assertion.Validate(DateTime.UtcNow); if (Trace.ShouldTrace(TraceEventType.Information)) { Trace.TraceData(TraceEventType.Information, string.Format(Tracing.AttrQueryAssertion, xmlAssertion == null ? string.Empty : xmlAssertion.OuterXml)); } IEnumerable <string> validationFailures; if (!assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endPoint.metadata.Keys, endPoint, out validationFailures))) { Trace.TraceData(TraceEventType.Error, Resources.SignatureInvalid); throw new Saml20Exception(Resources.SignatureInvalid); } foreach (SamlAttribute attr in assertion.Attributes) { Saml20Identity.Current.AddAttributeFromQuery(attr.Name, attr); } }
private static Saml20Assertion CreateDKSaml20TokenFromAssertion(Saml20EncryptedAssertion encAss) { return new Saml20Assertion(encAss.Assertion.DocumentElement, null, false); }
public void TestAssertionEncryption() { Saml20EncryptedAssertion encryptedAssertion = new Saml20EncryptedAssertion(); encryptedAssertion.Assertion = AssertionUtil.GetTestAssertion_01(); X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\sts_dev_certificate.pfx", "test1234"); encryptedAssertion.TransportKey = (RSA) cert.PublicKey.Key; encryptedAssertion.Encrypt(); XmlDocument encryptedAssertionXML = encryptedAssertion.GetXml(); Assert.IsNotNull(encryptedAssertionXML); // A number of simple tests until we get some better way to verify the generated encrypted assertion. XmlNodeList list; list = encryptedAssertionXML.GetElementsByTagName(EncryptedAssertion.ELEMENT_NAME, Saml20Constants.ASSERTION); Assert.AreEqual(1, list.Count); list = encryptedAssertionXML.GetElementsByTagName(dk.nita.saml20.Schema.XEnc.EncryptedKey.ELEMENT_NAME, Saml20Constants.XENC); Assert.AreEqual(1, list.Count); }
public void TestAssertionDecryption_05() { // Load the assertion XmlDocument doc = new XmlDocument(); doc.Load(File.OpenRead(@"Saml20\Assertions\EncryptedAssertion_05")); // Find the transport key. X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\sts_dev_certificate.pfx", "test1234"); Saml20EncryptedAssertion encryptedAssertion = new Saml20EncryptedAssertion((RSA)cert.PrivateKey, doc); Assert.IsNull(encryptedAssertion.Assertion); // Check that it does not contain an assertion prior to decryption. encryptedAssertion.Decrypt(); Assert.IsNotNull(encryptedAssertion.Assertion); XmlNodeList list; // Perform some rudimentary tests on the output. list = encryptedAssertion.Assertion.GetElementsByTagName(Assertion.ELEMENT_NAME, Saml20Constants.ASSERTION); Assert.AreEqual(1, list.Count); }
public void TestAssertionDecryption_03() { // Load the assertion XmlDocument doc = new XmlDocument(); doc.Load(File.OpenRead(@"Saml20\Assertions\EncryptedAssertion_03")); // Find the transport key. X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\sts_dev_certificate.pfx", "test1234"); Saml20EncryptedAssertion encryptedAssertion = new Saml20EncryptedAssertion((RSA)cert.PrivateKey, doc); Assert.IsNull(encryptedAssertion.Assertion); // Check that it does not contain an assertion prior to decryption. encryptedAssertion.Decrypt(); Assert.IsNotNull(encryptedAssertion.Assertion); }
public void TestAlgorithmConfiguration_02() { Saml20EncryptedAssertion encryptedAssertion = new Saml20EncryptedAssertion(); encryptedAssertion.SessionKeyAlgorithm = EncryptedXml.XmlEncAES128Url; encryptedAssertion.Assertion = AssertionUtil.GetTestAssertion_01(); X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\sts_dev_certificate.pfx", "test1234"); encryptedAssertion.TransportKey = (RSA)cert.PublicKey.Key; encryptedAssertion.Encrypt(); XmlDocument encryptedAssertionXML = encryptedAssertion.GetXml(); Assert.IsNotNull(encryptedAssertionXML); // Verify that the EncryptionMethod element is set correctly. XmlNodeList list = encryptedAssertionXML.GetElementsByTagName(dk.nita.saml20.Schema.XEnc.EncryptedData.ELEMENT_NAME, Saml20Constants.XENC); Assert.AreEqual(1, list.Count); XmlElement el = (XmlElement) list[0]; // Go through the children and look for the EncryptionMethod element, and verify its algorithm attribute. bool encryptionMethodFound = false; foreach (XmlNode node in el.ChildNodes) { if (node.LocalName == dk.nita.saml20.Schema.XEnc.EncryptionMethod.ELEMENT_NAME && node.NamespaceURI == Saml20Constants.XENC) { el = (XmlElement) node; Assert.AreEqual(EncryptedXml.XmlEncAES128Url, el.GetAttribute("Algorithm")); encryptionMethodFound = true; } } Assert.That(encryptionMethodFound, "Unable to find EncryptionMethod element in EncryptedData."); // Now decrypt the assertion, and verify that it recognizes the Algorithm used. Saml20EncryptedAssertion decrypter = new Saml20EncryptedAssertion((RSA) cert.PrivateKey); Assert.IsNull(decrypter.Assertion); decrypter.LoadXml(encryptedAssertionXML.DocumentElement); // Set a wrong algorithm and make sure that the class gets it algorithm info from the assertion itself. decrypter.SessionKeyAlgorithm = EncryptedXml.XmlEncTripleDESUrl; decrypter.Decrypt(); // Verify that the class has discovered the correct algorithm and set the SessionKeyAlgorithm property accordingly. Assert.AreEqual(EncryptedXml.XmlEncAES128Url, decrypter.SessionKeyAlgorithm); Assert.IsNotNull(decrypter.Assertion); }
public void TestAlgorithmConfiguration_01() { Saml20EncryptedAssertion encryptedAssertion = new Saml20EncryptedAssertion(); encryptedAssertion.SessionKeyAlgorithm = "RSA"; Assert.Fail("\"Saml20EncryptedAssertion\" class does not respond to incorrect algorithm identifying URI."); }
/// <summary> /// Performs the attribute query against the specified IdP endpoint and adds the resulting attributes to Saml20Identity.Current. /// </summary> /// <param name="context">The http context.</param> /// <param name="endPoint">The IdP to perform the query against.</param> /// <param name="nameIdFormat">The nameid format.</param> public void PerformQuery(HttpContext context, IDPEndPoint endPoint, string nameIdFormat) { Trace.TraceMethodCalled(GetType(), "PerformQuery()"); HttpSOAPBindingBuilder builder = new HttpSOAPBindingBuilder(context); NameID name = new NameID(); name.Value = Saml20Identity.Current.Name; name.Format = nameIdFormat; _attrQuery.Subject.Items = new object[] { name }; _attrQuery.SamlAttribute = _attributes.ToArray(); XmlDocument query = new XmlDocument(); query.LoadXml(Serialization.SerializeToXmlString(_attrQuery)); XmlSignatureUtils.SignDocument(query, ID); if(query.FirstChild is XmlDeclaration) query.RemoveChild(query.FirstChild); Stream s; if (Trace.ShouldTrace(TraceEventType.Information)) Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendAttrQuery, endPoint.metadata.GetAttributeQueryEndpointLocation(), query.OuterXml)); try { s = builder.GetResponse(endPoint.metadata.GetAttributeQueryEndpointLocation(), query.OuterXml, endPoint.AttributeQuery); }catch(Exception e) { Trace.TraceData(TraceEventType.Error, e.ToString()); throw; } HttpSOAPBindingParser parser = new HttpSOAPBindingParser(s); Status status = parser.GetStatus(); if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success) { Trace.TraceData(TraceEventType.Error, string.Format(Tracing.AttrQueryStatusError, Serialization.SerializeToXmlString(status))); throw new Saml20Exception(status.StatusMessage); } bool isEncrypted; XmlElement xmlAssertion = Saml20SignonHandler.GetAssertion(parser.SamlMessage, out isEncrypted); if (isEncrypted) { Saml20EncryptedAssertion ass = new Saml20EncryptedAssertion( (RSA) FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey); ass.LoadXml(xmlAssertion); ass.Decrypt(); xmlAssertion = ass.Assertion.DocumentElement; } Saml20Assertion assertion = new Saml20Assertion(xmlAssertion, null, AssertionProfile.Core, endPoint.QuirksMode); if(Trace.ShouldTrace(TraceEventType.Information)) { Trace.TraceData(TraceEventType.Information, string.Format(Tracing.AttrQueryAssertion, xmlAssertion == null ? string.Empty : xmlAssertion.OuterXml)); } if(!assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endPoint.metadata.Keys, endPoint))){ Trace.TraceData(TraceEventType.Error, Resources.SignatureInvalid); throw new Saml20Exception(Resources.SignatureInvalid); } foreach (SamlAttribute attr in assertion.Attributes) { Saml20Identity.Current.AddAttributeFromQuery(attr.Name, attr); } }