/// <summary>
        /// Encodes the specified association data bag.
        /// </summary>
        /// <param name="secret">The symmetric secret.</param>
        /// <param name="expiresUtc">The UTC time that the association should expire.</param>
        /// <param name="privateAssociation">A value indicating whether this is a private association.</param>
        /// <returns>
        /// The association handle that represents this association.
        /// </returns>
        public string Serialize(byte[] secret, DateTime expiresUtc, bool privateAssociation)
        {
            var associationDataBag = new AssociationDataBag {
                Secret = secret,
                IsPrivateAssociation = privateAssociation,
                ExpiresUtc           = expiresUtc,
            };

            var formatter = AssociationDataBag.CreateFormatter(this.cryptoKeyStore, AssociationHandleEncodingSecretBucket, expiresUtc - DateTime.UtcNow);

            return(formatter.Serialize(associationDataBag));
        }
        /// <summary>
        /// Retrieves an association given an association handle.
        /// </summary>
        /// <param name="containingMessage">The OpenID message that referenced this association handle.</param>
        /// <param name="privateAssociation">A value indicating whether a private association is expected.</param>
        /// <param name="handle">The association handle.</param>
        /// <returns>
        /// An association instance, or <c>null</c> if the association has expired or the signature is incorrect (which may be because the OP's symmetric key has changed).
        /// </returns>
        /// <exception cref="ProtocolException">Thrown if the association is not of the expected type.</exception>
        public Association Deserialize(IProtocolMessage containingMessage, bool privateAssociation, string handle)
        {
            var formatter          = AssociationDataBag.CreateFormatter(this.cryptoKeyStore, AssociationHandleEncodingSecretBucket);
            AssociationDataBag bag = new AssociationDataBag();

            try {
                formatter.Deserialize(bag, containingMessage, handle, Protocol.Default.openid.assoc_handle);
            } catch (ProtocolException ex) {
                Logger.OpenId.Error("Rejecting an association because deserialization of the encoded handle failed.", ex);
                return(null);
            }

            ErrorUtilities.VerifyProtocol(bag.IsPrivateAssociation == privateAssociation, "Unexpected association type.");
            Association assoc = Association.Deserialize(handle, bag.ExpiresUtc, bag.Secret);

            return(assoc.IsExpired ? null : assoc);
        }