Example #1
0
        public void Best()
        {
            Association a = HmacShaAssociation.Create(
                Protocol.Default,
                Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1,
                "h1",
                this.sha1Secret,
                TimeSpan.FromHours(1));
            Association b = HmacShaAssociation.Create(
                Protocol.Default,
                Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1,
                "h2",
                this.sha1Secret,
                TimeSpan.FromHours(1));

            this.assocs.Set(a);
            this.assocs.Set(b);

            // make b the best by making a older
            a.Issued -= TimeSpan.FromHours(1);
            Assert.AreSame(b, this.assocs.Best.FirstOrDefault());
            // now make a the best
            b.Issued -= TimeSpan.FromHours(2);
            Assert.AreSame(a, this.assocs.Best.FirstOrDefault());
        }
        /// <summary>
        /// Called to create the Association based on a request previously given by the Relying Party.
        /// </summary>
        /// <param name="request">The prior request for an association.</param>
        /// <param name="securitySettings">The security settings of the Provider.</param>
        /// <returns>The created association.</returns>
        /// <remarks>
        ///     <para>The caller will update this message's
        /// <see cref="AssociateSuccessfulResponse.ExpiresIn"/> and
        /// <see cref="AssociateSuccessfulResponse.AssociationHandle"/>
        /// properties based on the <see cref="Association"/> returned by this method, but any other
        /// association type specific properties must be set by this method.</para>
        ///     <para>The response message is updated to include the details of the created association by this method,
        /// but the resulting association is <i>not</i> added to the association store and must be done by the caller.</para>
        /// </remarks>
        protected override Association CreateAssociationAtProvider(AssociateRequest request, ProviderSecuritySettings securitySettings)
        {
            Association association = HmacShaAssociation.Create(Protocol, this.AssociationType, AssociationRelyingPartyType.Smart, securitySettings);

            this.MacKey = association.SecretKey;
            return(association);
        }
Example #3
0
        /// <summary>
        /// Creates the association at the provider side after the association request has been received.
        /// </summary>
        /// <param name="request">The association request.</param>
        /// <param name="securitySettings">The security settings of the Provider.</param>
        /// <returns>The newly created association.</returns>
        /// <remarks>
        /// The response message is updated to include the details of the created association by this method,
        /// but the resulting association is <i>not</i> added to the association store and must be done by the caller.
        /// </remarks>
        protected override Association CreateAssociationAtProvider(AssociateRequest request, ProviderSecuritySettings securitySettings)
        {
            ErrorUtilities.VerifyArgumentNotNull(request, "request");
            var diffieHellmanRequest = request as AssociateDiffieHellmanRequest;

            ErrorUtilities.VerifyArgument(diffieHellmanRequest != null, "request");
            ErrorUtilities.VerifyArgumentNotNull(securitySettings, "securitySettings");

            this.SessionType = this.SessionType ?? request.SessionType;

            // Go ahead and create the association first, complete with its secret that we're about to share.
            Association association = HmacShaAssociation.Create(this.Protocol, this.AssociationType, AssociationRelyingPartyType.Smart, securitySettings);

            this.AssociationHandle = association.Handle;
            this.ExpiresIn         = association.SecondsTillExpiration;

            // We now need to securely communicate the secret to the relying party using Diffie-Hellman.
            // We do this by performing a DH algorithm on the secret and setting a couple of properties
            // that will be transmitted to the Relying Party.  The RP will perform an inverse operation
            // using its part of a DH secret in order to decrypt the shared secret we just invented
            // above when we created the association.
            DiffieHellman dh = new DiffieHellmanManaged(
                diffieHellmanRequest.DiffieHellmanModulus ?? AssociateDiffieHellmanRequest.DefaultMod,
                diffieHellmanRequest.DiffieHellmanGen ?? AssociateDiffieHellmanRequest.DefaultGen,
                AssociateDiffieHellmanRequest.DefaultX);
            HashAlgorithm hasher = DiffieHellmanUtilities.Lookup(this.Protocol, this.SessionType);

            this.DiffieHellmanServerPublic = DiffieHellmanUtilities.EnsurePositive(dh.CreateKeyExchange());
            this.EncodedMacKey             = DiffieHellmanUtilities.SHAHashXorSecret(hasher, dh, diffieHellmanRequest.DiffieHellmanConsumerPublic, association.SecretKey);

            return(association);
        }
Example #4
0
        private double ParameterizedCheckIdTest(Protocol protocol, string assocType)
        {
            Association assoc = HmacShaAssociation.Create(
                protocol,
                assocType,
                AssociationRelyingPartyType.Smart,
                this.provider.SecuritySettings);

            this.provider.AssociationStore.StoreAssociation(AssociationRelyingPartyType.Smart, assoc);
            var       checkidRequest = this.CreateCheckIdRequest(true);
            Stopwatch timer          = new Stopwatch();

            timer.Start();
            int iterations;

            for (iterations = 0; timer.ElapsedMilliseconds < TestRunTime.TotalMilliseconds; iterations++)
            {
                var request = (IAuthenticationRequest)this.provider.GetRequest(checkidRequest);
                request.IsAuthenticated = true;
                var response = this.provider.PrepareResponse(request);
                Assert.IsInstanceOf <PositiveAssertionResponse>(response.OriginalMessage);
            }
            timer.Stop();
            double executionsPerSecond = GetExecutionsPerSecond(iterations, timer);

            TestUtilities.TestLogger.InfoFormat("Responded to {0} checkid messages in {1}; or {2} authentications per second.", iterations, timer.Elapsed, executionsPerSecond);
            return(executionsPerSecond);
        }
Example #5
0
        /// <summary>
        /// Creates a new association of a given type at an OpenID Provider.
        /// </summary>
        /// <param name="protocol">The protocol.</param>
        /// <param name="associationType">Type of the association (i.e. HMAC-SHA1 or HMAC-SHA256)</param>
        /// <param name="associationUse">A value indicating whether the new association will be used privately by the Provider for "dumb mode" authentication
        /// or shared with the Relying Party for "smart mode" authentication.</param>
        /// <param name="associationStore">The Provider's association store.</param>
        /// <param name="securitySettings">The security settings of the Provider.</param>
        /// <returns>
        /// The newly created association.
        /// </returns>
        /// <remarks>
        /// The new association is NOT automatically put into an association store.  This must be done by the caller.
        /// </remarks>
        internal static HmacShaAssociation Create(Protocol protocol, string associationType, AssociationRelyingPartyType associationUse, IProviderAssociationStore associationStore, ProviderSecuritySettings securitySettings)
        {
            Requires.NotNull(protocol, "protocol");
            Requires.NotNullOrEmpty(associationType, "associationType");
            Requires.NotNull(associationStore, "associationStore");
            Requires.NotNull(securitySettings, "securitySettings");

            int secretLength = HmacShaAssociation.GetSecretLength(protocol, associationType);

            // Generate the secret that will be used for signing
            byte[] secret = MessagingUtilities.GetCryptoRandomData(secretLength);

            TimeSpan lifetime;

            if (associationUse == AssociationRelyingPartyType.Smart)
            {
                if (!securitySettings.AssociationLifetimes.TryGetValue(associationType, out lifetime))
                {
                    lifetime = DefaultMaximumLifetime;
                }
            }
            else
            {
                lifetime = HmacShaAssociation.DumbSecretLifetime;
            }

            string handle = associationStore.Serialize(secret, DateTime.UtcNow + lifetime, associationUse == AssociationRelyingPartyType.Dumb);

            Assumes.True(protocol != null);             // All the way up to the method call, the condition holds, yet we get a Requires failure next
            Assumes.True(secret != null);
            Assumes.True(!string.IsNullOrEmpty(associationType));
            var result = HmacShaAssociation.Create(protocol, associationType, handle, secret, lifetime);

            return(result);
        }
Example #6
0
        public void Sign()
        {
            Association assoc1 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, "h1", this.sha1Secret, TimeSpan.FromMinutes(2));
            Association assoc2 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, "h2", this.sha1Secret2, TimeSpan.FromMinutes(2));

            var data = new byte[] { 0xdd, 0xcc };

            // sign once and verify that it's sane
            byte[] signature1 = assoc1.Sign(data);
            Assert.That(signature1, Is.Not.Null);
            Assert.That(signature1.Length, Is.Not.EqualTo(0));

            // sign again and make sure it's different
            byte[] signature2 = assoc2.Sign(data);
            Assert.That(signature2, Is.Not.Null);
            Assert.That(signature2.Length, Is.Not.EqualTo(0));
            Assert.That(signature1, Is.Not.EqualTo(signature2));

            // sign again with the same secret and make sure it's the same.
            Assert.That(assoc1.Sign(data), Is.EqualTo(signature1));

            // now change the data and make sure signature changes
            data[1] = 0xee;
            Assert.That(assoc1.Sign(data), Is.Not.EqualTo(signature1));
        }
Example #7
0
        public void Sign()
        {
            Association assoc1 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, "h1", this.sha1Secret, TimeSpan.FromMinutes(2));
            Association assoc2 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, "h2", this.sha1Secret2, TimeSpan.FromMinutes(2));

            var data = new byte[] { 0xdd, 0xcc };

            // sign once and verify that it's sane
            byte[] signature1 = assoc1.Sign(data);
            Assert.IsNotNull(signature1);
            Assert.AreNotEqual(0, signature1.Length);

            // sign again and make sure it's different
            byte[] signature2 = assoc2.Sign(data);
            Assert.IsNotNull(signature2);
            Assert.AreNotEqual(0, signature2.Length);
            Assert.IsFalse(MessagingUtilities.AreEquivalent(signature1, signature2));

            // sign again with the same secret and make sure it's the same.
            Assert.IsTrue(MessagingUtilities.AreEquivalent(signature1, assoc1.Sign(data)));

            // now change the data and make sure signature changes
            data[1] = 0xee;
            Assert.IsFalse(MessagingUtilities.AreEquivalent(signature1, assoc1.Sign(data)));
        }
        public void SignSome()
        {
            Association assoc = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1,
                                                          "h1", sha1Secret, TimeSpan.FromMinutes(2));
            const string prefix = "q.";

            var dict = new Dictionary <string, string>();

            dict.Add("q.a", "b");
            dict.Add("q.c", "d");
            dict.Add("q.e", "f");

            var signKeys = new List <string> {
                "a", "c"
            };                                                        // don't sign e

            byte[] sig1 = assoc.Sign(dict, signKeys, prefix);

            // change the unsigned value and verify that the sig doesn't change
            dict["q.e"] = "g";
            Assert.IsTrue(Util.ArrayEquals(sig1, assoc.Sign(dict, signKeys, prefix)));
            // change a signed value and verify that the sig does change.
            dict["q.c"] = "D";
            Assert.IsFalse(Util.ArrayEquals(sig1, assoc.Sign(dict, signKeys, prefix)));

            // change the ordering of signed fields and verify that the signature changes.
            dict["q.c"] = "d";             // put this back first.
            Assert.IsTrue(Util.ArrayEquals(sig1, assoc.Sign(dict, signKeys, prefix)));
            signKeys.Insert(0, signKeys[1]);
            signKeys.RemoveAt(2);
            Assert.IsFalse(Util.ArrayEquals(sig1, assoc.Sign(dict, signKeys, prefix)));
        }
Example #9
0
        public void CreateRequests()
        {
            var rp = this.CreateRelyingParty();

            StoreAssociation(rp, OPUri, HmacShaAssociation.Create("somehandle", new byte[20], TimeSpan.FromDays(1)));
            Identifier id       = Identifier.Parse(GetMockIdentifier(ProtocolVersion.V20));
            var        requests = rp.CreateRequests(id, RPRealmUri, RPUri);

            Assert.AreEqual(1, requests.Count());
        }
Example #10
0
        public async Task CreateRequest()
        {
            var rp = this.CreateRelyingParty();

            StoreAssociation(rp, OPUri, HmacShaAssociation.Create("somehandle", new byte[20], TimeSpan.FromDays(1)));
            Identifier id  = Identifier.Parse(GetMockIdentifier(ProtocolVersion.V20));
            var        req = await rp.CreateRequestAsync(id, RPRealmUri, RPUri);

            Assert.IsNotNull(req);
        }
Example #11
0
        public void HandleLifecycle()
        {
            Association a = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1,
                                                      "somehandle", sha1Secret, TimeSpan.FromDays(1));

            assocs.Set(a);
            Assert.AreSame(a, assocs.Get(a.Handle));
            Assert.IsTrue(assocs.Remove(a.Handle));
            Assert.IsNull(assocs.Get(a.Handle));
            Assert.IsFalse(assocs.Remove(a.Handle));
        }
        /// <summary>
        /// Creates the association at relying party side after the association response has been received.
        /// </summary>
        /// <param name="request">The original association request that was already sent and responded to.</param>
        /// <returns>The newly created association.</returns>
        /// <remarks>
        /// The resulting association is <i>not</i> added to the association store and must be done by the caller.
        /// </remarks>
        public Association CreateAssociationAtRelyingParty(AssociateRequest request)
        {
            var diffieHellmanRequest = request as AssociateDiffieHellmanRequest;

            ErrorUtilities.VerifyArgument(diffieHellmanRequest != null, OpenIdStrings.DiffieHellmanAssociationRequired);

            HashAlgorithm hasher = DiffieHellmanUtilities.Lookup(Protocol, this.SessionType);

            byte[] associationSecret = DiffieHellmanUtilities.SHAHashXorSecret(hasher, diffieHellmanRequest.Algorithm, this.DiffieHellmanServerPublic, this.EncodedMacKey);

            Association association = HmacShaAssociation.Create(Protocol, this.AssociationType, this.AssociationHandle, associationSecret, TimeSpan.FromSeconds(this.ExpiresIn));

            return(association);
        }
Example #13
0
        public void Properties()
        {
            string      handle   = "somehandle";
            TimeSpan    lifetime = TimeSpan.FromMinutes(2);
            Association assoc    = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, handle, this.sha1Secret, lifetime);

            Assert.IsFalse(assoc.IsExpired);
            Assert.That(assoc.Issued, Is.EqualTo(DateTime.UtcNow).Within(deltaDateTime));
            Assert.That(assoc.Expires, Is.EqualTo(DateTime.UtcNow + lifetime).Within(deltaDateTime));
            Assert.That(assoc.Handle, Is.EqualTo(handle));
            Assert.That(assoc.SecondsTillExpiration, Is.EqualTo(lifetime.TotalSeconds).Within(deltaDateTime.TotalSeconds));
            Assert.That(assoc.SecretKey, Is.EqualTo(this.sha1Secret));
            Assert.That(assoc.Issued.Millisecond, Is.EqualTo(0), "No milliseconds because this can be cut off in conversions.");
        }
Example #14
0
        public void Properties()
        {
            string      handle   = "somehandle";
            TimeSpan    lifetime = TimeSpan.FromMinutes(2);
            Association assoc    = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, handle, this.sha1Secret, lifetime);

            Assert.IsFalse(assoc.IsExpired);
            Assert.IsTrue(Math.Abs((DateTime.Now - assoc.Issued.ToLocalTime()).TotalSeconds) < deltaDateTime.TotalSeconds);
            Assert.IsTrue(Math.Abs((DateTime.Now.ToLocalTime() + lifetime - assoc.Expires.ToLocalTime()).TotalSeconds) < deltaDateTime.TotalSeconds);
            Assert.AreEqual(handle, assoc.Handle);
            Assert.IsTrue(Math.Abs(lifetime.TotalSeconds - assoc.SecondsTillExpiration) < deltaDateTime.TotalSeconds);
            Assert.IsTrue(MessagingUtilities.AreEquivalent(this.sha1Secret, assoc.SecretKey));
            Assert.AreEqual(0, assoc.Issued.Millisecond, "No milliseconds because this can be cut off in conversions.");
        }
Example #15
0
        public virtual Association CreateAssociation(AssociationRelyingPartyType associationType, OpenIdProvider provider)
        {
            if (provider == null && associationType == AssociationRelyingPartyType.Smart)
            {
                throw new ArgumentNullException("provider", "For Smart associations, the provider must be given.");
            }

            string   assoc_type;
            Protocol associationProtocol;

            if (associationType == AssociationRelyingPartyType.Dumb)
            {
                // We'll just use the best association available.
                associationProtocol = Protocol.Default;
                assoc_type          = associationProtocol.Args.SignatureAlgorithm.Best;
            }
            else
            {
                associationProtocol = provider.Protocol;
                assoc_type          = Util.GetRequiredArg(provider.Query, provider.Protocol.openid.assoc_type);
                Debug.Assert(Array.IndexOf(provider.Protocol.Args.SignatureAlgorithm.All, assoc_type) >= 0, "This should have been checked by our caller.");
            }
            int secretLength = HmacShaAssociation.GetSecretLength(associationProtocol, assoc_type);

            RNGCryptoServiceProvider generator = new RNGCryptoServiceProvider();

            byte[]             secret     = new byte[secretLength];
            byte[]             uniq_bytes = new byte[4];
            string             uniq;
            string             handle;
            HmacShaAssociation assoc;

            generator.GetBytes(secret);
            generator.GetBytes(uniq_bytes);

            uniq = Convert.ToBase64String(uniq_bytes);

            double seconds = DateTime.UtcNow.Subtract(Association.UnixEpoch).TotalSeconds;

            handle = "{{" + assoc_type + "}{" + seconds + "}{" + uniq + "}";

            TimeSpan lifeSpan = associationType == AssociationRelyingPartyType.Dumb ? dumbSecretLifetime : smartAssociationLifetime;

            assoc = HmacShaAssociation.Create(secretLength, handle, secret, lifeSpan);

            store.StoreAssociation(associationType, assoc);

            return(assoc);
        }
        /// <summary>
        /// Gets a private Provider association used for signing messages in "dumb" mode.
        /// </summary>
        /// <returns>An existing or newly created association.</returns>
        private Association GetDumbAssociationForSigning()
        {
            // If no assoc_handle was given or it was invalid, the only thing
            // left to do is sign a message using a 'dumb' mode association.
            Protocol    protocol    = Protocol.Default;
            Association association = this.opAssociations.GetAssociation(AssociationRelyingPartyType.Dumb, this.opSecuritySettings);

            if (association == null)
            {
                association = HmacShaAssociation.Create(protocol, protocol.Args.SignatureAlgorithm.HMAC_SHA256, AssociationRelyingPartyType.Dumb, this.opSecuritySettings);
                this.opAssociations.StoreAssociation(AssociationRelyingPartyType.Dumb, association);
            }

            return(association);
        }
        void initializeAssociation()
        {
            string assoc_type = Util.GetRequiredArg(Args, Protocol.openidnp.assoc_type);

            if (Array.IndexOf(Protocol.Args.SignatureAlgorithm.All, assoc_type) >= 0)
            {
                byte[] secret;

                string session_type;
                if (!Args.TryGetValue(Protocol.openidnp.session_type, out session_type) ||
                    Protocol.Args.SessionType.NoEncryption.Equals(session_type, StringComparison.Ordinal))
                {
                    secret = getDecoded(Protocol.openidnp.mac_key);
                }
                else
                {
                    try {
                        byte[] dh_server_public = getDecoded(Protocol.openidnp.dh_server_public);
                        byte[] enc_mac_key      = getDecoded(Protocol.openidnp.enc_mac_key);
                        secret = DiffieHellmanUtil.SHAHashXorSecret(DiffieHellmanUtil.Lookup(Protocol, session_type), DH, dh_server_public, enc_mac_key);
                    } catch (ArgumentException ex) {
                        throw new OpenIdException(string.Format(CultureInfo.CurrentCulture,
                                                                Strings.InvalidOpenIdQueryParameterValue,
                                                                Protocol.openid.session_type, session_type), ex);
                    }
                }

                string   assocHandle = Util.GetRequiredArg(Args, Protocol.openidnp.assoc_handle);
                TimeSpan expiresIn   = new TimeSpan(0, 0, Convert.ToInt32(Util.GetRequiredArg(Args, Protocol.openidnp.expires_in), CultureInfo.InvariantCulture));

                try {
                    Association = HmacShaAssociation.Create(Protocol, assoc_type,
                                                            assocHandle, secret, expiresIn);
                } catch (ArgumentException ex) {
                    throw new OpenIdException(string.Format(CultureInfo.CurrentCulture,
                                                            Strings.InvalidOpenIdQueryParameterValue,
                                                            Protocol.openid.assoc_type, assoc_type), ex);
                }
            }
            else
            {
                throw new OpenIdException(string.Format(CultureInfo.CurrentCulture,
                                                        Strings.InvalidOpenIdQueryParameterValue,
                                                        Protocol.openid.assoc_type, assoc_type));
            }
        }
Example #18
0
        public async Task CreateRequestsWithEndpointFilter()
        {
            var rp = this.CreateRelyingParty();

            StoreAssociation(rp, OPUri, HmacShaAssociation.Create("somehandle", new byte[20], TimeSpan.FromDays(1)));
            Identifier id = Identifier.Parse(GetMockIdentifier(ProtocolVersion.V20));

            rp.EndpointFilter = opendpoint => true;
            var requests = await rp.CreateRequestsAsync(id, RPRealmUri, RPUri);

            Assert.AreEqual(1, requests.Count());

            rp.EndpointFilter = opendpoint => false;
            requests          = await rp.CreateRequestsAsync(id, RPRealmUri, RPUri);

            Assert.AreEqual(0, requests.Count());
        }
Example #19
0
        /// <summary>
        /// Simulates an extension request and response.
        /// </summary>
        /// <param name="protocol">The protocol to use in the roundtripping.</param>
        /// <param name="requests">The extensions to add to the request message.</param>
        /// <param name="responses">The extensions to add to the response message.</param>
        /// <remarks>
        /// This method relies on the extension objects' Equals methods to verify
        /// accurate transport.  The Equals methods should be verified by separate tests.
        /// </remarks>
        internal static void Roundtrip(
            Protocol protocol,
            IEnumerable <IOpenIdMessageExtension> requests,
            IEnumerable <IOpenIdMessageExtension> responses)
        {
            ProviderSecuritySettings securitySettings = new ProviderSecuritySettings();
            Association association = HmacShaAssociation.Create(protocol, protocol.Args.SignatureAlgorithm.Best, AssociationRelyingPartyType.Smart, securitySettings);
            var         coordinator = new OpenIdCoordinator(
                rp => {
                RegisterExtension(rp.Channel, Mocks.MockOpenIdExtension.Factory);
                var requestBase = new CheckIdRequest(protocol.Version, OpenIdTestBase.OPUri, AuthenticationRequestMode.Immediate);
                OpenIdTestBase.StoreAssociation(rp, OpenIdTestBase.OPUri, association);
                requestBase.AssociationHandle = association.Handle;
                requestBase.ClaimedIdentifier = "http://claimedid";
                requestBase.LocalIdentifier   = "http://localid";
                requestBase.ReturnTo          = OpenIdTestBase.RPUri;

                foreach (IOpenIdMessageExtension extension in requests)
                {
                    requestBase.Extensions.Add(extension);
                }

                rp.Channel.Send(requestBase);
                var response = rp.Channel.ReadFromRequest <PositiveAssertionResponse>();

                var receivedResponses = response.Extensions.Cast <IOpenIdMessageExtension>();
                CollectionAssert <IOpenIdMessageExtension> .AreEquivalentByEquality(responses.ToArray(), receivedResponses.ToArray());
            },
                op => {
                RegisterExtension(op.Channel, Mocks.MockOpenIdExtension.Factory);
                op.AssociationStore.StoreAssociation(AssociationRelyingPartyType.Smart, association);
                var request          = op.Channel.ReadFromRequest <CheckIdRequest>();
                var response         = new PositiveAssertionResponse(request);
                var receivedRequests = request.Extensions.Cast <IOpenIdMessageExtension>();
                CollectionAssert <IOpenIdMessageExtension> .AreEquivalentByEquality(requests.ToArray(), receivedRequests.ToArray());

                foreach (var extensionResponse in responses)
                {
                    response.Extensions.Add(extensionResponse);
                }

                op.Channel.Send(response);
            });

            coordinator.Run();
        }
        public void Sign()
        {
            Association assoc1 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1,
                                                           "h1", sha1Secret, TimeSpan.FromMinutes(2));
            Association assoc2 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1,
                                                           "h2", sha1Secret2, TimeSpan.FromMinutes(2));

            var dict = new Dictionary <string, string>();

            dict.Add("a", "b");
            dict.Add("c", "d");
            var keys = new List <string>();

            keys.Add("a");
            keys.Add("c");

            // sign once and verify that it's sane
            byte[] signature1 = assoc1.Sign(dict, keys);
            Assert.IsNotNull(signature1);
            Assert.AreNotEqual(0, signature1.Length);

            // sign again and make sure it's different
            byte[] signature2 = assoc2.Sign(dict, keys);
            Assert.IsNotNull(signature2);
            Assert.AreNotEqual(0, signature2.Length);
            Assert.IsFalse(Util.ArrayEquals(signature1, signature2));

            // sign again with the same secret and make sure it's the same.
            Assert.IsTrue(Util.ArrayEquals(signature1, assoc1.Sign(dict, keys)));

            // now add data and make sure signature changes
            dict.Add("g", "h");
            keys.Add("g");
            Assert.IsFalse(Util.ArrayEquals(signature1, assoc1.Sign(dict, keys)));

            // now change existing data.
            dict.Remove("g");
            keys.Remove("g");
            dict["c"] = "e";
            Assert.IsFalse(Util.ArrayEquals(signature1, assoc1.Sign(dict, keys)));
            dict.Remove("c");
            keys.Remove("c");
            Assert.IsFalse(Util.ArrayEquals(signature1, assoc1.Sign(dict, keys)));
        }
        /// <summary>
        /// Gets an association to use for signing new data.
        /// </summary>
        /// <returns>
        /// The association, which may have previously existed or
        /// may have been created as a result of this call.
        /// </returns>
        private Association GetAssociation()
        {
            Association privateAssociation = this.store.GetAssociation(SecretUri, this.securitySettings);

            if (privateAssociation == null || !privateAssociation.HasUsefulLifeRemaining)
            {
                int    secretLength = HmacShaAssociation.GetSecretLength(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.Best);
                byte[] secret       = MessagingUtilities.GetCryptoRandomData(secretLength);
                privateAssociation = HmacShaAssociation.Create(this.CreateNewAssociationHandle(), secret, this.securitySettings.PrivateSecretMaximumAge);
                if (!privateAssociation.HasUsefulLifeRemaining)
                {
                    Logger.WarnFormat(
                        "Brand new private association has a shorter lifespan ({0}) than the maximum allowed authentication time for a user ({1}).  This may lead to login failures.",
                        this.securitySettings.PrivateSecretMaximumAge,
                        DotNetOpenAuthSection.Configuration.OpenId.MaxAuthenticationTime);
                }

                this.store.StoreAssociation(SecretUri, privateAssociation);
            }

            return(privateAssociation);
        }
        public void SignaturesMatchKnownGood()
        {
            Protocol protocol = Protocol.V20;
            var      settings = new ProviderSecuritySettings();
            var      store    = new AssociationMemoryStore <AssociationRelyingPartyType>();

            byte[]      associationSecret = Convert.FromBase64String("rsSwv1zPWfjPRQU80hciu8FPDC+GONAMJQ/AvSo1a2M=");
            Association association       = HmacShaAssociation.Create("mock", associationSecret, TimeSpan.FromDays(1));

            store.StoreAssociation(AssociationRelyingPartyType.Smart, association);
            SigningBindingElement signer = new SigningBindingElement(store, settings);

            signer.Channel = new TestChannel(this.MessageDescriptions);

            IndirectSignedResponse        message       = new IndirectSignedResponse(protocol.Version, new Uri("http://rp"));
            ITamperResistantOpenIdMessage signedMessage = message;

            message.ProviderEndpoint        = new Uri("http://provider");
            signedMessage.UtcCreationDate   = DateTime.Parse("1/1/2009");
            signedMessage.AssociationHandle = association.Handle;
            Assert.IsNotNull(signer.ProcessOutgoingMessage(message));
            Assert.AreEqual("o9+uN7qTaUS9v0otbHTuNAtbkpBm14+es9QnNo6IHD4=", signedMessage.Signature);
        }
        /// <summary>
        /// Called to create the Association based on a request previously given by the Relying Party.
        /// </summary>
        /// <param name="request">The prior request for an association.</param>
        /// <returns>The created association.</returns>
        protected override Association CreateAssociationAtRelyingParty(AssociateRequest request)
        {
            Association association = HmacShaAssociation.Create(Protocol, this.AssociationType, this.AssociationHandle, this.MacKey, TimeSpan.FromSeconds(this.ExpiresIn));

            return(association);
        }
Example #24
0
        private void ParameterizedAuthenticationTest(Protocol protocol, bool statelessRP, bool sharedAssociation, bool positive, bool immediate, bool tamper)
        {
            Contract.Requires<ArgumentException>(!statelessRP || !sharedAssociation, "The RP cannot be stateless while sharing an association with the OP.");
            Contract.Requires<ArgumentException>(positive || !tamper, "Cannot tamper with a negative response.");
            ProviderSecuritySettings securitySettings = new ProviderSecuritySettings();
            Association association = sharedAssociation ? HmacShaAssociation.Create(protocol, protocol.Args.SignatureAlgorithm.Best, AssociationRelyingPartyType.Smart, securitySettings) : null;
            var coordinator = new OpenIdCoordinator(
                rp => {
                    var request = new CheckIdRequest(protocol.Version, OPUri, immediate ? AuthenticationRequestMode.Immediate : AuthenticationRequestMode.Setup);

                    if (association != null) {
                        StoreAssociation(rp, OPUri, association);
                        request.AssociationHandle = association.Handle;
                    }

                    request.ClaimedIdentifier = "http://claimedid";
                    request.LocalIdentifier = "http://localid";
                    request.ReturnTo = RPUri;
                    request.Realm = RPUri;
                    rp.Channel.Send(request);
                    if (positive) {
                        if (tamper) {
                            try {
                                rp.Channel.ReadFromRequest<PositiveAssertionResponse>();
                                Assert.Fail("Expected exception {0} not thrown.", typeof(InvalidSignatureException).Name);
                            } catch (InvalidSignatureException) {
                                TestLogger.InfoFormat("Caught expected {0} exception after tampering with signed data.", typeof(InvalidSignatureException).Name);
                            }
                        } else {
                            var response = rp.Channel.ReadFromRequest<PositiveAssertionResponse>();
                            Assert.IsNotNull(response);
                            Assert.AreEqual(request.ClaimedIdentifier, response.ClaimedIdentifier);
                            Assert.AreEqual(request.LocalIdentifier, response.LocalIdentifier);
                            Assert.AreEqual(request.ReturnTo, response.ReturnTo);

                            // Attempt to replay the message and verify that it fails.
                            // Because in various scenarios and protocol versions different components
                            // notice the replay, we can get one of two exceptions thrown.
                            // When the OP notices the replay we get a generic InvalidSignatureException.
                            // When the RP notices the replay we get a specific ReplayMessageException.
                            try {
                                CoordinatingChannel channel = (CoordinatingChannel)rp.Channel;
                                channel.Replay(response);
                                Assert.Fail("Expected ProtocolException was not thrown.");
                            } catch (ProtocolException ex) {
                                Assert.IsTrue(ex is ReplayedMessageException || ex is InvalidSignatureException, "A {0} exception was thrown instead of the expected {1} or {2}.", ex.GetType(), typeof(ReplayedMessageException).Name, typeof(InvalidSignatureException).Name);
                            }
                        }
                    } else {
                        var response = rp.Channel.ReadFromRequest<NegativeAssertionResponse>();
                        Assert.IsNotNull(response);
                        if (immediate) {
                            // Only 1.1 was required to include user_setup_url
                            if (protocol.Version.Major < 2) {
                                Assert.IsNotNull(response.UserSetupUrl);
                            }
                        } else {
                            Assert.IsNull(response.UserSetupUrl);
                        }
                    }
                },
                op => {
                    if (association != null) {
                        op.AssociationStore.StoreAssociation(AssociationRelyingPartyType.Smart, association);
                    }

                    var request = op.Channel.ReadFromRequest<CheckIdRequest>();
                    Assert.IsNotNull(request);
                    IProtocolMessage response;
                    if (positive) {
                        response = new PositiveAssertionResponse(request);
                    } else {
                        response = new NegativeAssertionResponse(request, op.Channel);
                    }
                    op.Channel.Send(response);

                    if (positive && (statelessRP || !sharedAssociation)) {
                        var checkauthRequest = op.Channel.ReadFromRequest<CheckAuthenticationRequest>();
                        var checkauthResponse = new CheckAuthenticationResponse(checkauthRequest.Version, checkauthRequest);
                        checkauthResponse.IsValid = checkauthRequest.IsValid;
                        op.Channel.Send(checkauthResponse);

                        if (!tamper) {
                            // Respond to the replay attack.
                            checkauthRequest = op.Channel.ReadFromRequest<CheckAuthenticationRequest>();
                            checkauthResponse = new CheckAuthenticationResponse(checkauthRequest.Version, checkauthRequest);
                            checkauthResponse.IsValid = checkauthRequest.IsValid;
                            op.Channel.Send(checkauthResponse);
                        }
                    }
                });
            if (tamper) {
                coordinator.IncomingMessageFilter = message => {
                    var assertion = message as PositiveAssertionResponse;
                    if (assertion != null) {
                        // Alter the Local Identifier between the Provider and the Relying Party.
                        // If the signature binding element does its job, this should cause the RP
                        // to throw.
                        assertion.LocalIdentifier = "http://victim";
                    }
                };
            }
            if (statelessRP) {
                coordinator.RelyingParty = new OpenIdRelyingParty(null);
            }

            coordinator.Run();
        }