コード例 #1
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>
        public static void SignXml(string certFriendlyName, IXPathNavigable xmlDoc, string targetReferenceId, bool includePublicKey)
        {
            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;

            XmlDsigEnvelopedSignatureTransform envelopSigTransform = new XmlDsigEnvelopedSignatureTransform();

            reference.AddTransform(envelopSigTransform);

            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);
            }
        }
コード例 #2
0
        /// <summary>
        /// Signs the specified query string with the certificate found in the
        /// local machine matching the provided friendly name.  The algorithm
        /// is expected to be one of the parameters in the query string.
        /// </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="queryString">Query string to sign.</param>
        /// <returns>
        /// A signed query string where a digital signature is added.
        /// </returns>
        public static string SignQueryString(string certFriendlyName, string queryString)
        {
            if (string.IsNullOrEmpty(certFriendlyName))
            {
                throw new Saml2Exception(Resources.SignedQueryStringInvalidCertFriendlyName);
            }

            if (string.IsNullOrEmpty(queryString))
            {
                throw new Saml2Exception(Resources.SignedQueryStringInvalidQueryString);
            }

            char[] queryStringSep           = { '&' };
            NameValueCollection queryParams = new NameValueCollection();

            foreach (string pairs in queryString.Split(queryStringSep))
            {
                string key   = pairs.Substring(0, pairs.IndexOf("=", StringComparison.Ordinal));
                string value = pairs.Substring(pairs.IndexOf("=", StringComparison.Ordinal) + 1);

                queryParams[key] = value;
            }

            if (string.IsNullOrEmpty(queryParams[Saml2Constants.SignatureAlgorithm]))
            {
                throw new Saml2Exception(Resources.SignedQueryStringSigAlgMissing);
            }

            X509Certificate2 cert = FedletCertificateFactory.GetCertificateByFriendlyName(certFriendlyName);

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

            if (!cert.HasPrivateKey)
            {
                throw new Saml2Exception(Resources.SignedQueryStringCertHasNoPrivateKey);
            }

            string encodedSignature   = string.Empty;
            string signatureAlgorithm = HttpUtility.UrlDecode(queryParams[Saml2Constants.SignatureAlgorithm]);

            if (signatureAlgorithm == Saml2Constants.SignatureAlgorithmRsa)
            {
                RSACryptoServiceProvider privateKey = (RSACryptoServiceProvider)cert.PrivateKey;
                byte[] signature = privateKey.SignData(
                    Encoding.UTF8.GetBytes(queryString.ToString()),
                    new SHA1CryptoServiceProvider());

                encodedSignature = Convert.ToBase64String(signature);
            }
            else
            {
                throw new Saml2Exception(Resources.SignedQueryStringSigAlgNotSupported);
            }

            string signedQueryString
                = queryString
                  + "&" + Saml2Constants.Signature
                  + "=" + HttpUtility.UrlEncode(encodedSignature);

            return(signedQueryString);
        }
コード例 #3
0
        /// <summary>
        /// Encrypts the NameID attribute of the AttributeQuery request.
        /// </summary>
        /// <param name="certFriendlyName">
        /// Friendly Name of the X509Certificate to be retrieved
        /// from the LocalMachine keystore and used to encrypt generated symmetric key.
        /// Be sure to have appropriate permissions set on the keystore.
        /// </param>
        /// <param name="xmlDoc">
        /// XML document to be encrypted.
        /// </param>
        /// <param name="symmetricAlgorithmUri">
        /// Symmetric algorithm uri used for encryption.
        /// </param>
        public static void EncryptAttributeQueryNameID(string certFriendlyName, string symmetricAlgorithmUri, XmlDocument xmlDoc)
        {
            if (string.IsNullOrWhiteSpace(certFriendlyName))
            {
                throw new Saml2Exception(Resources.EncryptedXmlInvalidCertFriendlyName);
            }

            if (string.IsNullOrWhiteSpace(symmetricAlgorithmUri))
            {
                throw new Saml2Exception(Resources.EncryptedXmlInvalidEncrAlgorithm);
            }

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

            X509Certificate2 cert = FedletCertificateFactory.GetCertificateByFriendlyName(certFriendlyName);

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

            XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlDoc.NameTable);

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

            string  xpath = "/samlp:AttributeQuery/saml:Subject/saml:NameID";
            XmlNode root  = xmlDoc.DocumentElement;
            XmlNode node  = root.SelectSingleNode(xpath, nsMgr);

            XmlNode encryptedID = xmlDoc.CreateNode(XmlNodeType.Element, "EncryptedID", Saml2Constants.NamespaceSamlAssertion);

            node.ParentNode.PrependChild(encryptedID);

            XmlElement elementToEncrypt = (XmlElement)encryptedID.AppendChild(node.Clone());

            if (elementToEncrypt == null)
            {
                throw new Saml2Exception(Resources.EncryptedXmlInvalidXml);
            }
            encryptedID.ParentNode.RemoveChild(node);

            SymmetricAlgorithm alg = Saml2Utils.GetAlgorithm(symmetricAlgorithmUri);

            if (alg == null)
            {
                throw new Saml2Exception(Resources.EncryptedXmlInvalidEncrAlgorithm);
            }

            alg.GenerateKey();

            string        encryptionElementID    = Saml2Utils.GenerateId();
            string        encryptionKeyElementID = Saml2Utils.GenerateId();
            EncryptedData encryptedData          = new EncryptedData();

            encryptedData.Type             = EncryptedXml.XmlEncElementUrl;
            encryptedData.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES128Url);
            encryptedData.Id = encryptionElementID;

            EncryptedXml encryptedXml = new EncryptedXml();

            byte[] encryptedElement = encryptedXml.EncryptData(elementToEncrypt, alg, false);
            encryptedData.CipherData.CipherValue = encryptedElement;
            encryptedData.KeyInfo = new KeyInfo();

            EncryptedKey encryptedKey = new EncryptedKey();

            encryptedKey.Id = encryptionKeyElementID;
            RSA publicKeyRSA = cert.PublicKey.Key as RSA;

            encryptedKey.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);
            encryptedKey.CipherData       = new CipherData(EncryptedXml.EncryptKey(alg.Key, publicKeyRSA, false));

            encryptedData.KeyInfo.AddClause(new KeyInfoRetrievalMethod("#" + encryptionKeyElementID, "http://www.w3.org/2001/04/xmlenc#EncryptedKey"));

            KeyInfoName kin = new KeyInfoName();

            kin.Value = cert.SubjectName.Name;
            encryptedKey.KeyInfo.AddClause(kin);

            EncryptedXml.ReplaceElement(elementToEncrypt, encryptedData, false);

            XmlNode importKeyNode = xmlDoc.ImportNode(encryptedKey.GetXml(), true);

            encryptedID.AppendChild(importKeyNode);
        }
コード例 #4
0
ファイル: Saml2Utils.cs プロジェクト: seanoneillcode/openam-1
        /// <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);
            }
        }
コード例 #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);
            }
        }
コード例 #6
0
        /// <summary>
        /// Signs the specified query string with the certificate found in the
        /// local machine matching the provided friendly name.  The algorithm
        /// is expected to be one of the parameters in the query string.
        /// </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="queryString">Query string to sign.</param>
        /// <returns>
        /// A signed query string where a digital signature is added.
        /// </returns>
        public static string SignQueryString(string certFriendlyName, string queryString)
        {
            if (string.IsNullOrEmpty(certFriendlyName))
            {
                throw new Saml2Exception(Resources.SignedQueryStringInvalidCertFriendlyName);
            }

            if (string.IsNullOrEmpty(queryString))
            {
                throw new Saml2Exception(Resources.SignedQueryStringInvalidQueryString);
            }

            char[] queryStringSep           = { '&' };
            NameValueCollection queryParams = new NameValueCollection();

            foreach (string pairs in queryString.Split(queryStringSep))
            {
                string key   = pairs.Substring(0, pairs.IndexOf("=", StringComparison.Ordinal));
                string value = pairs.Substring(pairs.IndexOf("=", StringComparison.Ordinal) + 1);

                queryParams[key] = value;
            }

            if (string.IsNullOrEmpty(queryParams[Saml2Constants.SignatureAlgorithm]))
            {
                throw new Saml2Exception(Resources.SignedQueryStringSigAlgMissing);
            }

            X509Certificate2 cert = FedletCertificateFactory.GetCertificateByFriendlyName(certFriendlyName);

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

            if (!cert.HasPrivateKey)
            {
                throw new Saml2Exception(Resources.SignedQueryStringCertHasNoPrivateKey);
            }

            string encodedSignature   = string.Empty;
            string signatureAlgorithm = HttpUtility.UrlDecode(queryParams[Saml2Constants.SignatureAlgorithm]);

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

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

            byte[] toBeSigned = Encoding.UTF8.GetBytes(queryString.ToString());
            byte[] signature  = privateKey.SignData(toBeSigned, GetRequestedCryptoServiceProvider(signatureAlgorithm));
            encodedSignature = Convert.ToBase64String(signature);

            string signedQueryString
                = queryString
                  + "&" + Saml2Constants.Signature
                  + "=" + HttpUtility.UrlEncode(encodedSignature);

            return(signedQueryString);
        }