/// <summary>
        /// Looks for the first association type in a preferred-order list that is
        /// likely to be supported given a specific OpenID version and the security settings,
        /// and perhaps a matching Diffie-Hellman session type.
        /// </summary>
        /// <param name="protocol">The OpenID version that dictates which associations are available.</param>
        /// <param name="highSecurityIsBetter">A value indicating whether to consider higher strength security to be better.  Use <c>true</c> for initial association requests from the Relying Party; use <c>false</c> from Providers when the Relying Party asks for an unrecognized association in order to pick a suggested alternative that is likely to be supported on both sides.</param>
        /// <param name="securityRequirements">The set of requirements the selected association type must comply to.</param>
        /// <param name="requireMatchingDHSessionType">Use <c>true</c> for HTTP associations, <c>false</c> for HTTPS associations.</param>
        /// <param name="associationType">The resulting association type's well known protocol name.  (i.e. HMAC-SHA256)</param>
        /// <param name="sessionType">The resulting session type's well known protocol name, if a matching one is available.  (i.e. DH-SHA256)</param>
        /// <returns>
        /// True if a qualifying association could be found; false otherwise.
        /// </returns>
        internal static bool TryFindBestAssociation(Protocol protocol, bool highSecurityIsBetter, SecuritySettings securityRequirements, bool requireMatchingDHSessionType, out string associationType, out string sessionType)
        {
            Requires.NotNull(protocol, "protocol");
            Requires.NotNull(securityRequirements, "securityRequirements");

            associationType = null;
            sessionType     = null;

            // We use AsEnumerable() to avoid VerificationException (http://stackoverflow.com/questions/478422/why-does-simple-array-and-linq-generate-verificationexception-operation-could-de)
            IEnumerable <HmacSha> preferredOrder = highSecurityIsBetter ?
                                                   hmacShaAssociationTypes.AsEnumerable() : hmacShaAssociationTypes.Reverse();

            foreach (HmacSha sha in preferredOrder)
            {
                int hashSizeInBits = sha.SecretLength * 8;
                if (hashSizeInBits > securityRequirements.MaximumHashBitLength ||
                    hashSizeInBits < securityRequirements.MinimumHashBitLength)
                {
                    continue;
                }

                if (OpenIdUtilities.IsDiffieHellmanPresent)
                {
                    sessionType = DiffieHellmanUtilities.GetNameForSize(protocol, hashSizeInBits);
                }
                else
                {
                    sessionType = requireMatchingDHSessionType ? null : protocol.Args.SessionType.NoEncryption;
                }

                if (requireMatchingDHSessionType && sessionType == null)
                {
                    continue;
                }
                associationType = sha.GetAssociationType(protocol);
                if (associationType == null)
                {
                    continue;
                }

                return(true);
            }

            return(false);
        }
Esempio n. 2
0
        /// <summary>
        /// Determines whether a named Diffie-Hellman session type and association type can be used together.
        /// </summary>
        /// <param name="protocol">The protocol carrying the names of the session and association types.</param>
        /// <param name="associationType">The value of the openid.assoc_type parameter.</param>
        /// <param name="sessionType">The value of the openid.session_type parameter.</param>
        /// <returns>
        ///     <c>true</c> if the named association and session types are compatible; otherwise, <c>false</c>.
        /// </returns>
        internal static bool IsDHSessionCompatible(Protocol protocol, string associationType, string sessionType)
        {
            ErrorUtilities.VerifyArgumentNotNull(protocol, "protocol");
            ErrorUtilities.VerifyNonZeroLength(associationType, "associationType");
            ErrorUtilities.VerifyArgumentNotNull(sessionType, "sessionType");

            // All association types can work when no DH session is used at all.
            if (string.Equals(sessionType, protocol.Args.SessionType.NoEncryption, StringComparison.Ordinal))
            {
                return(true);
            }

            // When there _is_ a DH session, it must match in hash length with the association type.
            int associationSecretLengthInBytes = GetSecretLength(protocol, associationType);
            int sessionHashLengthInBytes       = DiffieHellmanUtilities.Lookup(protocol, sessionType).HashSize / 8;

            return(associationSecretLengthInBytes == sessionHashLengthInBytes);
        }
Esempio n. 3
0
        /// <summary>
        /// Determines whether a named Diffie-Hellman session type and association type can be used together.
        /// </summary>
        /// <param name="protocol">The protocol carrying the names of the session and association types.</param>
        /// <param name="associationType">The value of the openid.assoc_type parameter.</param>
        /// <param name="sessionType">The value of the openid.session_type parameter.</param>
        /// <returns>
        ///     <c>true</c> if the named association and session types are compatible; otherwise, <c>false</c>.
        /// </returns>
        internal static bool IsDHSessionCompatible(Protocol protocol, string associationType, string sessionType)
        {
            Contract.Requires <ArgumentNullException>(protocol != null);
            Contract.Requires <ArgumentException>(!String.IsNullOrEmpty(associationType));
            Contract.Requires <ArgumentNullException>(sessionType != null);

            // All association types can work when no DH session is used at all.
            if (string.Equals(sessionType, protocol.Args.SessionType.NoEncryption, StringComparison.Ordinal))
            {
                return(true);
            }

            // When there _is_ a DH session, it must match in hash length with the association type.
            int associationSecretLengthInBytes = GetSecretLength(protocol, associationType);
            int sessionHashLengthInBytes       = DiffieHellmanUtilities.Lookup(protocol, sessionType).HashSize / 8;

            return(associationSecretLengthInBytes == sessionHashLengthInBytes);
        }
        /// <summary>
        /// Determines whether a named Diffie-Hellman session type and association type can be used together.
        /// </summary>
        /// <param name="protocol">The protocol carrying the names of the session and association types.</param>
        /// <param name="associationType">The value of the openid.assoc_type parameter.</param>
        /// <param name="sessionType">The value of the openid.session_type parameter.</param>
        /// <returns>
        ///     <c>true</c> if the named association and session types are compatible; otherwise, <c>false</c>.
        /// </returns>
        internal static bool IsDHSessionCompatible(Protocol protocol, string associationType, string sessionType)
        {
            Requires.NotNull(protocol, "protocol");
            Requires.NotNullOrEmpty(associationType, "associationType");
            Requires.NotNull(sessionType, "sessionType");

            // All association types can work when no DH session is used at all.
            if (string.Equals(sessionType, protocol.Args.SessionType.NoEncryption, StringComparison.Ordinal))
            {
                return(true);
            }

            if (OpenIdUtilities.IsDiffieHellmanPresent)
            {
                // When there _is_ a DH session, it must match in hash length with the association type.
                int associationSecretLengthInBytes = GetSecretLength(protocol, associationType);
                int sessionHashLengthInBytes       = DiffieHellmanUtilities.Lookup(protocol, sessionType).HashSize / 8;
                return(associationSecretLengthInBytes == sessionHashLengthInBytes);
            }
            else
            {
                return(false);
            }
        }