private SrpInteger ComputeHash(byte[] data) { var hash = Hasher.ComputeHash(data); return(SrpInteger.FromByteArray(hash)); // should yield the same result: // var hex = hash.Aggregate(new StringBuilder(), (sb, b) => sb.Append(b.ToString("X2")), sb => sb.ToString()); // return SrpInteger.FromHex(hex); }
/// <summary> /// Derives the client session. /// </summary> /// <param name="clientSecretEphemeral">The client secret ephemeral.</param> /// <param name="serverPublicEphemeral">The server public ephemeral.</param> /// <param name="salt">The salt.</param> /// <param name="username">The username.</param> /// <param name="privateKey">The private key.</param> /// <returns>Session key and proof.</returns> public SrpSession DeriveSession(string clientSecretEphemeral, string serverPublicEphemeral, byte[] salt, string username, byte[] privateKey) { // N — A large safe prime (N = 2q+1, where q is prime) // g — A generator modulo N // k — Multiplier parameter (k = H(N, g) in SRP-6a, k = 3 for legacy SRP-6) // H — One-way hash function var N = Parameters.Prime; var g = Parameters.Generator; var H = Parameters.Hash; // a — Secret ephemeral value // B — Public ephemeral value // s — User's salt // I — Username // x — Private key (derived from p and s) var a = SrpInteger.FromHex(clientSecretEphemeral); var B = SrpInteger.FromHex(serverPublicEphemeral); var s = SrpInteger.FromByteArray(salt); var I = username + string.Empty; var x = SrpInteger.FromByteArray(privateKey); // A = g^a (a = random number) var A = g.ModPow(a, N); // B % N > 0 if (B % N == 0) { // fixme: .code, .statusCode, etc. throw new SecurityException("The server sent an invalid public ephemeral"); } // u = H(PAD(A), PAD(B)) var u = ComputeU(A, B); // S = (B - kg^x) ^ (a + ux) var S = ComputeS(a, B, u, x); // K = H(S) var K = H(S); // M1 = H(H(N) xor H(g), H(I), s, A, B, K) var M1 = H(H(N) ^ H(g), H(I), s, A, B, K); return(new SrpSession { Key = K.ToByteArray(), Proof = M1.ToByteArray(), }); }
/// <summary> /// Verifies the session using the server-provided session proof. /// </summary> /// <param name="clientPublicEphemeral">The client public ephemeral.</param> /// <param name="clientSession">The client session.</param> /// <param name="serverSessionProof">The server session proof.</param> public void VerifySession(string clientPublicEphemeral, SrpSession clientSession, string serverSessionProof) { // H — One-way hash function var H = Parameters.Hash; // A — Public ephemeral values // M — Proof of K // K — Shared, strong session key var A = SrpInteger.FromHex(clientPublicEphemeral); var M = SrpInteger.FromByteArray(clientSession.Proof); var K = SrpInteger.FromByteArray(clientSession.Key); // H(A, M, K) var expected = H(A, M, K); var actual = SrpInteger.FromHex(serverSessionProof); if (actual != expected) { // fixme: .code, .statusCode, etc. throw new SecurityException("Server provided session proof is invalid"); } }