Пример #1
0
        private static void ValidateSignedInfo(SignedXml signedXml, XmlElement xmlElement)
        {
            if (signedXml.SignedInfo.References.Count == 0)
            {
                throw new InvalidSignatureException("No reference found in Xml signature, it doesn't validate the Xml data.");
            }

            if (signedXml.SignedInfo.References.Count != 1)
            {
                throw new InvalidSignatureException("Multiple references for Xml signatures are not allowed.");
            }

            var reference = (Reference)signedXml.SignedInfo.References[0];
            var id        = reference.Uri.Substring(1);

            var idElement = signedXml.GetIdElement(xmlElement.OwnerDocument, id);

            if (idElement != xmlElement)
            {
                throw new InvalidSignatureException("Incorrect reference on Xml signature. The reference must be to the root element of the element containing the signature.");
            }

            foreach (Transform transform in reference.TransformChain)
            {
                if (!allowedTransforms.Contains(transform.Algorithm))
                {
                    throw new InvalidSignatureException(
                              "Transform \"" + transform.Algorithm + "\" found in Xml signature SHOULD NOT be used with SAML2.");
                }
            }
        }
Пример #2
0
        //an XML signature can "cover" not the whole document, but only a part of it
        //.NET's built in "CheckSignature" does not cover this case, it will validate to true.
        //We should check the signature reference, so it "references" the id of the root document element! If not - it's a hack
        private bool ValidateSignatureReference(SignedXml signedXml)
        {
            if (signedXml.SignedInfo.References.Count != 1)             //no ref at all
            {
                return(false);
            }

            var reference = (Reference)signedXml.SignedInfo.References[0];
            var id        = reference.Uri.Substring(1);

            var idElement = signedXml.GetIdElement(_xmlDoc, id);

            if (idElement == _xmlDoc.DocumentElement)
            {
                return(true);
            }
            else             //sometimes its not the "root" doc-element that is being signed, but the "assertion" element
            {
                var assertionNode = _xmlDoc.SelectSingleNode("/samlp:Response/saml:Assertion", _xmlNameSpaceManager) as XmlElement;
                if (assertionNode != idElement)
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #3
0
        // Enveloped or detached 'internally' supported ony.
        internal void Sign(XmlElement rootElement)
        {
            XmlDocument doc = rootElement.OwnerDocument;

            SignedXml signedXml = new SignedXml(rootElement);

            signedXml.SigningKey = _cert.PrivateKey;
            KeyInfo keyInfo = GetKeyInfo();

            signedXml.SignedInfo.CanonicalizationMethod = _canonicalizationMethod;
            if (keyInfo != null)
            {
                signedXml.KeyInfo = keyInfo;
            }

            if (_references.Count > 0)
            {
                foreach (var reference in _references)
                {
                    signedXml.AddReference(NewReference(reference));
                }
            }
            else
            {
                signedXml.AddReference(NewReference(string.Empty)); //Sign entire xml document.
            }

            try
            {
                signedXml.ComputeSignature();
            }
            catch (CryptographicException e)
            {
                throw new DigitalSignException(e);
            }

            XmlElement xmlDSig = signedXml.GetXml();

            if (_detached)
            {
                doc.LoadXml(xmlDSig.OuterXml);
            }
            else
            {
                //Enveloped
                if (_references.Count == 1 && _references[0].StartsWith("#"))
                {
                    XmlElement idElement = signedXml.GetIdElement(doc, _references[0].Substring(1));
                    idElement.AppendChild(doc.ImportNode(xmlDSig, true));
                }
                else
                {
                    rootElement.AppendChild(doc.ImportNode(xmlDSig, true));
                }
            }
        }
        /// <summary>
        /// Verifies the signature.
        /// </summary>
        /// <param name="xml">The XML.</param>
        /// <returns>The issuer certificate</returns>
        protected virtual X509Certificate2 VerifySignature(XElement xml)
        {
            Contract.Requires(xml != null);
            Contract.Ensures(Contract.Result <X509Certificate2>() != null);

            if ((Configuration == null) || (Configuration.IssuerTokenResolver == null))
            {
                throw new SecurityTokenException("No issuer token resolver configured");
            }

            var xmlElement = xml.ToXmlElement();
            var signedXml  = new SignedXml(xmlElement);

            // find signature
            XmlNodeList nodeList = xmlElement.GetElementsByTagName("Signature");

            // throw an exception if no signature was found.
            if (nodeList.Count <= 0)
            {
                throw new CryptographicException("Verification failed: No Signature was found in the document.");
            }

            // throw an exception if more than one signature was found.
            if (nodeList.Count > 1)
            {
                throw new CryptographicException("Verification failed: More that one signature was found for the document.");
            }

            // load the <signature> node.
            signedXml.LoadXml((XmlElement)nodeList[0]);

            // resolve the issuer certificate
            byte[] thumbprint = Convert.FromBase64String(GetIssuerThumbprint(signedXml));
            var    identifier = new X509ThumbprintKeyIdentifierClause(thumbprint);
            var    issuerKey  = Configuration.IssuerTokenResolver.ResolveToken(identifier) as X509SecurityToken;


            // check the signature
            var referenceUri = ((Reference)signedXml.SignedInfo.References[0]).Uri;

            if (!signedXml.CheckSignature(issuerKey.Certificate, true) ||
                (referenceUri != "" && signedXml.GetIdElement(xmlElement.OwnerDocument, referenceUri) != xmlElement))
            {
                throw new CryptographicException("Signature verification failed");
            }

            if (issuerKey.Certificate != null)
            {
                return(issuerKey.Certificate);
            }
            else
            {
                throw new CryptographicException("No issuer certificate found");
            }
        }
Пример #5
0
        private static void ValidateReference(
            SignedXml signedXml,
            XmlElement xmlElement,
            string mininumDigestAlgorithm)
        {
            if (signedXml.SignedInfo.References.Count == 0)
            {
                throw new InvalidSignatureException(
                          "No reference found in Xml signature, it doesn't validate the Xml data.");
            }

            if (signedXml.SignedInfo.References.Count != 1)
            {
                throw new InvalidSignatureException("Multiple references for Xml signatures are not allowed.");
            }

            var reference = (Reference)signedXml.SignedInfo.References[0];

            if (string.IsNullOrWhiteSpace(reference.Uri))
            {
                throw new InvalidSignatureException("Empty reference for Xml signature is not allowed.");
            }

            var id = reference.Uri.Substring(1);

            var idElement = signedXml.GetIdElement(xmlElement.OwnerDocument, id);

            if (idElement != xmlElement)
            {
                throw new InvalidSignatureException(
                          "Incorrect reference on Xml signature. The reference must be to the root element of the element containing the signature.");
            }

            foreach (Transform transform in reference.TransformChain)
            {
                if (!allowedTransforms.Contains(transform.Algorithm))
                {
                    throw new InvalidSignatureException(
                              "Transform \"" + transform.Algorithm +
                              "\" found in Xml signature SHOULD NOT be used with SAML2.");
                }
            }

            if (!DigestAlgorithms.SkipWhile(a => a != mininumDigestAlgorithm)
                .Contains(reference.DigestMethod))
            {
                throw new InvalidSignatureException("The digest method " + reference.DigestMethod
                                                    + " is weaker than the minimum accepted " +
                                                    mininumDigestAlgorithm + ".");
            }
        }
        /// <summary>
        /// an XML signature can "cover" not the whole document, but only a part of it
        /// .NET's built in "CheckSignature" does not cover this case, it will validate to true.
        /// We should check the signature reference, so it "references" the id of the root document element! If not - it's a hack
        /// </summary>
        private bool HasValidSignatureReference(SignedXml signedXml)
        {
            if (signedXml.SignedInfo.References.Count != 1) //no ref at all
            {
                return(false);
            }

            var reference = (Reference)signedXml.SignedInfo.References[0];
            var id        = reference.Uri.Substring(1);

            var idElement = signedXml.GetIdElement(_xmlDoc, id);

            if (idElement == _xmlDoc.DocumentElement)
            {
                return(true);
            }

            var assertionNode = _xmlDoc.SelectSingleNode("/samlp:Response/saml:Assertion", _xmlNameSpaceManager) as XmlElement;

            return(assertionNode == idElement);
        }
Пример #7
0
        /// <summary>
        /// Verifies that there is only one reference in the signature and that the reference in the signature matches the reference in the XML
        /// </summary>
        /// <param name="signedXml">The path to the signed file</param>
        /// <param name="xmlElement">signature and object data of the signed file</param>
        private static void CheckSignatureReference(SignedXml signedXml, XmlElement xmlElement)
        {
            //if no reference at all is found, there is a problem
            if (signedXml.SignedInfo.References.Count == 0)
            {
                throw new Exception("No reference was found in XML signature");
            }

            //if there is more than one reference, there is a problem
            if (signedXml.SignedInfo.References.Count != 1)
            {
                throw new Exception("Multiple references for XML signatures are not allowed");
            }

            var    reference       = (Reference)signedXml.SignedInfo.References[0];
            var    id              = reference.Uri.Substring(1);
            var    idElement       = signedXml.GetIdElement(xmlElement.OwnerDocument, id);
            string signedReference = "";

            //the reference in the XML will be compared to the reference in the signature, if no match, there is a problem
            if (idElement == null)
            {
                XmlNodeList objectNode = xmlElement.GetElementsByTagName("Object", "*");
                //If we dont fine the id above, we will pull the Object element from the file
                if (objectNode.Count == 1)
                {
                    //Create a new attribute.
                    XmlNode testroot = objectNode[0];
                    signedReference = testroot.Attributes[0].Value.ToString();
                }

                //Check the reference from the XML and see if it matches the signature, if it still doesn't there is a problem
                if (id != signedReference)
                {
                    throw new Exception("The signed reference does not match the XML reference");
                }
            }
        }