예제 #1
0
        void CheckProperties(XmlDsigExcC14NWithCommentsTransform transform)
        {
            Assert.Equal("http://www.w3.org/2001/10/xml-exc-c14n#WithComments", transform.Algorithm);

            Type[] input = transform.InputTypes;
            Assert.Equal(3, input.Length);
            // check presence of every supported input types
            bool istream = false;
            bool ixmldoc = false;
            bool ixmlnl  = false;

            foreach (Type t in input)
            {
                if (t == typeof(Stream))
                {
                    istream = true;
                }
                if (t == typeof(XmlDocument))
                {
                    ixmldoc = true;
                }
                if (t == typeof(XmlNodeList))
                {
                    ixmlnl = true;
                }
            }
            Assert.True(istream, "Input Stream");
            Assert.True(ixmldoc, "Input XmlDocument");
            Assert.True(ixmlnl, "Input XmlNodeList");

            Type[] output = transform.OutputTypes;
            Assert.Equal(1, output.Length);
            Assert.Equal(typeof(Stream), output[0]);
        }
예제 #2
0
    // Sign an XML file and save the signature in a new file.
    public static void SignXmlFile(string FileName, string SignedFileName, RSA Key)
    {
        // Create a new XML document.
        XmlDocument doc = new XmlDocument();

        // Format the document to ignore white spaces.
        doc.PreserveWhitespace = false;

        // Load the passed XML file using it's name.
        doc.Load(new XmlTextReader(FileName));

        // Create a SignedXml object.
        SignedXml signedXml = new SignedXml(doc);

        // Add the key to the SignedXml document.
        signedXml.SigningKey = Key;

        // Specify a canonicalization method.
        signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NWithCommentsTransformUrl;

        // Set the InclusiveNamespacesPrefixList property.
        XmlDsigExcC14NWithCommentsTransform canMethod = (XmlDsigExcC14NWithCommentsTransform)signedXml.SignedInfo.CanonicalizationMethodObject;

        canMethod.InclusiveNamespacesPrefixList = "Sign";

        // Create a reference to be signed.
        Reference reference = new Reference();

        reference.Uri = "";

        // Add an enveloped transformation to the reference.
        XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();

        reference.AddTransform(env);

        // Add the reference to the SignedXml object.
        signedXml.AddReference(reference);

        // Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
        KeyInfo keyInfo = new KeyInfo();

        keyInfo.AddClause(new RSAKeyValue((RSA)Key));
        signedXml.KeyInfo = keyInfo;

        // Compute the signature.
        signedXml.ComputeSignature();

        // Get the XML representation of the signature and save
        // it to an XmlElement object.
        XmlElement xmlDigitalSignature = signedXml.GetXml();

        // Append the element to the XML document.
        doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, true));

        if (doc.FirstChild is XmlDeclaration)
        {
            doc.RemoveChild(doc.FirstChild);
        }

        // Save the signed XML document to a file specified
        // using the passed string.
        XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false));

        doc.WriteTo(xmltw);
        xmltw.Close();
    }
예제 #3
0
        /// <summary>
        /// Signs the specified xml document with the certificate found in
        /// the local machine matching the provided friendly name and
        /// referring to the specified target reference ID.
        /// </summary>
        /// <param name="certFriendlyName">
        /// Friendly Name of the X509Certificate to be retrieved
        /// from the LocalMachine keystore and used to sign the xml document.
        /// Be sure to have appropriate permissions set on the keystore.
        /// </param>
        /// <param name="xmlDoc">
        /// XML document to be signed.
        /// </param>
        /// <param name="targetReferenceId">
        /// Reference element that will be specified as signed.
        /// </param>
        /// <param name="includePublicKey">
        /// Flag to determine whether to include the public key in the
        /// signed xml.
        /// </param>
        /// <param name="serviceProviderInstance">
        /// ServiceProvider instance for retreaving Signature transform
        /// and canonicalization method
        /// </param>
        public static void SignXml(string certFriendlyName, IXPathNavigable xmlDoc, string targetReferenceId, bool includePublicKey, ServiceProvider serviceProviderInstance)
        {
            if (string.IsNullOrEmpty(certFriendlyName))
            {
                throw new Saml2Exception(Resources.SignedXmlInvalidCertFriendlyName);
            }

            if (xmlDoc == null)
            {
                throw new Saml2Exception(Resources.SignedXmlInvalidXml);
            }

            if (string.IsNullOrEmpty(targetReferenceId))
            {
                throw new Saml2Exception(Resources.SignedXmlInvalidTargetRefId);
            }

            X509Certificate2 cert = FedletCertificateFactory.GetCertificateByFriendlyName(certFriendlyName);

            if (cert == null)
            {
                throw new Saml2Exception(Resources.SignedXmlCertNotFound);
            }

            XmlDocument xml       = (XmlDocument)xmlDoc;
            SignedXml   signedXml = new SignedXml(xml);

            signedXml.SigningKey = cert.PrivateKey;

            if (includePublicKey)
            {
                KeyInfo keyInfo = new KeyInfo();
                keyInfo.AddClause(new KeyInfoX509Data(cert));
                signedXml.KeyInfo = keyInfo;
            }

            Reference reference = new Reference();

            reference.Uri = "#" + targetReferenceId;

            //Read the transform type and canonicalization method from sp-extended.xml
            string    transformType = serviceProviderInstance.SignatureTransformMethod;
            string    canonicalizationMethodType = serviceProviderInstance.CanonicalizationMethod;
            Transform sigTransform;

            //Implement the gathered data
            switch (transformType)
            {
            case "XmlDsigExcC14NTransform":
                sigTransform = new XmlDsigExcC14NTransform();
                break;

            case "XmlDsigExcC14NWithCommentsTransform":
                sigTransform = new XmlDsigExcC14NWithCommentsTransform();
                break;

            default:
                sigTransform = new XmlDsigEnvelopedSignatureTransform();
                break;
            }

            if (canonicalizationMethodType != null &&
                (canonicalizationMethodType == SignedXml.XmlDsigExcC14NTransformUrl ||
                 canonicalizationMethodType == SignedXml.XmlDsigExcC14NWithCommentsTransformUrl))
            {
                signedXml.Signature.SignedInfo.CanonicalizationMethod = canonicalizationMethodType;
            }

            reference.AddTransform(sigTransform);
            signedXml.AddReference(reference);
            signedXml.ComputeSignature();

            XmlElement xmlSignature = signedXml.GetXml();

            XmlNamespaceManager nsMgr = new XmlNamespaceManager(xml.NameTable);

            nsMgr.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
            nsMgr.AddNamespace("saml", Saml2Constants.NamespaceSamlAssertion);
            nsMgr.AddNamespace("samlp", Saml2Constants.NamespaceSamlProtocol);

            XmlNode issuerNode = xml.DocumentElement.SelectSingleNode("saml:Issuer", nsMgr);

            if (issuerNode != null)
            {
                xml.DocumentElement.InsertAfter(xmlSignature, issuerNode);
            }
            else
            {
                // Insert as a child to the target reference id
                XmlNode targetNode = xml.DocumentElement.SelectSingleNode("//*[@ID='" + targetReferenceId + "']", nsMgr);
                targetNode.PrependChild(xmlSignature);
            }
        }
예제 #4
0
        public static void ReaderWriter_C14N_DifferentReadersWriters()
        {
            int          count   = 0;
            var          params1 = TestConfigHelper.GetTest("ReaderWriter_C14N_DifferentReadersWriters_ParamGroup1");
            var          params2 = TestConfigHelper.GetTest("ReaderWriter_C14N_DifferentReadersWriters_ParamGroup2");
            var          params3 = TestConfigHelper.GetTest("ReaderWriter_C14N_DifferentReadersWriters_ParamGroup3");
            var          params4 = TestConfigHelper.GetTest("ReaderWriter_C14N_DifferentReadersWriters_ParamGroup4");
            Transform    transform;
            MemoryStream canonicalStream;
            MemoryStream ms;
            Stream       transformedOutput;

            byte[] outputFromSecurity;
            byte[] outputFromIndigo;

            //TestC14NInMultipleWriters
            foreach (var input in params1.Inputs)
            {
                foreach (var input2 in params2.Inputs)
                {
                    foreach (var input3 in params3.Inputs)
                    {
                        count++;
                        string rwTypeStr = input.Arguments[0].Value;
                        ReaderWriterFactory.ReaderWriterType rwType = (ReaderWriterFactory.ReaderWriterType)Enum.Parse(typeof(ReaderWriterFactory.ReaderWriterType), rwTypeStr, true);
                        Encoding encoding          = Encoding.GetEncoding((string)input.Arguments[1].Value);
                        string   sampleXmlFileName = input2.Arguments[0].Value;
                        bool     mustSupportV14N   = input.Arguments[2].Value == "true";
                        string   baselineFileName  = input2.Arguments[1].Value;

                        bool testWithComments = input3.Arguments[0].Value == "true";

                        XmlDocument xmlDoc = new XmlDocument();
                        xmlDoc.PreserveWhitespace = true;

                        if (testWithComments)
                        {
                            transform = new XmlDsigExcC14NWithCommentsTransform();
                        }
                        else
                        {
                            transform = new XmlDsigExcC14NTransform();
                        }
                        xmlDoc.Load(baselineFileName);
                        transform.LoadInput(xmlDoc);
                        transformedOutput  = transform.GetOutput(typeof(Stream)) as Stream;
                        outputFromSecurity = StreamToByteArray(transformedOutput);

                        byte[] sampleXmlFileBytes = File.ReadAllBytes(sampleXmlFileName);

                        ms = new MemoryStream();
                        XmlWriter w = ReaderWriterFactory.CreateXmlWriter(rwType, ms, encoding);

                        canonicalStream = new MemoryStream();

                        XmlDictionaryWriter dicWriter = w as XmlDictionaryWriter;
                        if (dicWriter == null)
                        {
                            dicWriter = XmlDictionaryWriter.CreateDictionaryWriter(w);
                        }

                        if (!dicWriter.CanCanonicalize)
                        {
                            Assert.False(mustSupportV14N, "Error, writer should support C14N, but it doesn't!");
                            continue;
                        }

                        dicWriter.WriteStartElement("MyRoot");
                        dicWriter.StartCanonicalization(canonicalStream, testWithComments, null);
                        FileStream fs            = File.OpenRead(sampleXmlFileName);
                        XmlReader  webdataReader = XmlReader.Create(fs);
                        CopyXmlToWriter(webdataReader, dicWriter);
                        dicWriter.EndCanonicalization();
                        dicWriter.WriteEndElement();
                        dicWriter.Flush();
                        webdataReader.Close();
                        fs.Close();

                        outputFromIndigo = canonicalStream.ToArray();

                        Helper.DumpToFile(outputFromSecurity);
                        Helper.DumpToFile(outputFromIndigo);
                        Assert.True(Enumerable.SequenceEqual(outputFromSecurity, outputFromIndigo), $"ReaderWriter_C14N_DifferentReadersWriters test variation #{count} failed");
                    }
                }
            }

            //TestC14NInReader
            foreach (var input in params4.Inputs)
            {
                count++;
                string sampleXmlFileName = input.Arguments[3].Value;
                string rwTypeStr         = input.Arguments[0].Value;
                ReaderWriterFactory.ReaderWriterType rwType = (ReaderWriterFactory.ReaderWriterType)Enum.Parse(typeof(ReaderWriterFactory.ReaderWriterType), rwTypeStr, true);
                Encoding encoding = Encoding.GetEncoding((string)input.Arguments[1].Value);

                bool   mustSupportV14N  = input.Arguments[2].Value == "true";
                string baselineFileName = "ReaderWriter_C14N_BaselineXML_OnlyLF.xml";

                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.PreserveWhitespace = true;
                transform = new XmlDsigExcC14NTransform();
                xmlDoc.Load(baselineFileName);
                transform.LoadInput(xmlDoc);
                transformedOutput  = transform.GetOutput(typeof(Stream)) as Stream;
                outputFromSecurity = StreamToByteArray(transformedOutput);
                byte[] sampleXmlFileBytes = File.ReadAllBytes(sampleXmlFileName);

                XmlReader           r         = ReaderWriterFactory.CreateXmlReader(rwType, sampleXmlFileBytes, encoding);
                XmlDictionaryReader dicReader = r as XmlDictionaryReader;
                if (dicReader == null)
                {
                    dicReader = XmlDictionaryReader.CreateDictionaryReader(r);
                }

                canonicalStream = new MemoryStream();

                if (!dicReader.CanCanonicalize)
                {
                    Assert.False(mustSupportV14N, "Error, reader should support C14N, but it doesn't!");
                    continue;
                }

                dicReader.StartCanonicalization(canonicalStream, false, null);

                canonicalStream.Position = 0;
                string str = new StreamReader(canonicalStream).ReadToEnd();
                canonicalStream.Position = 0;
                while (dicReader.Read())
                {
                    ;                      // simply read it all into the C14N writer
                }
                dicReader.EndCanonicalization();
                dicReader.Close();

                outputFromIndigo = canonicalStream.ToArray();
                Helper.DumpToFile(outputFromSecurity);
                Helper.DumpToFile(outputFromIndigo);
                Assert.True(Enumerable.SequenceEqual(outputFromSecurity, outputFromIndigo), $"ReaderWriter_C14N_DifferentReadersWriters test variation #{count} failed");
            }

            //TestC14NWriterWithManyAttributes
            int           numberOfAttributes = 1000;
            int           seed   = (int)DateTime.Now.Ticks;
            Random        rndGen = new Random(seed);
            StringBuilder sb     = new StringBuilder();

            sb.Append("<Root><Element");
            int prefixIndex = 0;

            for (int i = 0; i < numberOfAttributes; i++)
            {
                string namespaceUri = null;
                string prefix       = null;
                if ((rndGen.Next() % 5) == 0)
                {
                    prefix       = "p" + (prefixIndex++);
                    namespaceUri = "http://namespace_" + i;
                }

                string localName = "attr" + i;
                string value     = "attrValue" + i;
                if (prefix == null)
                {
                    sb.Append($" {localName}=\"{value}\"");
                }
                else
                {
                    sb.Append($" {prefix}:{localName}=\"{2}\" xmlns:{value}=\"{namespaceUri}\"");
                }
            }
            sb.Append(">Hello world</Element></Root>");
            string      xmlString = sb.ToString();
            XmlDocument doc       = new XmlDocument();

            doc.LoadXml(xmlString);

            ms = new MemoryStream();
            XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(ms);

            canonicalStream = new MemoryStream();
            writer.StartCanonicalization(canonicalStream, false, null);
            doc.WriteTo(writer);
            writer.Flush();
            writer.EndCanonicalization();
            outputFromIndigo = canonicalStream.ToArray();
            byte[] nonCanonicalOutput = ms.ToArray();

            XmlDsigExcC14NTransform transform2 = new XmlDsigExcC14NTransform();

            transform2.LoadInput(doc);
            transformedOutput  = transform2.GetOutput(typeof(Stream)) as Stream;
            outputFromSecurity = StreamToByteArray(transformedOutput);

            Helper.DumpToFile(outputFromSecurity);
            Helper.DumpToFile(outputFromIndigo);
            Helper.DumpToFile(nonCanonicalOutput);

            Assert.True(Enumerable.SequenceEqual(outputFromSecurity, outputFromIndigo), $"ReaderWriter_C14N_DifferentReadersWriters test variation #{count} failed");
            count++;
            Assert.Equal(params1.Inputs.Count * params2.Inputs.Count * params3.Inputs.Count + params4.Inputs.Count + 1, count);
        }
예제 #5
0
        /// <summary>
        /// Signs the specified xml document with the certificate found in
        /// the local machine matching the provided friendly name and
        /// referring to the specified target reference ID.
        /// </summary>
        /// <param name="certFriendlyName">
        /// Friendly Name of the X509Certificate to be retrieved
        /// from the LocalMachine keystore and used to sign the xml document.
        /// Be sure to have appropriate permissions set on the keystore.
        /// </param>
        /// <param name="xmlDoc">
        /// XML document to be signed.
        /// </param>
        /// <param name="targetReferenceId">
        /// Reference element that will be specified as signed.
        /// </param>
        /// <param name="includePublicKey">
        /// Flag to determine whether to include the public key in the
        /// signed xml.
        /// </param>
        /// <param name="signatureSigningAlgorithm">
        /// The algorithm used to sign the xml.
        /// </param>
        /// <param name="digestAlgorithm">
        /// The method used to create the message digest.
        /// </param>
        /// <param name="serviceProviderInstance">
        /// ServiceProvider instance for retreaving Signature transform
        /// and canonicalization method
        /// </param>
        public static void SignXml(string certFriendlyName,
                                   IXPathNavigable xmlDoc,
                                   string targetReferenceId,
                                   bool includePublicKey,
                                   string signatureSigningAlgorithm,
                                   string digestAlgorithm,
                                   ServiceProvider serviceProviderInstance)
        {
            if (string.IsNullOrEmpty(certFriendlyName))
            {
                throw new Saml2Exception(Resources.SignedXmlInvalidCertFriendlyName);
            }

            if (xmlDoc == null)
            {
                throw new Saml2Exception(Resources.SignedXmlInvalidXml);
            }

            if (string.IsNullOrEmpty(targetReferenceId))
            {
                throw new Saml2Exception(Resources.SignedXmlInvalidTargetRefId);
            }

            X509Certificate2 cert = FedletCertificateFactory.GetCertificateByFriendlyName(certFriendlyName);

            if (cert == null)
            {
                throw new Saml2Exception(Resources.SignedXmlCertNotFound);
            }

            XmlDocument xml       = (XmlDocument)xmlDoc;
            SignedXml   signedXml = new SignedXml(xml);

            var cspParams = new CspParameters(24)
            {
                KeyContainerName = "XML_DISG_RSA_KEY"
            };
            var key = new RSACryptoServiceProvider(cspParams);

            key.FromXmlString(cert.PrivateKey.ToXmlString(true));

            signedXml.SigningKey = key;

            if (includePublicKey)
            {
                KeyInfo keyInfo = new KeyInfo();
                keyInfo.AddClause(new KeyInfoX509Data(cert));
                signedXml.KeyInfo = keyInfo;
            }

            Reference reference = new Reference();

            reference.Uri = "#" + targetReferenceId;

            //Read the transform type, signature digest and canonicalization method from sp-extended.xml
            string    transformType = serviceProviderInstance.SignatureTransformMethod;
            string    canonicalizationMethodType = serviceProviderInstance.CanonicalizationMethod;
            Transform sigTransform;

            //Implement the gathered data
            switch (transformType)
            {
            case "XmlDsigExcC14NTransform":
                sigTransform = new XmlDsigExcC14NTransform();
                break;

            case "XmlDsigExcC14NWithCommentsTransform":
                sigTransform = new XmlDsigExcC14NWithCommentsTransform();
                break;

            default:
                sigTransform = new XmlDsigEnvelopedSignatureTransform();
                break;
            }

            if (canonicalizationMethodType != null &&
                (canonicalizationMethodType == SignedXml.XmlDsigExcC14NTransformUrl ||
                 canonicalizationMethodType == SignedXml.XmlDsigExcC14NWithCommentsTransformUrl))
            {
                signedXml.Signature.SignedInfo.CanonicalizationMethod = canonicalizationMethodType;
            }

            reference.AddTransform(sigTransform);
            bool bIsUsingExtendedAlgorithms = false;

            if (!String.IsNullOrEmpty(digestAlgorithm))
            {
                reference.DigestMethod = digestAlgorithm;
                if (!digestAlgorithm.ToLowerInvariant().Contains("xmldsig#sha1"))
                {
                    bIsUsingExtendedAlgorithms = true;
                }
            }

            signedXml.AddReference(reference);
            if (!String.IsNullOrEmpty(signatureSigningAlgorithm))
            {
                signedXml.SignedInfo.SignatureMethod = signatureSigningAlgorithm;
                if (!signatureSigningAlgorithm.ToLowerInvariant().Contains("-sha1"))
                {
                    bIsUsingExtendedAlgorithms = true;
                }
            }

            if (bIsUsingExtendedAlgorithms && !FedletSignedSignatureSupportSingleton.IsInitialised)
            {
                throw new Saml2Exception(Resources.ExtendedAlgorithmsUnavailable);
            }

            signedXml.ComputeSignature();
            XmlElement          xmlSignature = signedXml.GetXml();
            XmlNamespaceManager nsMgr        = new XmlNamespaceManager(xml.NameTable);

            nsMgr.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
            nsMgr.AddNamespace("saml", Saml2Constants.NamespaceSamlAssertion);
            nsMgr.AddNamespace("samlp", Saml2Constants.NamespaceSamlProtocol);

            XmlNode issuerNode = xml.DocumentElement.SelectSingleNode("saml:Issuer", nsMgr);

            if (issuerNode != null)
            {
                xml.DocumentElement.InsertAfter(xmlSignature, issuerNode);
            }
            else
            {
                // Insert as a child to the target reference id
                XmlNode targetNode = xml.DocumentElement.SelectSingleNode("//*[@ID='" + targetReferenceId + "']", nsMgr);
                targetNode.PrependChild(xmlSignature);
            }
        }