diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2010-08-12 06:56:07 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2010-08-12 06:56:07 -0700 |
commit | 47b0071a7f4f3437ab92f3cc427cd52cfa4d6ff9 (patch) | |
tree | 6ef36271bf9c92e641679c5e62da1f22e667f57d /src | |
parent | ccc415b8104c66d3d422c1cffd04a4b1b26dfa0c (diff) | |
download | DotNetOpenAuth-47b0071a7f4f3437ab92f3cc427cd52cfa4d6ff9.zip DotNetOpenAuth-47b0071a7f4f3437ab92f3cc427cd52cfa4d6ff9.tar.gz DotNetOpenAuth-47b0071a7f4f3437ab92f3cc427cd52cfa4d6ff9.tar.bz2 |
Remaining whitespace lineending fix.
Diffstat (limited to 'src')
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<T>"/> 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<T>"/> 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<T>"/> 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<T>"/> 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<T>"/> 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<T>"/> 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<T>"/> 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<T>"/> 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); + } + } + } +} |