Ejemplo n.º 1
0
        /// <summary>
        /// Computes the server evidence from the given parameters.
        /// </summary>
        /// <param name="clientPublicKey">The client's ephemeral public key.</param>
        /// <param name="clientProof"></param>
        /// <param name="sharedKey">The shared context key.</param>
        /// <param name="authId">The authorization identity.</param>
        /// <param name="options">The raw options string as sent by the
        /// client.</param>
        /// <param name="sid">The session id sent by the server.</param>
        /// <param name="ttl">The time-to-live value for the session id sent
        /// by the server.</param>
        /// <param name="hashAlgorithm">The message digest algorithm to use for
        /// calculating the server proof.</param>
        /// <returns>The server proof as an array of bytes.</returns>
        public static byte[] ComputeServerProof(Mpi clientPublicKey, byte[] clientProof,
                                                Mpi sharedKey, string authId, string options, string sid, uint ttl,
                                                HashAlgorithm hashAlgorithm)
        {
            byte[] A = clientPublicKey.ToBytes(), M1 = clientProof,
            K = sharedKey.ToBytes(), I = Encoding.UTF8.GetBytes(authId),
            o = Encoding.UTF8.GetBytes(options), _sid = Encoding.UTF8.GetBytes(sid);
            HashAlgorithm H = hashAlgorithm;

            // The proof is calculated as follows:
            //
            // H( bytes(A)
            //  | bytes(M1)
            //  | bytes(K)
            //  | bytes(H( bytes(I) ))
            //  | bytes(H( bytes(o) ))
            //  | bytes(sid)
            //  | ttl
            // )
            byte[] seq = new ByteBuilder()
                         .Append(A)
                         .Append(M1)
                         .Append(K)
                         .Append(H.ComputeHash(I))
                         .Append(H.ComputeHash(o))
                         .Append(_sid)
                         .Append(ttl, true)
                         .ToArray();
            return(H.ComputeHash(seq));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Computes the client evidence from the given parameters.
        /// </summary>
        /// <param name="safePrimeModulus">The safe prime modulus sent by the
        /// server.</param>
        /// <param name="generator">The generator sent by the server.</param>
        /// <param name="username">The username to authenticate with.</param>
        /// <param name="salt">The client's password salt.</param>
        /// <param name="clientPublicKey">The client's ephemeral public key.</param>
        /// <param name="serverPublicKey">The server's ephemeral public key.</param>
        /// <param name="sharedKey">The shared context key.</param>
        /// <param name="authId">The authorization identity.</param>
        /// <param name="options">The raw options string as received from the
        /// server.</param>
        /// <param name="hashAlgorithm">The message digest algorithm to use for
        /// calculating the client proof.</param>
        /// <returns>The client proof as an array of bytes.</returns>
        public static byte[] ComputeClientProof(Mpi safePrimeModulus, Mpi generator,
                                                string username, byte[] salt, Mpi clientPublicKey, Mpi serverPublicKey,
                                                Mpi sharedKey, string authId, string options, HashAlgorithm hashAlgorithm)
        {
            byte[] N = safePrimeModulus.ToBytes(), g = generator.ToBytes(),
            U = Encoding.UTF8.GetBytes(username), s = salt,
            A = clientPublicKey.ToBytes(), B = serverPublicKey.ToBytes(),
            K = sharedKey.ToBytes(), I = Encoding.UTF8.GetBytes(authId),
            L = Encoding.UTF8.GetBytes(options);
            HashAlgorithm H = hashAlgorithm;

            // The proof is calculated as follows:
            //
            // H( bytes(H( bytes(N) )) ^ bytes( H( bytes(g) ))
            //  | bytes(H( bytes(U) ))
            //  | bytes(s)
            //  | bytes(A)
            //  | bytes(B)
            //  | bytes(K)
            //  | bytes(H( bytes(I) ))
            //  | bytes(H( bytes(L) ))
            // )
            byte[] seq = new ByteBuilder()
                         .Append(Xor(H.ComputeHash(N), H.ComputeHash(g)))
                         .Append(H.ComputeHash(U))
                         .Append(s)
                         .Append(A)
                         .Append(B)
                         .Append(K)
                         .Append(H.ComputeHash(I))
                         .Append(H.ComputeHash(L))
                         .ToArray();
            return(H.ComputeHash(seq));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Calculates the shared context key K from the given parameters.
        /// </summary>
        /// <param name="salt">The user's password salt.</param>
        /// <param name="username">The username to authenticate with.</param>
        /// <param name="password">The password to authenticate with.</param>
        /// <param name="clientPublicKey">The client's ephemeral public key.</param>
        /// <param name="serverPublicKey">The server's ephemeral public key.</param>
        /// <param name="clientPrivateKey">The client's private key.</param>
        /// <param name="generator">The generator sent by the server.</param>
        /// <param name="safePrimeModulus">The safe prime modulus sent by the
        /// server.</param>
        /// <param name="hashAlgorithm">The negotiated hash algorithm to use
        /// for the calculations.</param>
        /// <returns>The shared context key K as a "multi-precision
        /// integer".</returns>
        /// <remarks>
        /// A = Client Public Key
        /// B = Server Public Key
        /// N = Safe Prime Modulus
        /// U = Username
        /// p = Password
        /// s = User's Password Salt
        /// a = Client Private Key
        /// g = Generator
        /// K = Shared Public Key
        /// </remarks>
        public static Mpi ComputeSharedKey(byte[] salt, string username,
                                           string password, Mpi clientPublicKey, Mpi serverPublicKey,
                                           Mpi clientPrivateKey, Mpi generator, Mpi safePrimeModulus,
                                           HashAlgorithm hashAlgorithm)
        {
            // u = H(A | B)
            byte[] u = hashAlgorithm.ComputeHash(new ByteBuilder()
                                                 .Append(clientPublicKey.ToBytes())
                                                 .Append(serverPublicKey.ToBytes())
                                                 .ToArray());
            // x = H(s | H(U | ":" | p))
            byte[] up = hashAlgorithm.ComputeHash(
                Encoding.UTF8.GetBytes(username + ":" + password)),
            sup = new ByteBuilder().Append(salt).Append(up).ToArray(),
            x   = hashAlgorithm.ComputeHash(sup);
            // S = ((B - (3 * g ^ x)) ^ (a + u * x)) % N
            Mpi _u = new Mpi(u), _x = new Mpi(x);

            ts.TraceInformation("ComputeSharedKey: _u = " + _u.Value.ToString("X"));
            ts.TraceInformation("ComputeSharedKey: _x = " + _x.Value.ToString("X"));
            // base = B - (3 * (g ^ x))

            BigInteger _base = BigInteger.Subtract(serverPublicKey.Value,
                                                   BigInteger.Multiply(new BigInteger(3),
                                                                       BigInteger.ModPow(generator.Value, _x.Value, safePrimeModulus.Value)) %
                                                   safePrimeModulus.Value);

            if (_base.Sign < 0)
            {
                _base = BigInteger.Add(_base, safePrimeModulus.Value);
            }
            ts.TraceInformation("ComputeSharedKey: _base = " + _base.ToString("X"));

            // Alternative way to calculate base; This is not being used in actual calculations
            // but still here to ease debugging.
            BigInteger gx  = BigInteger.ModPow(generator.Value, _x.Value, safePrimeModulus.Value),
                       gx3 = BigInteger.Multiply(new BigInteger(3), gx) % safePrimeModulus.Value;

            ts.TraceInformation("ComputeSharedKey: gx = " + gx.ToString("X"));
            BigInteger @base = BigInteger.Subtract(serverPublicKey.Value, gx3) % safePrimeModulus.Value;

            if (@base.Sign < 0)
            {
                @base = BigInteger.Add(@base, safePrimeModulus.Value);
            }
            ts.TraceInformation("ComputeSharedKey: @base = " + @base.ToString("X"));

            // exp = a + u * x
            BigInteger exp = BigInteger.Add(clientPrivateKey.Value,
                                            BigInteger.Multiply(_u.Value, _x.Value)),
                       S = BigInteger.ModPow(_base, exp, safePrimeModulus.Value);

            ts.TraceInformation("ComputeSharedKey: exp = " + exp.ToString("X"));
            ts.TraceInformation("ComputeSharedKey: S = " + S.ToString("X"));

            // K = H(S)
            return(new Mpi(hashAlgorithm.ComputeHash(new Mpi(S).ToBytes())));
        }
Ejemplo n.º 4
0
		/// <summary>
		/// Computes the server evidence from the given parameters.
		/// </summary>
		/// <param name="clientPublicKey">The client's ephemeral public key.</param>
		/// <param name="clientProof"></param>
		/// <param name="sharedKey">The shared context key.</param>
		/// <param name="authId">The authorization identity.</param>
		/// <param name="options">The raw options string as sent by the
		/// client.</param>
		/// <param name="sid">The session id sent by the server.</param>
		/// <param name="ttl">The time-to-live value for the session id sent
		/// by the server.</param>
		/// <param name="hashAlgorithm">The message digest algorithm to use for
		/// calculating the server proof.</param>
		/// <returns>The server proof as an array of bytes.</returns>
		public static byte[] ComputeServerProof(Mpi clientPublicKey, byte[] clientProof,
			Mpi sharedKey, string authId, string options, string sid, uint ttl,
			HashAlgorithm hashAlgorithm) {
			byte[] A = clientPublicKey.ToBytes(), M1 = clientProof,
				K = sharedKey.ToBytes(), I = Encoding.UTF8.GetBytes(authId),
				o = Encoding.UTF8.GetBytes(options), _sid = Encoding.UTF8.GetBytes(sid);
			HashAlgorithm H = hashAlgorithm;
			// The proof is calculated as follows:
			//
			// H( bytes(A)
			//  | bytes(M1)
			//  | bytes(K)
			//  | bytes(H( bytes(I) ))
			//  | bytes(H( bytes(o) ))
			//  | bytes(sid)
			//  | ttl
			// )
			byte[] seq = new ByteBuilder()
				.Append(A)
				.Append(M1)
				.Append(K)
				.Append(H.ComputeHash(I))
				.Append(H.ComputeHash(o))
				.Append(_sid)
				.Append(ttl, true)
				.ToArray();
			return H.ComputeHash(seq);
		}
Ejemplo n.º 5
0
		/// <summary>
		/// Computes the client evidence from the given parameters.
		/// </summary>
		/// <param name="safePrimeModulus">The safe prime modulus sent by the
		/// server.</param>
		/// <param name="generator">The generator sent by the server.</param>
		/// <param name="username">The username to authenticate with.</param>
		/// <param name="salt">The client's password salt.</param>
		/// <param name="clientPublicKey">The client's ephemeral public key.</param>
		/// <param name="serverPublicKey">The server's ephemeral public key.</param>
		/// <param name="sharedKey">The shared context key.</param>
		/// <param name="authId">The authorization identity.</param>
		/// <param name="options">The raw options string as received from the
		/// server.</param>
		/// <param name="hashAlgorithm">The message digest algorithm to use for
		/// calculating the client proof.</param>
		/// <returns>The client proof as an array of bytes.</returns>
		public static byte[] ComputeClientProof(Mpi safePrimeModulus, Mpi generator,
			string username, byte[] salt, Mpi clientPublicKey, Mpi serverPublicKey,
			Mpi sharedKey, string authId, string options, HashAlgorithm hashAlgorithm) {
			byte[] N = safePrimeModulus.ToBytes(), g = generator.ToBytes(),
				U = Encoding.UTF8.GetBytes(username), s = salt,
				A = clientPublicKey.ToBytes(), B = serverPublicKey.ToBytes(),
				K = sharedKey.ToBytes(), I = Encoding.UTF8.GetBytes(authId),
				L = Encoding.UTF8.GetBytes(options);
			HashAlgorithm H = hashAlgorithm;
			// The proof is calculated as follows:
			//
			// H( bytes(H( bytes(N) )) ^ bytes( H( bytes(g) ))
			//  | bytes(H( bytes(U) ))
			//  | bytes(s)
			//  | bytes(A)
			//  | bytes(B)
			//  | bytes(K)
			//  | bytes(H( bytes(I) ))
			//  | bytes(H( bytes(L) ))
			// )
			byte[] seq = new ByteBuilder()
				.Append(Xor(H.ComputeHash(N), H.ComputeHash(g)))
				.Append(H.ComputeHash(U))
				.Append(s)
				.Append(A)
				.Append(B)
				.Append(K)
				.Append(H.ComputeHash(I))
				.Append(H.ComputeHash(L))
				.ToArray();
			return H.ComputeHash(seq);
		}
Ejemplo n.º 6
0
		/// <summary>
		/// Calculates the shared context key K from the given parameters.
		/// </summary>
		/// <param name="salt">The user's password salt.</param>
		/// <param name="username">The username to authenticate with.</param>
		/// <param name="password">The password to authenticate with.</param>
		/// <param name="clientPublicKey">The client's ephemeral public key.</param>
		/// <param name="serverPublicKey">The server's ephemeral public key.</param>
		/// <param name="clientPrivateKey">The client's private key.</param>
		/// <param name="generator">The generator sent by the server.</param>
		/// <param name="safePrimeModulus">The safe prime modulus sent by the
		/// server.</param>
		/// <param name="hashAlgorithm">The negotiated hash algorithm to use
		/// for the calculations.</param>
		/// <returns>The shared context key K as a "multi-precision
		/// integer".</returns>
		/// <remarks>
		/// A = Client Public Key
		/// B = Server Public Key
		/// N = Safe Prime Modulus
		/// U = Username
		/// p = Password
		/// s = User's Password Salt
		/// a = Client Private Key
		/// g = Generator
		/// K = Shared Public Key
		/// </remarks>
		public static Mpi ComputeSharedKey(byte[] salt, string username,
			string password, Mpi clientPublicKey, Mpi serverPublicKey,
			Mpi clientPrivateKey, Mpi generator, Mpi safePrimeModulus,
			HashAlgorithm hashAlgorithm) {
			// u = H(A | B)
			byte[] u = hashAlgorithm.ComputeHash(new ByteBuilder()
				.Append(clientPublicKey.ToBytes())
				.Append(serverPublicKey.ToBytes())
				.ToArray());
			// x = H(s | H(U | ":" | p))
			byte[] up = hashAlgorithm.ComputeHash(
				Encoding.UTF8.GetBytes(username + ":" + password)),
				sup = new ByteBuilder().Append(salt).Append(up).ToArray(),
				x = hashAlgorithm.ComputeHash(sup);
			// S = ((B - (3 * g ^ x)) ^ (a + u * x)) % N
			Mpi _u = new Mpi(u), _x = new Mpi(x);
			ts.TraceInformation("ComputeSharedKey: _u = " + _u.Value.ToString("X"));
			ts.TraceInformation("ComputeSharedKey: _x = " + _x.Value.ToString("X"));
			// base = B - (3 * (g ^ x))
			
			BigInteger _base = BigInteger.Subtract(serverPublicKey.Value,
				BigInteger.Multiply(new BigInteger(3),
				BigInteger.ModPow(generator.Value, _x.Value, safePrimeModulus.Value)) %
				safePrimeModulus.Value);
			if (_base.Sign < 0)
				_base = BigInteger.Add(_base, safePrimeModulus.Value);
			ts.TraceInformation("ComputeSharedKey: _base = " + _base.ToString("X"));

			// Alternative way to calculate base; This is not being used in actual calculations
			// but still here to ease debugging.
			BigInteger gx = BigInteger.ModPow(generator.Value, _x.Value, safePrimeModulus.Value),
				gx3 = BigInteger.Multiply(new BigInteger(3), gx) % safePrimeModulus.Value;
			ts.TraceInformation("ComputeSharedKey: gx = " + gx.ToString("X"));
			BigInteger @base = BigInteger.Subtract(serverPublicKey.Value, gx3) % safePrimeModulus.Value;
			if (@base.Sign < 0)
				@base = BigInteger.Add(@base, safePrimeModulus.Value);
			ts.TraceInformation("ComputeSharedKey: @base = " + @base.ToString("X"));

			// exp = a + u * x
			BigInteger exp = BigInteger.Add(clientPrivateKey.Value,
				BigInteger.Multiply(_u.Value, _x.Value)),
			S = BigInteger.ModPow(_base, exp, safePrimeModulus.Value);
			ts.TraceInformation("ComputeSharedKey: exp = " + exp.ToString("X"));
			ts.TraceInformation("ComputeSharedKey: S = " + S.ToString("X"));

			// K = H(S)
			return new Mpi(hashAlgorithm.ComputeHash(new Mpi(S).ToBytes()));
		}