예제 #1
0
        public string ComputeHash(string password, bool client)
        {
            string text, a1, a2;

            byte[] buf, digest;

            // compute A1
            text = string.Format("{0}:{1}:{2}", UserName, Realm, password);
            buf  = Encoding.UTF8.GetBytes(text);
            using (var md5 = new MD5())
                digest = md5.ComputeHash(buf);

            using (var md5 = new MD5()) {
                md5.TransformBlock(digest, 0, digest.Length, null, 0);
                text = string.Format(":{0}:{1}", Nonce, CNonce);
                if (!string.IsNullOrEmpty(AuthZid))
                {
                    text += ":" + AuthZid;
                }
                buf = Encoding.ASCII.GetBytes(text);
                md5.TransformFinalBlock(buf, 0, buf.Length);
                a1 = HexEncode(md5.Hash);
            }

            // compute A2
            text  = client ? "AUTHENTICATE:" : ":";
            text += DigestUri;

            if (Qop == "auth-int" || Qop == "auth-conf")
            {
                text += ":00000000000000000000000000000000";
            }

            buf = Encoding.ASCII.GetBytes(text);
            using (var md5 = new MD5())
                digest = md5.ComputeHash(buf);
            a2 = HexEncode(digest);

            // compute KD
            text = string.Format("{0}:{1}:{2:x8}:{3}:{4}:{5}", a1, Nonce, Nc, CNonce, Qop, a2);
            buf  = Encoding.ASCII.GetBytes(text);
            using (var md5 = new MD5())
                digest = md5.ComputeHash(buf);

            return(HexEncode(digest));
        }
		public string ComputeHash (string password, bool client)
		{
			string text, a1, a2;
			byte[] buf, digest;

			// compute A1
			text = string.Format ("{0}:{1}:{2}", UserName, Realm, password);
			buf = Encoding.UTF8.GetBytes (text);
			using (var md5 = new MD5 ())
				digest = md5.ComputeHash (buf);

			using (var md5 = new MD5 ()) {
				md5.TransformBlock (digest, 0, digest.Length, null, 0);
				text = string.Format (":{0}:{1}", Nonce, CNonce);
				if (!string.IsNullOrEmpty (AuthZid))
					text += ":" + AuthZid;
				buf = Encoding.ASCII.GetBytes (text);
				md5.TransformFinalBlock (buf, 0, buf.Length);
				a1 = HexEncode (md5.Hash);
			}

			// compute A2
			text = client ? "AUTHENTICATE:" : ":";
			text += DigestUri;

			if (Qop == "auth-int" || Qop == "auth-conf")
				text += ":00000000000000000000000000000000";

			buf = Encoding.ASCII.GetBytes (text);
			using (var md5 = new MD5 ())
				digest = md5.ComputeHash (buf);
			a2 = HexEncode (digest);

			// compute KD
			text = string.Format ("{0}:{1}:{2:x8}:{3}:{4}:{5}", a1, Nonce, Nc, CNonce, Qop, a2);
			buf = Encoding.ASCII.GetBytes (text);
			using (var md5 = new MD5 ())
				digest = md5.ComputeHash (buf);

			return HexEncode (digest);
		}
예제 #3
0
		/// <summary>
		/// Parses the server's challenge token and returns the next challenge response.
		/// </summary>
		/// <remarks>
		/// Parses the server's challenge token and returns the next challenge response.
		/// </remarks>
		/// <returns>The next challenge response.</returns>
		/// <param name="token">The server's challenge token.</param>
		/// <param name="startIndex">The index into the token specifying where the server's challenge begins.</param>
		/// <param name="length">The length of the server's challenge.</param>
		/// <exception cref="System.InvalidOperationException">
		/// The SASL mechanism is already authenticated.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// The SASL mechanism does not support SASL-IR.
		/// </exception>
		/// <exception cref="SaslException">
		/// An error has occurred while parsing the server's challenge token.
		/// </exception>
		protected override byte[] Challenge (byte[] token, int startIndex, int length)
		{
			if (IsAuthenticated)
				throw new InvalidOperationException ();

			if (token == null)
				throw new NotSupportedException ("CRAM-MD5 does not support SASL-IR.");

			var cred = Credentials.GetCredential (Uri, MechanismName);
			var userName = Encoding.UTF8.GetBytes (cred.UserName);
			var password = Encoding.UTF8.GetBytes (cred.Password);
			var ipad = new byte[64];
			var opad = new byte[64];
			byte[] digest;

			if (password.Length > 64) {
				byte[] checksum;

				using (var md5 = new MD5 ())
					checksum = md5.ComputeHash (password);

				Array.Copy (checksum, ipad, checksum.Length);
				Array.Copy (checksum, opad, checksum.Length);
			} else {
				Array.Copy (password, ipad, password.Length);
				Array.Copy (password, opad, password.Length);
			}

			for (int i = 0; i < 64; i++) {
				ipad[i] ^= 0x36;
				opad[i] ^= 0x5c;
			}

			using (var md5 = new MD5 ()) {
				md5.TransformBlock (ipad, 0, ipad.Length, null, 0);
				md5.TransformFinalBlock (token, startIndex, length);
				digest = md5.Hash;
			}

			using (var md5 = new MD5 ()) {
				md5.TransformBlock (opad, 0, opad.Length, null, 0);
				md5.TransformFinalBlock (digest, 0, digest.Length);
				digest = md5.Hash;
			}

			var buffer = new byte[userName.Length + 1 + (digest.Length * 2)];
			int offset = 0;

			for (int i = 0; i < userName.Length; i++)
				buffer[offset++] = userName[i];
			buffer[offset++] = 0x20;
			for (int i = 0; i < digest.Length; i++) {
				byte c = digest[i];

				buffer[offset++] = HexAlphabet[(c >> 4) & 0x0f];
				buffer[offset++] = HexAlphabet[c & 0x0f];
			}

			IsAuthenticated = true;

			return buffer;
		}
예제 #4
0
        /// <summary>
        /// Parses the server's challenge token and returns the next challenge response.
        /// </summary>
        /// <remarks>
        /// Parses the server's challenge token and returns the next challenge response.
        /// </remarks>
        /// <returns>The next challenge response.</returns>
        /// <param name="token">The server's challenge token.</param>
        /// <param name="startIndex">The index into the token specifying where the server's challenge begins.</param>
        /// <param name="length">The length of the server's challenge.</param>
        /// <exception cref="System.InvalidOperationException">
        /// The SASL mechanism is already authenticated.
        /// </exception>
        /// <exception cref="System.NotSupportedException">
        /// THe SASL mechanism does not support SASL-IR.
        /// </exception>
        /// <exception cref="SaslException">
        /// An error has occurred while parsing the server's challenge token.
        /// </exception>
        protected override byte[] Challenge(byte[] token, int startIndex, int length)
        {
            if (IsAuthenticated)
            {
                throw new InvalidOperationException();
            }

            if (token == null)
            {
                throw new NotSupportedException("CRAM-MD5 does not support SASL-IR.");
            }

            var cred     = Credentials.GetCredential(Uri, MechanismName);
            var userName = Encoding.UTF8.GetBytes(cred.UserName);
            var password = Encoding.UTF8.GetBytes(cred.Password);
            var ipad     = new byte[64];
            var opad     = new byte[64];

            byte[] digest;

            if (password.Length > 64)
            {
                byte[] checksum;

                using (var md5 = new MD5())
                    checksum = md5.ComputeHash(password);

                Array.Copy(checksum, ipad, checksum.Length);
                Array.Copy(checksum, opad, checksum.Length);
            }
            else
            {
                Array.Copy(password, ipad, password.Length);
                Array.Copy(password, opad, password.Length);
            }

            for (int i = 0; i < 64; i++)
            {
                ipad[i] ^= 0x36;
                opad[i] ^= 0x5c;
            }

            using (var md5 = new MD5()) {
                md5.TransformBlock(ipad, 0, ipad.Length, null, 0);
                md5.TransformFinalBlock(token, startIndex, length);
                digest = md5.Hash;
            }

            using (var md5 = new MD5()) {
                md5.TransformBlock(opad, 0, opad.Length, null, 0);
                md5.TransformFinalBlock(digest, 0, digest.Length);
                digest = md5.Hash;
            }

            var buffer = new byte[userName.Length + 1 + (digest.Length * 2)];
            int offset = 0;

            for (int i = 0; i < userName.Length; i++)
            {
                buffer[offset++] = userName[i];
            }
            buffer[offset++] = 0x20;
            for (int i = 0; i < digest.Length; i++)
            {
                byte c = digest[i];

                buffer[offset++] = HexAlphabet[(c >> 4) & 0x0f];
                buffer[offset++] = HexAlphabet[c & 0x0f];
            }

            IsAuthenticated = true;

            return(buffer);
        }