/// <summary> /// Gets the return to signature. /// </summary> /// <param name="returnTo">The return to.</param> /// <returns>The generated signature.</returns> /// <remarks> /// Only the parameters in the return_to URI are signed, rather than the base URI /// itself, in order that OPs that might change the return_to's implicit port :80 part /// or other minor changes do not invalidate the signature. /// </remarks> private string GetReturnToSignature(Uri returnTo) { Contract.Requires <ArgumentNullException>(returnTo != null); // Assemble the dictionary to sign, taking care to remove the signature itself // in order to accurately reproduce the original signature (which of course didn't include // the signature). // Also we need to sort the dictionary's keys so that we sign in the same order as we did // the last time. var returnToParameters = HttpUtility.ParseQueryString(returnTo.Query); returnToParameters.Remove(ReturnToSignatureParameterName); var sortedReturnToParameters = new SortedDictionary <string, string>(StringComparer.OrdinalIgnoreCase); foreach (string key in returnToParameters) { sortedReturnToParameters.Add(key, returnToParameters[key]); } Logger.Bindings.DebugFormat("ReturnTo signed data: {0}{1}", Environment.NewLine, sortedReturnToParameters.ToStringDeferred()); // Sign the parameters. byte[] bytesToSign = KeyValueFormEncoding.GetBytes(sortedReturnToParameters); byte[] signature; try { signature = this.secretManager.Sign(bytesToSign, returnToParameters[ReturnToSignatureHandleParameterName]); } catch (ProtocolException ex) { throw ErrorUtilities.Wrap(ex, OpenIdStrings.MaximumAuthenticationTimeExpired); } string signatureBase64 = Convert.ToBase64String(signature); return(signatureBase64); }
/// <summary> /// Calculates the signature for a given message. /// </summary> /// <param name="signedMessage">The message to sign or verify.</param> /// <param name="association">The association to use to sign the message.</param> /// <returns>The calculated signature of the method.</returns> protected string GetSignature(ITamperResistantOpenIdMessage signedMessage, Association association) { Requires.NotNull(signedMessage, "signedMessage"); Requires.That(!string.IsNullOrEmpty(signedMessage.SignedParameterOrder), "signedMessage", "SignedParameterOrder must not be null or empty."); Requires.NotNull(association, "association"); // Prepare the parts to sign, taking care to replace an openid.mode value // of check_authentication with its original id_res so the signature matches. MessageDictionary dictionary = this.Channel.MessageDescriptions.GetAccessor(signedMessage); var parametersToSign = from name in signedMessage.SignedParameterOrder.Split(',') let prefixedName = Protocol.V20.openid.Prefix + name select new KeyValuePair <string, string>(name, dictionary.GetValueOrThrow(prefixedName, signedMessage)); byte[] dataToSign = KeyValueFormEncoding.GetBytes(parametersToSign); string signature = Convert.ToBase64String(association.Sign(dataToSign)); if (Logger.Signatures.IsDebugEnabled) { Logger.Signatures.DebugFormat( "Signing these message parts: {0}{1}{0}Base64 representation of signed data: {2}{0}Signature: {3}", Environment.NewLine, parametersToSign.ToStringDeferred(), Convert.ToBase64String(dataToSign), signature); } return(signature); }
/// <summary> /// Calculates the signature for a given message. /// </summary> /// <param name="signedMessage">The message to sign or verify.</param> /// <param name="association">The association to use to sign the message.</param> /// <returns>The calculated signature of the method.</returns> private static string GetSignature(ITamperResistantOpenIdMessage signedMessage, Association association) { ErrorUtilities.VerifyArgumentNotNull(signedMessage, "signedMessage"); ErrorUtilities.VerifyNonZeroLength(signedMessage.SignedParameterOrder, "signedMessage.SignedParameterOrder"); ErrorUtilities.VerifyArgumentNotNull(association, "association"); // Prepare the parts to sign, taking care to replace an openid.mode value // of check_authentication with its original id_res so the signature matches. MessageDictionary dictionary = new MessageDictionary(signedMessage); var parametersToSign = from name in signedMessage.SignedParameterOrder.Split(',') let prefixedName = Protocol.V20.openid.Prefix + name select new KeyValuePair <string, string>(name, dictionary[prefixedName]); byte[] dataToSign = KeyValueFormEncoding.GetBytes(parametersToSign); string signature = Convert.ToBase64String(association.Sign(dataToSign)); if (signingLogger.IsDebugEnabled) { signingLogger.DebugFormat( CultureInfo.InvariantCulture, "Signing these message parts: {0}{1}{0}Base64 representation of signed data: {2}{0}Signature: {3}", Environment.NewLine, parametersToSign.ToStringDeferred(), Convert.ToBase64String(dataToSign), signature); } return(signature); }
/// <summary> /// Gets the return to signature. /// </summary> /// <param name="returnTo">The return to.</param> /// <param name="cryptoKey">The crypto key.</param> /// <returns> /// The generated signature. /// </returns> /// <remarks> /// Only the parameters in the return_to URI are signed, rather than the base URI /// itself, in order that OPs that might change the return_to's implicit port :80 part /// or other minor changes do not invalidate the signature. /// </remarks> private byte[] GetReturnToSignature(Uri returnTo, CryptoKey cryptoKey = null) { Requires.NotNull(returnTo, "returnTo"); // Assemble the dictionary to sign, taking care to remove the signature itself // in order to accurately reproduce the original signature (which of course didn't include // the signature). // Also we need to sort the dictionary's keys so that we sign in the same order as we did // the last time. var returnToParameters = HttpUtility.ParseQueryString(returnTo.Query); returnToParameters.Remove(ReturnToSignatureParameterName); var sortedReturnToParameters = new SortedDictionary <string, string>(StringComparer.OrdinalIgnoreCase); foreach (string key in returnToParameters) { sortedReturnToParameters.Add(key, returnToParameters[key]); } Logger.Bindings.DebugFormat("ReturnTo signed data: {0}{1}", Environment.NewLine, sortedReturnToParameters.ToStringDeferred()); // Sign the parameters. byte[] bytesToSign = KeyValueFormEncoding.GetBytes(sortedReturnToParameters); byte[] signature; try { if (cryptoKey == null) { cryptoKey = this.cryptoKeyStore.GetKey(SecretUri.AbsoluteUri, returnToParameters[ReturnToSignatureHandleParameterName]); ErrorUtilities.VerifyProtocol( cryptoKey != null, MessagingStrings.MissingDecryptionKeyForHandle, SecretUri.AbsoluteUri, returnToParameters[ReturnToSignatureHandleParameterName]); } using (var signer = HmacAlgorithms.Create(HmacAlgorithms.HmacSha256, cryptoKey.Key)) { signature = signer.ComputeHash(bytesToSign); } } catch (ProtocolException ex) { throw ErrorUtilities.Wrap(ex, OpenIdStrings.MaximumAuthenticationTimeExpired); } return(signature); }
/// <summary> /// Queues a message for sending in the response stream where the fields /// are sent in the response stream in querystring style. /// </summary> /// <param name="response">The message to send as a response.</param> /// <returns> /// The pending user agent redirect based message to be sent as an HttpResponse. /// </returns> /// <remarks> /// This method implements spec V1.0 section 5.3. /// </remarks> protected override OutgoingWebResponse PrepareDirectResponse(IProtocolMessage response) { var messageAccessor = this.MessageDescriptions.GetAccessor(response); var fields = messageAccessor.Serialize(); byte[] keyValueEncoding = KeyValueFormEncoding.GetBytes(fields); OutgoingWebResponse preparedResponse = new OutgoingWebResponse(); preparedResponse.Headers.Add(HttpResponseHeader.ContentType, KeyValueFormContentType); preparedResponse.OriginalMessage = response; preparedResponse.ResponseStream = new MemoryStream(keyValueEncoding); IHttpDirectResponse httpMessage = response as IHttpDirectResponse; if (httpMessage != null) { preparedResponse.Status = httpMessage.HttpStatusCode; } return(preparedResponse); }
/// <summary> /// Queues a message for sending in the response stream where the fields /// are sent in the response stream in querystring style. /// </summary> /// <param name="response">The message to send as a response.</param> /// <returns> /// The pending user agent redirect based message to be sent as an HttpResponse. /// </returns> /// <remarks> /// This method implements spec V1.0 section 5.3. /// </remarks> protected override UserAgentResponse SendDirectMessageResponse(IProtocolMessage response) { ErrorUtilities.VerifyArgumentNotNull(response, "response"); var serializer = MessageSerializer.Get(response.GetType()); var fields = serializer.Serialize(response); byte[] keyValueEncoding = KeyValueFormEncoding.GetBytes(fields); UserAgentResponse preparedResponse = new UserAgentResponse(); preparedResponse.Headers.Add(HttpResponseHeader.ContentType, KeyValueFormContentType); preparedResponse.OriginalMessage = response; preparedResponse.ResponseStream = new MemoryStream(keyValueEncoding); IHttpDirectResponse httpMessage = response as IHttpDirectResponse; if (httpMessage != null) { preparedResponse.Status = httpMessage.HttpStatusCode; } return(preparedResponse); }
/// <summary> /// Queues a message for sending in the response stream where the fields /// are sent in the response stream in querystring style. /// </summary> /// <param name="response">The message to send as a response.</param> /// <returns> /// The pending user agent redirect based message to be sent as an HttpResponse. /// </returns> /// <remarks> /// This method implements spec V1.0 section 5.3. /// </remarks> protected override HttpResponseMessage PrepareDirectResponse(IProtocolMessage response) { var messageAccessor = this.MessageDescriptions.GetAccessor(response); var fields = messageAccessor.Serialize(); byte[] keyValueEncoding = KeyValueFormEncoding.GetBytes(fields); var preparedResponse = new HttpResponseMessageWithOriginal(response); ApplyMessageTemplate(response, preparedResponse); var content = new StreamContent(new MemoryStream(keyValueEncoding)); content.Headers.ContentType = new MediaTypeHeaderValue(KeyValueFormContentType); preparedResponse.Content = content; IHttpDirectResponse httpMessage = response as IHttpDirectResponse; if (httpMessage != null) { preparedResponse.StatusCode = httpMessage.HttpStatusCode; } return(preparedResponse); }