/// <summary> /// Computes the client response containing the client's public key and /// evidence. /// </summary> /// <param name="challenge">The challenge containing the protocol elements /// received from the server in response to the initial client /// response.</param> /// <returns>An array of bytes containing the client's challenge /// response.</returns> /// <exception cref="SaslException">Thrown if the server specified any /// mandatory options which are not supported.</exception> private byte[] ComputeFinalResponse(byte[] challenge) { ServerMessage1 m = ServerMessage1.Deserialize(challenge); // We don't support integrity protection or confidentiality. if (!String.IsNullOrEmpty(m.Options["mandatory"])) { throw new SaslException("Mandatory options are not supported."); } // Set up the message digest algorithm. var mda = SelectHashAlgorithm(m.Options["mda"]); HashAlgorithm = Activator.CreateInstance(mda.Item2) as HashAlgorithm; // Compute public and private key. PublicKey = Helper.ComputeClientPublicKey(m.Generator, m.SafePrimeModulus, PrivateKey); // Compute the shared key and client evidence. SharedKey = Helper.ComputeSharedKey(m.Salt, Username, Password, PublicKey, m.PublicKey, PrivateKey, m.Generator, m.SafePrimeModulus, HashAlgorithm); ClientProof = Helper.ComputeClientProof(m.SafePrimeModulus, m.Generator, Username, m.Salt, PublicKey, m.PublicKey, SharedKey, AuthId, m.RawOptions, HashAlgorithm); ClientMessage2 response = new ClientMessage2(PublicKey, ClientProof); // Let the server know which hash algorithm we are using. response.Options["mda"] = mda.Item1; // Remember the raw options string because we'll need it again // when verifying the server signature. Options = response.BuildOptionsString(); return(response.Serialize()); }
public void DeserializeServerFirstMessage() { ServerMessage1 m = ServerMessage1.Deserialize(serverMessage1); BigInteger expectedGenerator = new BigInteger(2), expectedModulus = BigInteger.Parse(expectedSafePrimeModulus, NumberStyles.HexNumber), _expectedPublicKey = BigInteger.Parse(expectedPublicKey, NumberStyles.HexNumber); Assert.AreEqual <BigInteger>(expectedGenerator, m.Generator.Value); Assert.AreEqual <BigInteger>(expectedModulus, m.SafePrimeModulus.Value); Assert.AreEqual <BigInteger>(_expectedPublicKey, m.PublicKey.Value); Assert.IsTrue(m.Salt.SequenceEqual(expectedSalt)); Assert.AreEqual <string>(expectedOptions, m.RawOptions); Assert.AreEqual <int>(expectedParsedOptions.Count, m.Options.Count); foreach (KeyValuePair <string, string> pair in expectedParsedOptions) { Assert.AreEqual <string>(pair.Value, m.Options[pair.Key]); } }