/// <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 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 = { '&' }; var queryParams = new NameValueCollection(); foreach (var pairs in queryString.Split(queryStringSep)) { var key = pairs.Substring(0, pairs.IndexOf("=", StringComparison.Ordinal)); var value = pairs.Substring(pairs.IndexOf("=", StringComparison.Ordinal) + 1); queryParams[key] = value; } if (string.IsNullOrEmpty(queryParams[Saml2Constants.SignatureAlgorithm])) { throw new Saml2Exception(Resources.SignedQueryStringSigAlgMissing); } var cert = m_certificateFactory.GetCertificateByFriendlyName(certFriendlyName, m_logger); if (cert == null) { throw new Saml2Exception(Resources.SignedQueryStringCertNotFound); } if (!cert.HasPrivateKey) { throw new Saml2Exception(Resources.SignedQueryStringCertHasNoPrivateKey); } var signatureAlgorithmUrl = HttpUtility.UrlDecode(queryParams[Saml2Constants.SignatureAlgorithm]); var hashAlgorithmName = GetHashAlgorithmNameFromSignatureAlgorithmUrl(signatureAlgorithmUrl); using (var signingKey = cert.GetRSAPrivateKey()) { var privateKey = signingKey; var signature = privateKey.SignData(Encoding.UTF8.GetBytes(queryString), hashAlgorithmName, RSASignaturePadding.Pkcs1); var encodedSignature = Convert.ToBase64String(signature); var signedQueryString = queryString + "&" + Saml2Constants.Signature + "=" + HttpUtility.UrlEncode(encodedSignature); return(signedQueryString); } }
/// <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 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 = { '&' }; var 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 = _certificateFactory.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) { var privateKey = (RSACryptoServiceProvider)cert.PrivateKey; byte[] signature = privateKey.SignData( Encoding.UTF8.GetBytes(queryString), new SHA1CryptoServiceProvider()); encodedSignature = Convert.ToBase64String(signature); } else { throw new Saml2Exception(Resources.SignedQueryStringSigAlgNotSupported); } string signedQueryString = queryString + "&" + Saml2Constants.Signature + "=" + HttpUtility.UrlEncode(encodedSignature); return(signedQueryString); }