public override void GenerateClient (TlsContext ctx)
		{
			using (var dh = new DiffieHellmanManaged (P, G, 0)) {
				using (var X = new SecureBuffer (dh.DecryptKeyExchange (Y))) {
					Y = dh.CreateKeyExchange ();
					ComputeMasterSecret (ctx, X);
				}
			}
		}
		public void KeyExchange ()
		{
			// create a new DH instance
			DiffieHellman dh1 = new DiffieHellmanManaged ();
			// export the public parameters of the first DH instance
			DHParameters dhp = dh1.ExportParameters (false);
			// create a second DH instance and initialize it with the public parameters of the first instance
			DiffieHellman dh2 = new DiffieHellmanManaged (dhp.P, dhp.G, 160);
			// generate the public key of the first DH instance
			byte[] ke1 = dh1.CreateKeyExchange ();
			// generate the public key of the second DH instance
			byte[] ke2 = dh2.CreateKeyExchange ();
			// let the first DH instance compute the shared secret using the second DH public key
			byte[] dh1k = dh1.DecryptKeyExchange (ke2);
			// let the second DH instance compute the shared secret using the first DH public key
			byte[] dh2k = dh2.DecryptKeyExchange (ke1);
			// both shared secrets are the same
			AssertEquals ("Shared Secret", dh1k, dh2k);
		}
        private bool ShareKey()
        {
            // Look for pre-existing valid association
            HttpContext.Current.Trace.Write("Looking up OpenID Server in Associations table");
            DataRow assoc = FindAssocByServer(OpenIDServer);
            if (assoc != null)
            {
                if ((DateTime)assoc["expiration"] > DateTime.Now)
                {
                    HttpContext.Current.Trace.Write("Valid association found.");
                    return true;
                }
            }

            // No valid pre-existing association. Create a new association.
            HttpContext.Current.Trace.Write("No valid association found.");
            Dictionary<string, string> sd = new Dictionary<string, string>();
            DiffieHellmanManaged dhm = new DiffieHellmanManaged();
            sd["openid.mode"] = "associate";

            switch (AuthVersion)
            {
                case ProtocolVersion.V2_0:
                    sd["openid.ns"] = "http://specs.openid.net/auth/2.0";
                    break;
                case ProtocolVersion.V1_1:
                    if (Encryption == KeyEncryption.DHSHA256)
                    {
                        Encryption = KeyEncryption.DHSHA1;
                    }
                    break;
            }

            byte[] pubkey = null;
            DHParameters dp;

            switch (Encryption)
            {
                case KeyEncryption.None:
                    sd["openid.assoc_type"] = "HMAC-SHA1";
                    switch (AuthVersion)
                    {
                        case ProtocolVersion.V2_0:
                            sd["openid.session_type"] = "no-encryption";
                            break;
                        case ProtocolVersion.V1_1:
                            sd["openid.session_type"] = "";
                            break;
                    }
                    break;
                case KeyEncryption.DHSHA1:
                    pubkey = dhm.CreateKeyExchange();
                    dp = dhm.ExportParameters(true);

                    sd["openid.assoc_type"] = "HMAC-SHA1";
                    sd["openid.session_type"] = "DH-SHA1";
                    sd["openid.dh_modulus"] = HttpUtility.UrlEncode(Utility.UnsignedToBase64(dp.P));
                    sd["openid.dh_gen"] = HttpUtility.UrlEncode(Utility.UnsignedToBase64(dp.G));
                    sd["openid.dh_consumer_public"] = HttpUtility.UrlEncode(Utility.UnsignedToBase64(pubkey));
                    break;
                case KeyEncryption.DHSHA256:
                    pubkey = dhm.CreateKeyExchange();
                    dp = dhm.ExportParameters(true);

                    sd["openid.assoc_type"] = "HMAC-SHA256";
                    sd["openid.session_type"] = "DH-SHA256";
                    sd["openid.dh_modulus"] = HttpUtility.UrlEncode(Utility.UnsignedToBase64(dp.P));
                    sd["openid.dh_gen"] = HttpUtility.UrlEncode(Utility.UnsignedToBase64(dp.G));
                    sd["openid.dh_consumer_public"] = HttpUtility.UrlEncode(Utility.UnsignedToBase64(pubkey));
                    break;
            }

            HttpContext.Current.Trace.Write("Opening connection to OpenID Server");
            string response = "";
            response = Utility.MakeRequest(OpenIDServer, "GET", sd);

            Dictionary<string, string> association = new Dictionary<string, string>();
            if (response != null)
            {
                HttpContext.Current.Trace.Write("Association response received.");
                association = Utility.SplitResponse(response);
            }
            else
            {
                HttpContext.Current.Trace.Write("No association response received.");
                return false;
            }

            if (association.ContainsKey("error"))
            {
                // FIXME - Add error handling code
                HttpContext.Current.Trace.Write("Association response contains error.");
                return false;
            }

            if (Encryption == KeyEncryption.DHSHA1 || Encryption == KeyEncryption.DHSHA256)
            {
                HttpContext.Current.Trace.Write("Expecting DHSHA1 or DHSHA256.");
                if (association["enc_mac_key"] != null)
                {
                    HttpContext.Current.Trace.Write("Encrypted association key is present.");
                    byte[] serverpublickey = Convert.FromBase64String(association["dh_server_public"]);
                    byte[] mackey = Convert.FromBase64String(association["enc_mac_key"]);

                    byte[] dhShared = dhm.DecryptKeyExchange(serverpublickey);
                    byte[] shaShared = new byte[0];

                    if (Encryption == KeyEncryption.DHSHA1)
                    {
                        HttpContext.Current.Trace.Write("Decoding DHSHA1 Association.");
                        SHA1 sha1 = new SHA1CryptoServiceProvider();
                        shaShared = sha1.ComputeHash(Utility.EnsurePositive(dhShared));
                    }
                    else if (Encryption == KeyEncryption.DHSHA256)
                    {
                        HttpContext.Current.Trace.Write("Decoding DHSHA256 Association.");
                        SHA256 sha256 = new SHA256Managed();
                        shaShared = sha256.ComputeHash(Utility.EnsurePositive(dhShared));
                    }

                    byte[] secret = new byte[mackey.Length];
                    for (int i = 0; i < mackey.Length; i++)
                    {
                        secret[i] = (byte)(mackey[i] ^ shaShared[i]);
                    }
                    association["mac_key"] = Utility.ToBase64String(secret);
                }
                else
                {
                    ErrorStore.Store(Errors.ReceivedPlaintext);
                    HttpContext.Current.Trace.Write("Error: Received plaintext association when expecting encrypted.");
                    return false;
                }
            }
            AddAssoc(association);
            HttpContext.Current.Trace.Write("Successfully added association to table.");
            return true;
        }
Пример #4
0
        /// <summary>
        /// Perform an association request with an OpenID Provider.
        /// </summary>
        /// <param name="server">URL to the OpenID Provider.</param>
        /// <param name="associationManager">The IAssociationPersistence object to use for persistence.</param>
        /// <param name="version">The ProtocolVersion to use.</param>
        /// <param name="encryption">The key encryption type to use.</param>
        /// <returns>Populated Association object, or null.</returns>
        internal static Association CreateAssociation(Uri server, IAssociationPersistence associationManager,
                                                      ProtocolVersion version, KeyEncryption encryption)
        {
            if (server == null) { throw new ArgumentNullException("server"); }
            if (associationManager == null) { throw new ArgumentNullException("associationManager"); }

            NameValueCollection sd = new NameValueCollection();
            DiffieHellmanManaged dhm = new DiffieHellmanManaged();
            sd["openid.mode"] = "associate";

            switch (version)
            {
                case ProtocolVersion.V2Dot0:
                    sd["openid.ns"] = ProtocolUri.OpenId2Dot0.AbsoluteUri;
                    break;
                case ProtocolVersion.V1Dot1:
                    if (encryption == KeyEncryption.DHSHA256)
                    {
                        encryption = KeyEncryption.DHSHA1;
                    }
                    break;
            }

            byte[] pubkey = null;
            DHParameters dp;

            switch (encryption)
            {
                case KeyEncryption.None:
                    sd["openid.assoc_type"] = "HMAC-SHA1";
                    switch (version)
                    {
                        case ProtocolVersion.V2Dot0:
                            sd["openid.session_type"] = "no-encryption";
                            break;
                        case ProtocolVersion.V1Dot1:
                            sd["openid.session_type"] = "";
                            break;
                    }
                    break;
                case KeyEncryption.DHSHA1:
                    pubkey = dhm.CreateKeyExchange();
                    dp = dhm.ExportParameters(true);

                    sd["openid.assoc_type"] = "HMAC-SHA1";
                    sd["openid.session_type"] = "DH-SHA1";
                    sd["openid.dh_modulus"] = Utility.UnsignedToBase64(dp.P);
                    sd["openid.dh_gen"] = Utility.UnsignedToBase64(dp.G);
                    sd["openid.dh_consumer_public"] = Utility.UnsignedToBase64(pubkey);
                    break;
                case KeyEncryption.DHSHA256:
                    pubkey = dhm.CreateKeyExchange();
                    dp = dhm.ExportParameters(true);

                    sd["openid.assoc_type"] = "HMAC-SHA256";
                    sd["openid.session_type"] = "DH-SHA256";
                    sd["openid.dh_modulus"] = Utility.UnsignedToBase64(dp.P);
                    sd["openid.dh_gen"] = Utility.UnsignedToBase64(dp.G);
                    sd["openid.dh_consumer_public"] = Utility.UnsignedToBase64(pubkey);
                    break;
            }

            Tracer.Write("Opening connection to OpenID Provider.");
            string response = "";
            string actualLocation = null;
            response = Utility.MakeRequest(server, "POST", sd, out actualLocation);

            NameValueCollection association = null;
            Association retassoc = null;
            if (response != null)
            {
                Tracer.Write("Association response received.");
                association = Utility.SplitResponse(response);
            }
            else
            {
                Tracer.Write("No association response received.");
                switch (encryption)
                {
                    case KeyEncryption.DHSHA256:
                        Tracer.Write("Falling back to DHSHA1");
                        encryption = KeyEncryption.DHSHA1;
                        retassoc = CreateAssociation(server, associationManager, version, encryption);
                        if (retassoc != null) { return retassoc; }
                        break;
                    case KeyEncryption.DHSHA1:
                        Tracer.Write("Falling back to No-encryption");
                        encryption = KeyEncryption.None;
                        retassoc = CreateAssociation(server, associationManager, version, encryption);
                        if (retassoc != null) { return retassoc; }
                        break;
                }
                return null;
            }

            if (association["error"] != null)
            {
                Tracer.Write("Association response contains error. - " + association["error"]);
                return null;
            }

            if (encryption == KeyEncryption.DHSHA1 || encryption == KeyEncryption.DHSHA256)
            {
                Tracer.Write("Expecting DHSHA1 or DHSHA256.");
                StringBuilder vals = new StringBuilder();
                foreach (string key in association.Keys)
                {
                    vals.AppendLine(key + ": " + association[key]);
                }
                if (association["enc_mac_key"] == null) { Tracer.Write("No encoded MAC key returned! Received " + vals.ToString()); }
                if (association["enc_mac_key"] != null)
                {
                    Tracer.Write("Encrypted association key is present.");
                    byte[] serverpublickey = Convert.FromBase64String(association["dh_server_public"]);
                    byte[] mackey = Convert.FromBase64String(association["enc_mac_key"]);

                    byte[] dhShared = dhm.DecryptKeyExchange(serverpublickey);
                    byte[] shaShared = new byte[0];

                    if (encryption == KeyEncryption.DHSHA1)
                    {
                        Tracer.Write("Decoding DHSHA1 Association.");
                        SHA1 sha1 = new SHA1CryptoServiceProvider();
                        shaShared = sha1.ComputeHash(Utility.EnsurePositive(dhShared));
                    }
                    else if (encryption == KeyEncryption.DHSHA256)
                    {
                        Tracer.Write("Decoding DHSHA256 Association.");
                        SHA256 sha256 = new SHA256Managed();
                        shaShared = sha256.ComputeHash(Utility.EnsurePositive(dhShared));
                    }

                    byte[] secret = new byte[mackey.Length];
                    for (int i = 0; i < mackey.Length; i++)
                    {
                        secret[i] = (byte)(mackey[i] ^ shaShared[i]);
                    }
                    association["mac_key"] = Convert.ToBase64String(secret);
                }
                else
                {
                    Tracer.Write("Error: Received plaintext association when expecting encrypted.");
                    return null;
                }
            }

            Tracer.Write("Building association");
            retassoc = new Association();
            retassoc.AssociationType = association["assoc_type"];
            retassoc.Expiration = DateTime.UtcNow.AddSeconds(Convert.ToDouble(association["expires_in"], CultureInfo.InvariantCulture));
            retassoc.Handle = association["assoc_handle"];
            retassoc.ProtocolVersion = version;
            retassoc.Server = server.AbsoluteUri;
            retassoc.SessionType = association["session_type"];
            retassoc.Secret = Convert.FromBase64String(association["mac_key"]);
            return retassoc;
        }