summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2010-08-12 06:56:07 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2010-08-12 06:56:07 -0700
commit47b0071a7f4f3437ab92f3cc427cd52cfa4d6ff9 (patch)
tree6ef36271bf9c92e641679c5e62da1f22e667f57d /src
parentccc415b8104c66d3d422c1cffd04a4b1b26dfa0c (diff)
downloadDotNetOpenAuth-47b0071a7f4f3437ab92f3cc427cd52cfa4d6ff9.zip
DotNetOpenAuth-47b0071a7f4f3437ab92f3cc427cd52cfa4d6ff9.tar.gz
DotNetOpenAuth-47b0071a7f4f3437ab92f3cc427cd52cfa4d6ff9.tar.bz2
Remaining whitespace lineending fix.
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth/OAuth2/AuthorizationServer.cs94
-rw-r--r--src/DotNetOpenAuth/OAuth2/AuthorizationState.cs10
-rw-r--r--src/DotNetOpenAuth/OAuth2/ChannelElements/EndUserAuthorizationResponseTypeEncoder.cs10
-rw-r--r--src/DotNetOpenAuth/OAuth2/ChannelElements/IDataBagFormatter.cs150
-rw-r--r--src/DotNetOpenAuth/OAuth2/ChannelElements/OAuth2ChannelBase.cs10
-rw-r--r--src/DotNetOpenAuth/OAuth2/ChannelElements/OAuth2ClientChannel.cs74
-rw-r--r--src/DotNetOpenAuth/OAuth2/ChannelElements/UriStyleMessageFormatter.cs632
7 files changed, 490 insertions, 490 deletions
diff --git a/src/DotNetOpenAuth/OAuth2/AuthorizationServer.cs b/src/DotNetOpenAuth/OAuth2/AuthorizationServer.cs
index 83446da..e8844df 100644
--- a/src/DotNetOpenAuth/OAuth2/AuthorizationServer.cs
+++ b/src/DotNetOpenAuth/OAuth2/AuthorizationServer.cs
@@ -91,33 +91,33 @@ namespace DotNetOpenAuth.OAuth2 {
var response = this.PrepareRejectAuthorizationRequest(authorizationRequest, callback);
this.Channel.Send(response);
- }
-
- /// <summary>
- /// Checks the incoming HTTP request for an access token request and prepares a response if the request message was found.
- /// </summary>
- /// <param name="response">The formulated response, or <c>null</c> if the request was not found..</param>
- /// <returns>A value indicating whether any access token request was found in the HTTP request.</returns>
- /// <remarks>
- /// This method assumes that the authorization server and the resource server are the same and that they share a single
- /// asymmetric key for signing and encrypting the access token. If this is not true, use the <see cref="ReadAccessTokenRequest"/> method instead.
- /// </remarks>
+ }
+
+ /// <summary>
+ /// Checks the incoming HTTP request for an access token request and prepares a response if the request message was found.
+ /// </summary>
+ /// <param name="response">The formulated response, or <c>null</c> if the request was not found..</param>
+ /// <returns>A value indicating whether any access token request was found in the HTTP request.</returns>
+ /// <remarks>
+ /// This method assumes that the authorization server and the resource server are the same and that they share a single
+ /// asymmetric key for signing and encrypting the access token. If this is not true, use the <see cref="ReadAccessTokenRequest"/> method instead.
+ /// </remarks>
public bool TryPrepareAccessTokenResponse(out IDirectResponseProtocolMessage response) {
return this.TryPrepareAccessTokenResponse(this.Channel.GetRequestFromContext(), out response);
- }
-
- /// <summary>
- /// Checks the incoming HTTP request for an access token request and prepares a response if the request message was found.
- /// </summary>
- /// <param name="httpRequestInfo">The HTTP request info.</param>
- /// <param name="response">The formulated response, or <c>null</c> if the request was not found..</param>
- /// <returns>A value indicating whether any access token request was found in the HTTP request.</returns>
- /// <remarks>
- /// This method assumes that the authorization server and the resource server are the same and that they share a single
- /// asymmetric key for signing and encrypting the access token. If this is not true, use the <see cref="ReadAccessTokenRequest"/> method instead.
- /// </remarks>
+ }
+
+ /// <summary>
+ /// Checks the incoming HTTP request for an access token request and prepares a response if the request message was found.
+ /// </summary>
+ /// <param name="httpRequestInfo">The HTTP request info.</param>
+ /// <param name="response">The formulated response, or <c>null</c> if the request was not found..</param>
+ /// <returns>A value indicating whether any access token request was found in the HTTP request.</returns>
+ /// <remarks>
+ /// This method assumes that the authorization server and the resource server are the same and that they share a single
+ /// asymmetric key for signing and encrypting the access token. If this is not true, use the <see cref="ReadAccessTokenRequest"/> method instead.
+ /// </remarks>
public bool TryPrepareAccessTokenResponse(HttpRequestInfo httpRequestInfo, out IDirectResponseProtocolMessage response) {
- Contract.Requires<ArgumentNullException>(httpRequestInfo != null, "httpRequestInfo");
+ Contract.Requires<ArgumentNullException>(httpRequestInfo != null, "httpRequestInfo");
Contract.Ensures(Contract.Result<bool>() == (Contract.ValueAtReturn<IDirectResponseProtocolMessage>(out response) != null));
var request = this.ReadAccessTokenRequest(httpRequestInfo);
@@ -131,13 +131,13 @@ namespace DotNetOpenAuth.OAuth2 {
response = null;
return false;
- }
-
- /// <summary>
- /// Reads the access token request.
- /// </summary>
- /// <param name="requestInfo">The request info.</param>
- /// <returns>The Client's request for an access token; or <c>null</c> if no such message was found in the request.</returns>
+ }
+
+ /// <summary>
+ /// Reads the access token request.
+ /// </summary>
+ /// <param name="requestInfo">The request info.</param>
+ /// <returns>The Client's request for an access token; or <c>null</c> if no such message was found in the request.</returns>
public AccessTokenRequestBase ReadAccessTokenRequest(HttpRequestInfo requestInfo = null) {
if (requestInfo == null) {
requestInfo = this.Channel.GetRequestFromContext();
@@ -146,14 +146,14 @@ namespace DotNetOpenAuth.OAuth2 {
AccessTokenRequestBase request;
this.Channel.TryReadFromRequest(requestInfo, out request);
return request;
- }
-
- /// <summary>
- /// Prepares a response to inform the Client that the user has rejected the Client's authorization request.
- /// </summary>
- /// <param name="authorizationRequest">The authorization request.</param>
- /// <param name="callback">The Client callback URL to use when formulating the redirect to send the user agent back to the Client.</param>
- /// <returns>The authorization response message to send to the Client.</returns>
+ }
+
+ /// <summary>
+ /// Prepares a response to inform the Client that the user has rejected the Client's authorization request.
+ /// </summary>
+ /// <param name="authorizationRequest">The authorization request.</param>
+ /// <param name="callback">The Client callback URL to use when formulating the redirect to send the user agent back to the Client.</param>
+ /// <returns>The authorization response message to send to the Client.</returns>
public EndUserAuthorizationFailedResponse PrepareRejectAuthorizationRequest(EndUserAuthorizationRequest authorizationRequest, Uri callback = null) {
Contract.Requires<ArgumentNullException>(authorizationRequest != null, "authorizationRequest");
Contract.Ensures(Contract.Result<EndUserAuthorizationFailedResponse>() != null);
@@ -235,14 +235,14 @@ namespace DotNetOpenAuth.OAuth2 {
}
return response;
- }
-
- /// <summary>
- /// Gets the redirect URL to use for a particular authorization request.
- /// </summary>
- /// <param name="authorizationRequest">The authorization request.</param>
- /// <returns>The URL to redirect to. Never <c>null</c>.</returns>
- /// <exception cref="ProtocolException">Thrown if no callback URL could be determined.</exception>
+ }
+
+ /// <summary>
+ /// Gets the redirect URL to use for a particular authorization request.
+ /// </summary>
+ /// <param name="authorizationRequest">The authorization request.</param>
+ /// <returns>The URL to redirect to. Never <c>null</c>.</returns>
+ /// <exception cref="ProtocolException">Thrown if no callback URL could be determined.</exception>
protected Uri GetCallback(EndUserAuthorizationRequest authorizationRequest) {
Contract.Requires<ArgumentNullException>(authorizationRequest != null, "authorizationRequest");
Contract.Ensures(Contract.Result<Uri>() != null);
diff --git a/src/DotNetOpenAuth/OAuth2/AuthorizationState.cs b/src/DotNetOpenAuth/OAuth2/AuthorizationState.cs
index 75774c2..bfc33aa 100644
--- a/src/DotNetOpenAuth/OAuth2/AuthorizationState.cs
+++ b/src/DotNetOpenAuth/OAuth2/AuthorizationState.cs
@@ -14,11 +14,11 @@ namespace DotNetOpenAuth.OAuth2 {
/// A simple in-memory copy of an authorization state.
/// </summary>
[Serializable]
- public class AuthorizationState : IAuthorizationState {
- /// <summary>
- /// Initializes a new instance of the <see cref="AuthorizationState"/> class.
- /// </summary>
- /// <param name="scopes">The scopes of access being requested or that was obtained.</param>
+ public class AuthorizationState : IAuthorizationState {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AuthorizationState"/> class.
+ /// </summary>
+ /// <param name="scopes">The scopes of access being requested or that was obtained.</param>
public AuthorizationState(IEnumerable<string> scopes = null) {
this.Scope = new HashSet<string>(OAuthUtilities.ScopeStringComparer);
if (scopes != null) {
diff --git a/src/DotNetOpenAuth/OAuth2/ChannelElements/EndUserAuthorizationResponseTypeEncoder.cs b/src/DotNetOpenAuth/OAuth2/ChannelElements/EndUserAuthorizationResponseTypeEncoder.cs
index afcaee9..760dbb4 100644
--- a/src/DotNetOpenAuth/OAuth2/ChannelElements/EndUserAuthorizationResponseTypeEncoder.cs
+++ b/src/DotNetOpenAuth/OAuth2/ChannelElements/EndUserAuthorizationResponseTypeEncoder.cs
@@ -8,11 +8,11 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
using System;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Reflection;
- using DotNetOpenAuth.OAuth2.Messages;
-
- /// <summary>
- /// Encodes/decodes the OAuth 2.0 response_type argument.
- /// </summary>
+ using DotNetOpenAuth.OAuth2.Messages;
+
+ /// <summary>
+ /// Encodes/decodes the OAuth 2.0 response_type argument.
+ /// </summary>
internal class EndUserAuthorizationResponseTypeEncoder : IMessagePartEncoder {
/// <summary>
/// Initializes a new instance of the <see cref="EndUserAuthorizationResponseTypeEncoder"/> class.
diff --git a/src/DotNetOpenAuth/OAuth2/ChannelElements/IDataBagFormatter.cs b/src/DotNetOpenAuth/OAuth2/ChannelElements/IDataBagFormatter.cs
index 108b362..0289821 100644
--- a/src/DotNetOpenAuth/OAuth2/ChannelElements/IDataBagFormatter.cs
+++ b/src/DotNetOpenAuth/OAuth2/ChannelElements/IDataBagFormatter.cs
@@ -1,76 +1,76 @@
-//-----------------------------------------------------------------------
-// <copyright file="IDataBagFormatter.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OAuth2.ChannelElements {
- using System;
- using System.Diagnostics.Contracts;
- using DotNetOpenAuth.Messaging;
-
- /// <summary>
- /// A serializer for <see cref="DataBag"/>-derived types
- /// </summary>
- /// <typeparam name="T">The DataBag-derived type that is to be serialized/deserialized.</typeparam>
- [ContractClass(typeof(IDataBagFormatterContract<>))]
- internal interface IDataBagFormatter<T> where T : DataBag, new() {
- /// <summary>
- /// Serializes the specified message.
- /// </summary>
- /// <param name="message">The message to serialize. Must not be null.</param>
- /// <returns>A non-null, non-empty value.</returns>
- string Serialize(T message);
-
- /// <summary>
- /// Deserializes a <see cref="DataBag"/>.
- /// </summary>
- /// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be nulll.</param>
- /// <param name="data">The serialized form of the <see cref="DataBag"/> to deserialize. Must not be null or empty.</param>
- /// <returns>The deserialized value. Never null.</returns>
- T Deserialize(IProtocolMessage containingMessage, string data);
- }
-
- /// <summary>
- /// Contract class for the IDataBagFormatter interface.
- /// </summary>
- /// <typeparam name="T">The type of DataBag to serialize.</typeparam>
- [ContractClassFor(typeof(IDataBagFormatter<>))]
- internal abstract class IDataBagFormatterContract<T> : IDataBagFormatter<T> where T : DataBag, new() {
- /// <summary>
- /// Prevents a default instance of the <see cref="IDataBagFormatterContract&lt;T&gt;"/> class from being created.
- /// </summary>
- private IDataBagFormatterContract() {
- }
-
- #region IDataBagFormatter<T> Members
-
- /// <summary>
- /// Serializes the specified message.
- /// </summary>
- /// <param name="message">The message to serialize. Must not be null.</param>
- /// <returns>A non-null, non-empty value.</returns>
- string IDataBagFormatter<T>.Serialize(T message) {
- Contract.Requires<ArgumentNullException>(message != null, "message");
- Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<string>()));
-
- throw new System.NotImplementedException();
- }
-
- /// <summary>
- /// Deserializes a <see cref="DataBag"/>.
- /// </summary>
- /// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be nulll.</param>
- /// <param name="data">The serialized form of the <see cref="DataBag"/> to deserialize. Must not be null or empty.</param>
- /// <returns>The deserialized value. Never null.</returns>
- T IDataBagFormatter<T>.Deserialize(IProtocolMessage containingMessage, string data) {
- Contract.Requires<ArgumentNullException>(containingMessage != null, "containingMessage");
- Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(data));
- Contract.Ensures(Contract.Result<T>() != null);
-
- throw new System.NotImplementedException();
- }
-
- #endregion
- }
+//-----------------------------------------------------------------------
+// <copyright file="IDataBagFormatter.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth2.ChannelElements {
+ using System;
+ using System.Diagnostics.Contracts;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A serializer for <see cref="DataBag"/>-derived types
+ /// </summary>
+ /// <typeparam name="T">The DataBag-derived type that is to be serialized/deserialized.</typeparam>
+ [ContractClass(typeof(IDataBagFormatterContract<>))]
+ internal interface IDataBagFormatter<T> where T : DataBag, new() {
+ /// <summary>
+ /// Serializes the specified message.
+ /// </summary>
+ /// <param name="message">The message to serialize. Must not be null.</param>
+ /// <returns>A non-null, non-empty value.</returns>
+ string Serialize(T message);
+
+ /// <summary>
+ /// Deserializes a <see cref="DataBag"/>.
+ /// </summary>
+ /// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be nulll.</param>
+ /// <param name="data">The serialized form of the <see cref="DataBag"/> to deserialize. Must not be null or empty.</param>
+ /// <returns>The deserialized value. Never null.</returns>
+ T Deserialize(IProtocolMessage containingMessage, string data);
+ }
+
+ /// <summary>
+ /// Contract class for the IDataBagFormatter interface.
+ /// </summary>
+ /// <typeparam name="T">The type of DataBag to serialize.</typeparam>
+ [ContractClassFor(typeof(IDataBagFormatter<>))]
+ internal abstract class IDataBagFormatterContract<T> : IDataBagFormatter<T> where T : DataBag, new() {
+ /// <summary>
+ /// Prevents a default instance of the <see cref="IDataBagFormatterContract&lt;T&gt;"/> class from being created.
+ /// </summary>
+ private IDataBagFormatterContract() {
+ }
+
+ #region IDataBagFormatter<T> Members
+
+ /// <summary>
+ /// Serializes the specified message.
+ /// </summary>
+ /// <param name="message">The message to serialize. Must not be null.</param>
+ /// <returns>A non-null, non-empty value.</returns>
+ string IDataBagFormatter<T>.Serialize(T message) {
+ Contract.Requires<ArgumentNullException>(message != null, "message");
+ Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<string>()));
+
+ throw new System.NotImplementedException();
+ }
+
+ /// <summary>
+ /// Deserializes a <see cref="DataBag"/>.
+ /// </summary>
+ /// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be nulll.</param>
+ /// <param name="data">The serialized form of the <see cref="DataBag"/> to deserialize. Must not be null or empty.</param>
+ /// <returns>The deserialized value. Never null.</returns>
+ T IDataBagFormatter<T>.Deserialize(IProtocolMessage containingMessage, string data) {
+ Contract.Requires<ArgumentNullException>(containingMessage != null, "containingMessage");
+ Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(data));
+ Contract.Ensures(Contract.Result<T>() != null);
+
+ throw new System.NotImplementedException();
+ }
+
+ #endregion
+ }
} \ No newline at end of file
diff --git a/src/DotNetOpenAuth/OAuth2/ChannelElements/OAuth2ChannelBase.cs b/src/DotNetOpenAuth/OAuth2/ChannelElements/OAuth2ChannelBase.cs
index 913bff0..d9f33a0 100644
--- a/src/DotNetOpenAuth/OAuth2/ChannelElements/OAuth2ChannelBase.cs
+++ b/src/DotNetOpenAuth/OAuth2/ChannelElements/OAuth2ChannelBase.cs
@@ -11,11 +11,11 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
using System.Text;
using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OAuth2.Messages;
-
- /// <summary>
- /// The base messaging channel used by OAuth 2.0 parties.
- /// </summary>
+ using DotNetOpenAuth.OAuth2.Messages;
+
+ /// <summary>
+ /// The base messaging channel used by OAuth 2.0 parties.
+ /// </summary>
internal abstract class OAuth2ChannelBase : StandardMessageFactoryChannel {
/// <summary>
/// The messages receivable by this channel.
diff --git a/src/DotNetOpenAuth/OAuth2/ChannelElements/OAuth2ClientChannel.cs b/src/DotNetOpenAuth/OAuth2/ChannelElements/OAuth2ClientChannel.cs
index 76ccc25..fde2cc7 100644
--- a/src/DotNetOpenAuth/OAuth2/ChannelElements/OAuth2ClientChannel.cs
+++ b/src/DotNetOpenAuth/OAuth2/ChannelElements/OAuth2ClientChannel.cs
@@ -12,11 +12,11 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
using System.Net;
using System.Web;
- using DotNetOpenAuth.Messaging;
-
- /// <summary>
- /// The messaging channel used by OAuth 2.0 Clients.
- /// </summary>
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// The messaging channel used by OAuth 2.0 Clients.
+ /// </summary>
internal class OAuth2ClientChannel : OAuth2ChannelBase {
/// <summary>
/// Initializes a new instance of the <see cref="OAuth2ClientChannel"/> class.
@@ -46,16 +46,16 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
}
return httpRequest;
- }
-
- /// <summary>
- /// Gets the protocol message that may be in the given HTTP response.
- /// </summary>
- /// <param name="response">The response that is anticipated to contain an protocol message.</param>
- /// <returns>
- /// The deserialized message parts, if found. Null otherwise.
- /// </returns>
- /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception>
+ }
+
+ /// <summary>
+ /// Gets the protocol message that may be in the given HTTP response.
+ /// </summary>
+ /// <param name="response">The response that is anticipated to contain an protocol message.</param>
+ /// <returns>
+ /// The deserialized message parts, if found. Null otherwise.
+ /// </returns>
+ /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception>
protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) {
// The spec says direct responses should be JSON objects, but Facebook uses HttpFormUrlEncoded instead, calling it text/plain
string body = response.GetResponseReader().ReadToEnd();
@@ -66,15 +66,15 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
} else {
throw ErrorUtilities.ThrowProtocol("Unexpected response Content-Type {0}", response.ContentType.MediaType);
}
- }
-
- /// <summary>
- /// Gets the protocol message that may be embedded in the given HTTP request.
- /// </summary>
- /// <param name="request">The request to search for an embedded message.</param>
- /// <returns>
- /// The deserialized message, if one is found. Null otherwise.
- /// </returns>
+ }
+
+ /// <summary>
+ /// Gets the protocol message that may be embedded in the given HTTP request.
+ /// </summary>
+ /// <param name="request">The request to search for an embedded message.</param>
+ /// <returns>
+ /// The deserialized message, if one is found. Null otherwise.
+ /// </returns>
protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestInfo request) {
Logger.Channel.DebugFormat("Incoming HTTP request: {0} {1}", request.HttpMethod, request.UrlBeforeRewriting.AbsoluteUri);
@@ -100,19 +100,19 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
}
return (IDirectedProtocolMessage)this.Receive(fields, recipient);
- }
-
- /// <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 OAuth V1.0 section 5.3.
- /// </remarks>
+ }
+
+ /// <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 OAuth V1.0 section 5.3.
+ /// </remarks>
protected override OutgoingWebResponse PrepareDirectResponse(IProtocolMessage response) {
// Clients don't ever send direct responses.
throw new NotImplementedException();
diff --git a/src/DotNetOpenAuth/OAuth2/ChannelElements/UriStyleMessageFormatter.cs b/src/DotNetOpenAuth/OAuth2/ChannelElements/UriStyleMessageFormatter.cs
index a778564..37e09b4 100644
--- a/src/DotNetOpenAuth/OAuth2/ChannelElements/UriStyleMessageFormatter.cs
+++ b/src/DotNetOpenAuth/OAuth2/ChannelElements/UriStyleMessageFormatter.cs
@@ -1,316 +1,316 @@
-//-----------------------------------------------------------------------
-// <copyright file="UriStyleMessageFormatter.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OAuth2.ChannelElements {
- using System;
- using System.Collections.Generic;
- using System.Diagnostics.Contracts;
- using System.Linq;
- using System.Security.Cryptography;
- using System.Text;
- using System.Web;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.Messaging.Bindings;
- using DotNetOpenAuth.Messaging.Reflection;
-
- /// <summary>
- /// A serializer for <see cref="DataBag"/>-derived types
- /// </summary>
- /// <typeparam name="T">The DataBag-derived type that is to be serialized/deserialized.</typeparam>
- internal class UriStyleMessageFormatter<T> : IDataBagFormatter<T> where T : DataBag, new() {
- /// <summary>
- /// The length of the nonce to include in tokens that can be decoded once only.
- /// </summary>
- private const int NonceLength = 6;
-
- /// <summary>
- /// The message description cache to use for data bag types.
- /// </summary>
- private static readonly MessageDescriptionCollection MessageDescriptions = new MessageDescriptionCollection();
-
- /// <summary>
- /// The symmetric secret used for signing/encryption of verification codes and refresh tokens.
- /// </summary>
- private readonly byte[] symmetricSecret;
-
- /// <summary>
- /// The hashing algorithm to use while signing when using a symmetric secret.
- /// </summary>
- private readonly HashAlgorithm symmetricHasher;
-
- /// <summary>
- /// The crypto to use for signing access tokens.
- /// </summary>
- private readonly RSACryptoServiceProvider asymmetricSigning;
-
- /// <summary>
- /// The crypto to use for encrypting access tokens.
- /// </summary>
- private readonly RSACryptoServiceProvider asymmetricEncrypting;
-
- /// <summary>
- /// The hashing algorithm to use for asymmetric signatures.
- /// </summary>
- private readonly HashAlgorithm hasherForAsymmetricSigning;
-
- /// <summary>
- /// A value indicating whether the data in this instance will be protected against tampering.
- /// </summary>
- private readonly bool signed;
-
- /// <summary>
- /// The nonce store to use to ensure that this instance is only decoded once.
- /// </summary>
- private readonly INonceStore decodeOnceOnly;
-
- /// <summary>
- /// The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.
- /// </summary>
- private readonly TimeSpan? maximumAge;
-
- /// <summary>
- /// A value indicating whether the data in this instance will be protected against eavesdropping.
- /// </summary>
- private readonly bool encrypted;
-
- /// <summary>
- /// A value indicating whether the data in this instance will be GZip'd.
- /// </summary>
- private readonly bool compressed;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="UriStyleMessageFormatter&lt;T&gt;"/> class.
- /// </summary>
- /// <param name="signed">A value indicating whether the data in this instance will be protected against tampering.</param>
- /// <param name="encrypted">A value indicating whether the data in this instance will be protected against eavesdropping.</param>
- /// <param name="compressed">A value indicating whether the data in this instance will be GZip'd.</param>
- /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.</param>
- /// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param>
- internal UriStyleMessageFormatter(bool signed = false, bool encrypted = false, bool compressed = false, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null) {
- Contract.Requires<ArgumentException>(signed || decodeOnceOnly == null, "A signature must be applied if this data is meant to be decoded only once.");
- Contract.Requires<ArgumentException>(maximumAge.HasValue || decodeOnceOnly == null, "A maximum age must be given if a message can only be decoded once.");
-
- this.signed = signed;
- this.maximumAge = maximumAge;
- this.decodeOnceOnly = decodeOnceOnly;
- this.encrypted = encrypted;
- this.compressed = compressed;
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="UriStyleMessageFormatter&lt;T&gt;"/> class.
- /// </summary>
- /// <param name="signingKey">The asymmetric private key to use for signing the token.</param>
- /// <param name="encryptingKey">The asymmetric public key to use for encrypting the token.</param>
- /// <param name="compressed">A value indicating whether the data in this instance will be GZip'd.</param>
- /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.</param>
- /// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param>
- internal UriStyleMessageFormatter(RSAParameters? signingKey = null, RSAParameters? encryptingKey = null, bool compressed = false, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null)
- : this(signingKey.HasValue, encryptingKey.HasValue, compressed, maximumAge, decodeOnceOnly) {
- if (signingKey.HasValue) {
- this.asymmetricSigning = new RSACryptoServiceProvider();
- this.asymmetricSigning.ImportParameters(signingKey.Value);
- }
-
- if (encryptingKey.HasValue) {
- this.asymmetricEncrypting = new RSACryptoServiceProvider();
- this.asymmetricEncrypting.ImportParameters(encryptingKey.Value);
- }
-
- this.hasherForAsymmetricSigning = new SHA1CryptoServiceProvider();
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="UriStyleMessageFormatter&lt;T&gt;"/> class.
- /// </summary>
- /// <param name="symmetricSecret">The symmetric secret to use for signing and encrypting.</param>
- /// <param name="signed">A value indicating whether the data in this instance will be protected against tampering.</param>
- /// <param name="encrypted">A value indicating whether the data in this instance will be protected against eavesdropping.</param>
- /// <param name="compressed">A value indicating whether the data in this instance will be GZip'd.</param>
- /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.</param>
- /// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param>
- internal UriStyleMessageFormatter(byte[] symmetricSecret = null, bool signed = false, bool encrypted = false, bool compressed = false, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null)
- : this(signed, encrypted, compressed, maximumAge, decodeOnceOnly) {
- Contract.Requires<ArgumentException>(symmetricSecret != null || (!signed && !encrypted), "A secret is required when signing or encrypting is required.");
-
- if (symmetricSecret != null) {
- this.symmetricHasher = new HMACSHA256(symmetricSecret);
- }
-
- this.symmetricSecret = symmetricSecret;
- }
-
- /// <summary>
- /// Serializes the specified message.
- /// </summary>
- /// <param name="message">The message to serialize. Must not be null.</param>
- /// <returns>A non-null, non-empty value.</returns>
- public string Serialize(T message) {
- message.UtcCreationDate = DateTime.UtcNow;
-
- if (this.decodeOnceOnly != null) {
- message.Nonce = MessagingUtilities.GetNonCryptoRandomData(NonceLength);
- }
-
- if (this.signed) {
- message.Signature = this.CalculateSignature(message);
- }
-
- var fields = MessageSerializer.Get(message.GetType()).Serialize(MessageDescriptions.GetAccessor(message));
- string value = MessagingUtilities.CreateQueryString(fields);
-
- byte[] encoded = Encoding.UTF8.GetBytes(value);
-
- if (this.compressed) {
- encoded = MessagingUtilities.Compress(encoded);
- }
-
- if (this.encrypted) {
- encoded = this.Encrypt(encoded);
- }
-
- return Convert.ToBase64String(encoded);
- }
-
- /// <summary>
- /// Deserializes a <see cref="DataBag"/>.
- /// </summary>
- /// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be nulll.</param>
- /// <param name="value">The serialized form of the <see cref="DataBag"/> to deserialize. Must not be null or empty.</param>
- /// <returns>The deserialized value. Never null.</returns>
- public T Deserialize(IProtocolMessage containingMessage, string value) {
- var message = new T { ContainingMessage = containingMessage };
- byte[] data = Convert.FromBase64String(value);
-
- if (this.encrypted) {
- data = this.Decrypt(data);
- }
-
- if (this.compressed) {
- data = MessagingUtilities.Decompress(data);
- }
-
- value = Encoding.UTF8.GetString(data);
-
- // Deserialize into message newly created instance.
- var serializer = MessageSerializer.Get(message.GetType());
- var fields = MessageDescriptions.GetAccessor(message);
- serializer.Deserialize(HttpUtility.ParseQueryString(value).ToDictionary(), fields);
-
- if (this.signed) {
- // Verify that the verification code was issued by message authorization server.
- ErrorUtilities.VerifyProtocol(this.IsSignatureValid(message), Protocol.bad_verification_code);
- }
-
- if (this.maximumAge.HasValue) {
- // Has message verification code expired?
- DateTime expirationDate = message.UtcCreationDate + this.maximumAge.Value;
- if (expirationDate < DateTime.UtcNow) {
- throw new ExpiredMessageException(expirationDate, containingMessage);
- }
- }
-
- // Has message verification code already been used to obtain an access/refresh token?
- if (this.decodeOnceOnly != null) {
- ErrorUtilities.VerifyInternal(this.maximumAge.HasValue, "Oops! How can we validate a nonce without a maximum message age?");
- string context = "{" + GetType().FullName + "}";
- if (!this.decodeOnceOnly.StoreNonce(context, Convert.ToBase64String(message.Nonce), message.UtcCreationDate)) {
- Logger.OpenId.ErrorFormat("Replayed nonce detected ({0} {1}). Rejecting message.", message.Nonce, message.UtcCreationDate);
- throw new ReplayedMessageException(containingMessage);
- }
- }
-
- ((IMessage)message).EnsureValidMessage();
-
- return message;
- }
-
- /// <summary>
- /// Determines whether the signature on this instance is valid.
- /// </summary>
- /// <param name="message">The message whose signature is to be checked.</param>
- /// <returns>
- /// <c>true</c> if the signature is valid; otherwise, <c>false</c>.
- /// </returns>
- private bool IsSignatureValid(DataBag message) {
- Contract.Requires<ArgumentNullException>(message != null, "message");
-
- if (this.asymmetricSigning != null) {
- byte[] bytesToSign = this.GetBytesToSign(message);
- return this.asymmetricSigning.VerifyData(bytesToSign, this.hasherForAsymmetricSigning, message.Signature);
- } else {
- return MessagingUtilities.AreEquivalentConstantTime(message.Signature, this.CalculateSignature(message));
- }
- }
-
- /// <summary>
- /// Calculates the signature for the data in this verification code.
- /// </summary>
- /// <param name="message">The message whose signature is to be calculated.</param>
- /// <returns>The calculated signature.</returns>
- private byte[] CalculateSignature(DataBag message) {
- Contract.Requires<ArgumentNullException>(message != null, "message");
- Contract.Requires<InvalidOperationException>(this.asymmetricSigning != null || this.symmetricHasher != null);
- Contract.Ensures(Contract.Result<byte[]>() != null);
-
- byte[] bytesToSign = this.GetBytesToSign(message);
- if (this.asymmetricSigning != null) {
- return this.asymmetricSigning.SignData(bytesToSign, this.hasherForAsymmetricSigning);
- } else {
- return this.symmetricHasher.ComputeHash(bytesToSign);
- }
- }
-
- /// <summary>
- /// Gets the bytes to sign.
- /// </summary>
- /// <param name="message">The message to be encoded as normalized bytes for signing.</param>
- /// <returns>A buffer of the bytes to sign.</returns>
- private byte[] GetBytesToSign(DataBag message) {
- Contract.Requires<ArgumentNullException>(message != null, "message");
-
- // Sign the data, being sure to avoid any impact of the signature field itself.
- var fields = MessageDescriptions.GetAccessor(message);
- var fieldsCopy = fields.ToDictionary();
- fieldsCopy.Remove("sig");
-
- var sortedData = new SortedDictionary<string, string>(fieldsCopy, StringComparer.OrdinalIgnoreCase);
- string value = MessagingUtilities.CreateQueryString(sortedData);
- byte[] bytesToSign = Encoding.UTF8.GetBytes(value);
- return bytesToSign;
- }
-
- /// <summary>
- /// Encrypts the specified value using either the symmetric or asymmetric encryption algorithm as appropriate.
- /// </summary>
- /// <param name="value">The value.</param>
- /// <returns>The encrypted value.</returns>
- private byte[] Encrypt(byte[] value) {
- Contract.Requires<InvalidOperationException>(this.asymmetricEncrypting != null || this.symmetricSecret != null);
-
- if (this.asymmetricEncrypting != null) {
- return this.asymmetricEncrypting.EncryptWithRandomSymmetricKey(value);
- } else {
- return MessagingUtilities.Encrypt(value, this.symmetricSecret);
- }
- }
-
- /// <summary>
- /// Decrypts the specified value using either the symmetric or asymmetric encryption algorithm as appropriate.
- /// </summary>
- /// <param name="value">The value.</param>
- /// <returns>The decrypted value.</returns>
- private byte[] Decrypt(byte[] value) {
- Contract.Requires<InvalidOperationException>(this.asymmetricEncrypting != null || this.symmetricSecret != null);
-
- if (this.asymmetricEncrypting != null) {
- return this.asymmetricEncrypting.DecryptWithRandomSymmetricKey(value);
- } else {
- return MessagingUtilities.Decrypt(value, this.symmetricSecret);
- }
- }
- }
-}
+//-----------------------------------------------------------------------
+// <copyright file="UriStyleMessageFormatter.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth2.ChannelElements {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Linq;
+ using System.Security.Cryptography;
+ using System.Text;
+ using System.Web;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.Messaging.Bindings;
+ using DotNetOpenAuth.Messaging.Reflection;
+
+ /// <summary>
+ /// A serializer for <see cref="DataBag"/>-derived types
+ /// </summary>
+ /// <typeparam name="T">The DataBag-derived type that is to be serialized/deserialized.</typeparam>
+ internal class UriStyleMessageFormatter<T> : IDataBagFormatter<T> where T : DataBag, new() {
+ /// <summary>
+ /// The length of the nonce to include in tokens that can be decoded once only.
+ /// </summary>
+ private const int NonceLength = 6;
+
+ /// <summary>
+ /// The message description cache to use for data bag types.
+ /// </summary>
+ private static readonly MessageDescriptionCollection MessageDescriptions = new MessageDescriptionCollection();
+
+ /// <summary>
+ /// The symmetric secret used for signing/encryption of verification codes and refresh tokens.
+ /// </summary>
+ private readonly byte[] symmetricSecret;
+
+ /// <summary>
+ /// The hashing algorithm to use while signing when using a symmetric secret.
+ /// </summary>
+ private readonly HashAlgorithm symmetricHasher;
+
+ /// <summary>
+ /// The crypto to use for signing access tokens.
+ /// </summary>
+ private readonly RSACryptoServiceProvider asymmetricSigning;
+
+ /// <summary>
+ /// The crypto to use for encrypting access tokens.
+ /// </summary>
+ private readonly RSACryptoServiceProvider asymmetricEncrypting;
+
+ /// <summary>
+ /// The hashing algorithm to use for asymmetric signatures.
+ /// </summary>
+ private readonly HashAlgorithm hasherForAsymmetricSigning;
+
+ /// <summary>
+ /// A value indicating whether the data in this instance will be protected against tampering.
+ /// </summary>
+ private readonly bool signed;
+
+ /// <summary>
+ /// The nonce store to use to ensure that this instance is only decoded once.
+ /// </summary>
+ private readonly INonceStore decodeOnceOnly;
+
+ /// <summary>
+ /// The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.
+ /// </summary>
+ private readonly TimeSpan? maximumAge;
+
+ /// <summary>
+ /// A value indicating whether the data in this instance will be protected against eavesdropping.
+ /// </summary>
+ private readonly bool encrypted;
+
+ /// <summary>
+ /// A value indicating whether the data in this instance will be GZip'd.
+ /// </summary>
+ private readonly bool compressed;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UriStyleMessageFormatter&lt;T&gt;"/> class.
+ /// </summary>
+ /// <param name="signed">A value indicating whether the data in this instance will be protected against tampering.</param>
+ /// <param name="encrypted">A value indicating whether the data in this instance will be protected against eavesdropping.</param>
+ /// <param name="compressed">A value indicating whether the data in this instance will be GZip'd.</param>
+ /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.</param>
+ /// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param>
+ internal UriStyleMessageFormatter(bool signed = false, bool encrypted = false, bool compressed = false, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null) {
+ Contract.Requires<ArgumentException>(signed || decodeOnceOnly == null, "A signature must be applied if this data is meant to be decoded only once.");
+ Contract.Requires<ArgumentException>(maximumAge.HasValue || decodeOnceOnly == null, "A maximum age must be given if a message can only be decoded once.");
+
+ this.signed = signed;
+ this.maximumAge = maximumAge;
+ this.decodeOnceOnly = decodeOnceOnly;
+ this.encrypted = encrypted;
+ this.compressed = compressed;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UriStyleMessageFormatter&lt;T&gt;"/> class.
+ /// </summary>
+ /// <param name="signingKey">The asymmetric private key to use for signing the token.</param>
+ /// <param name="encryptingKey">The asymmetric public key to use for encrypting the token.</param>
+ /// <param name="compressed">A value indicating whether the data in this instance will be GZip'd.</param>
+ /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.</param>
+ /// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param>
+ internal UriStyleMessageFormatter(RSAParameters? signingKey = null, RSAParameters? encryptingKey = null, bool compressed = false, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null)
+ : this(signingKey.HasValue, encryptingKey.HasValue, compressed, maximumAge, decodeOnceOnly) {
+ if (signingKey.HasValue) {
+ this.asymmetricSigning = new RSACryptoServiceProvider();
+ this.asymmetricSigning.ImportParameters(signingKey.Value);
+ }
+
+ if (encryptingKey.HasValue) {
+ this.asymmetricEncrypting = new RSACryptoServiceProvider();
+ this.asymmetricEncrypting.ImportParameters(encryptingKey.Value);
+ }
+
+ this.hasherForAsymmetricSigning = new SHA1CryptoServiceProvider();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UriStyleMessageFormatter&lt;T&gt;"/> class.
+ /// </summary>
+ /// <param name="symmetricSecret">The symmetric secret to use for signing and encrypting.</param>
+ /// <param name="signed">A value indicating whether the data in this instance will be protected against tampering.</param>
+ /// <param name="encrypted">A value indicating whether the data in this instance will be protected against eavesdropping.</param>
+ /// <param name="compressed">A value indicating whether the data in this instance will be GZip'd.</param>
+ /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.</param>
+ /// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param>
+ internal UriStyleMessageFormatter(byte[] symmetricSecret = null, bool signed = false, bool encrypted = false, bool compressed = false, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null)
+ : this(signed, encrypted, compressed, maximumAge, decodeOnceOnly) {
+ Contract.Requires<ArgumentException>(symmetricSecret != null || (!signed && !encrypted), "A secret is required when signing or encrypting is required.");
+
+ if (symmetricSecret != null) {
+ this.symmetricHasher = new HMACSHA256(symmetricSecret);
+ }
+
+ this.symmetricSecret = symmetricSecret;
+ }
+
+ /// <summary>
+ /// Serializes the specified message.
+ /// </summary>
+ /// <param name="message">The message to serialize. Must not be null.</param>
+ /// <returns>A non-null, non-empty value.</returns>
+ public string Serialize(T message) {
+ message.UtcCreationDate = DateTime.UtcNow;
+
+ if (this.decodeOnceOnly != null) {
+ message.Nonce = MessagingUtilities.GetNonCryptoRandomData(NonceLength);
+ }
+
+ if (this.signed) {
+ message.Signature = this.CalculateSignature(message);
+ }
+
+ var fields = MessageSerializer.Get(message.GetType()).Serialize(MessageDescriptions.GetAccessor(message));
+ string value = MessagingUtilities.CreateQueryString(fields);
+
+ byte[] encoded = Encoding.UTF8.GetBytes(value);
+
+ if (this.compressed) {
+ encoded = MessagingUtilities.Compress(encoded);
+ }
+
+ if (this.encrypted) {
+ encoded = this.Encrypt(encoded);
+ }
+
+ return Convert.ToBase64String(encoded);
+ }
+
+ /// <summary>
+ /// Deserializes a <see cref="DataBag"/>.
+ /// </summary>
+ /// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be nulll.</param>
+ /// <param name="value">The serialized form of the <see cref="DataBag"/> to deserialize. Must not be null or empty.</param>
+ /// <returns>The deserialized value. Never null.</returns>
+ public T Deserialize(IProtocolMessage containingMessage, string value) {
+ var message = new T { ContainingMessage = containingMessage };
+ byte[] data = Convert.FromBase64String(value);
+
+ if (this.encrypted) {
+ data = this.Decrypt(data);
+ }
+
+ if (this.compressed) {
+ data = MessagingUtilities.Decompress(data);
+ }
+
+ value = Encoding.UTF8.GetString(data);
+
+ // Deserialize into message newly created instance.
+ var serializer = MessageSerializer.Get(message.GetType());
+ var fields = MessageDescriptions.GetAccessor(message);
+ serializer.Deserialize(HttpUtility.ParseQueryString(value).ToDictionary(), fields);
+
+ if (this.signed) {
+ // Verify that the verification code was issued by message authorization server.
+ ErrorUtilities.VerifyProtocol(this.IsSignatureValid(message), Protocol.bad_verification_code);
+ }
+
+ if (this.maximumAge.HasValue) {
+ // Has message verification code expired?
+ DateTime expirationDate = message.UtcCreationDate + this.maximumAge.Value;
+ if (expirationDate < DateTime.UtcNow) {
+ throw new ExpiredMessageException(expirationDate, containingMessage);
+ }
+ }
+
+ // Has message verification code already been used to obtain an access/refresh token?
+ if (this.decodeOnceOnly != null) {
+ ErrorUtilities.VerifyInternal(this.maximumAge.HasValue, "Oops! How can we validate a nonce without a maximum message age?");
+ string context = "{" + GetType().FullName + "}";
+ if (!this.decodeOnceOnly.StoreNonce(context, Convert.ToBase64String(message.Nonce), message.UtcCreationDate)) {
+ Logger.OpenId.ErrorFormat("Replayed nonce detected ({0} {1}). Rejecting message.", message.Nonce, message.UtcCreationDate);
+ throw new ReplayedMessageException(containingMessage);
+ }
+ }
+
+ ((IMessage)message).EnsureValidMessage();
+
+ return message;
+ }
+
+ /// <summary>
+ /// Determines whether the signature on this instance is valid.
+ /// </summary>
+ /// <param name="message">The message whose signature is to be checked.</param>
+ /// <returns>
+ /// <c>true</c> if the signature is valid; otherwise, <c>false</c>.
+ /// </returns>
+ private bool IsSignatureValid(DataBag message) {
+ Contract.Requires<ArgumentNullException>(message != null, "message");
+
+ if (this.asymmetricSigning != null) {
+ byte[] bytesToSign = this.GetBytesToSign(message);
+ return this.asymmetricSigning.VerifyData(bytesToSign, this.hasherForAsymmetricSigning, message.Signature);
+ } else {
+ return MessagingUtilities.AreEquivalentConstantTime(message.Signature, this.CalculateSignature(message));
+ }
+ }
+
+ /// <summary>
+ /// Calculates the signature for the data in this verification code.
+ /// </summary>
+ /// <param name="message">The message whose signature is to be calculated.</param>
+ /// <returns>The calculated signature.</returns>
+ private byte[] CalculateSignature(DataBag message) {
+ Contract.Requires<ArgumentNullException>(message != null, "message");
+ Contract.Requires<InvalidOperationException>(this.asymmetricSigning != null || this.symmetricHasher != null);
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+
+ byte[] bytesToSign = this.GetBytesToSign(message);
+ if (this.asymmetricSigning != null) {
+ return this.asymmetricSigning.SignData(bytesToSign, this.hasherForAsymmetricSigning);
+ } else {
+ return this.symmetricHasher.ComputeHash(bytesToSign);
+ }
+ }
+
+ /// <summary>
+ /// Gets the bytes to sign.
+ /// </summary>
+ /// <param name="message">The message to be encoded as normalized bytes for signing.</param>
+ /// <returns>A buffer of the bytes to sign.</returns>
+ private byte[] GetBytesToSign(DataBag message) {
+ Contract.Requires<ArgumentNullException>(message != null, "message");
+
+ // Sign the data, being sure to avoid any impact of the signature field itself.
+ var fields = MessageDescriptions.GetAccessor(message);
+ var fieldsCopy = fields.ToDictionary();
+ fieldsCopy.Remove("sig");
+
+ var sortedData = new SortedDictionary<string, string>(fieldsCopy, StringComparer.OrdinalIgnoreCase);
+ string value = MessagingUtilities.CreateQueryString(sortedData);
+ byte[] bytesToSign = Encoding.UTF8.GetBytes(value);
+ return bytesToSign;
+ }
+
+ /// <summary>
+ /// Encrypts the specified value using either the symmetric or asymmetric encryption algorithm as appropriate.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns>The encrypted value.</returns>
+ private byte[] Encrypt(byte[] value) {
+ Contract.Requires<InvalidOperationException>(this.asymmetricEncrypting != null || this.symmetricSecret != null);
+
+ if (this.asymmetricEncrypting != null) {
+ return this.asymmetricEncrypting.EncryptWithRandomSymmetricKey(value);
+ } else {
+ return MessagingUtilities.Encrypt(value, this.symmetricSecret);
+ }
+ }
+
+ /// <summary>
+ /// Decrypts the specified value using either the symmetric or asymmetric encryption algorithm as appropriate.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns>The decrypted value.</returns>
+ private byte[] Decrypt(byte[] value) {
+ Contract.Requires<InvalidOperationException>(this.asymmetricEncrypting != null || this.symmetricSecret != null);
+
+ if (this.asymmetricEncrypting != null) {
+ return this.asymmetricEncrypting.DecryptWithRandomSymmetricKey(value);
+ } else {
+ return MessagingUtilities.Decrypt(value, this.symmetricSecret);
+ }
+ }
+ }
+}