Skip to content

Commit

Permalink
Working on SRP protocol client, zyanfx#44.
Browse files Browse the repository at this point in the history
  • Loading branch information
yallie committed May 16, 2018
1 parent a4ce45e commit d1288b6
Show file tree
Hide file tree
Showing 5 changed files with 243 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;

Expand Down Expand Up @@ -84,5 +85,65 @@ public static SrpEphemeral GenerateEphemeral()
Public = A.ToHex(),
};
}

/// <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 static SrpSession DeriveSession(string clientSecretEphemeral, string serverPublicEphemeral, string salt, string username, string 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 = SrpParameters.Default.N;
var g = SrpParameters.Default.G;
var k = SrpParameters.Default.K;
var H = SrpParameters.Default.H;

// 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.FromHex(salt);
var I = username + string.Empty;
var x = SrpInteger.FromHex(privateKey);

// A = g^a (a = random number)
var A = g.ModPow(a, N);

// B % N > 0
if (B % N == SrpInteger.Zero)
{
// fixme: .code, .statusCode, etc.
throw new SecurityException("The server sent an invalid public ephemeral");
}

// u = H(A, B)
var u = H(A, B);

// S = (B - kg^x) ^ (a + ux)
var S = (B - (k * (g.ModPow(x, N)))).ModPow(a + (u * x), N);

// K = H(S)
var K = H(S);

// M = H(H(N) xor H(g), H(I), s, A, B, K)
var M = H(H(N) ^ H(g), H(I), s, A, B, K);

return new SrpSession
{
Key = K.ToHex(),
Proof = M.ToHex()
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ private static SrpInteger ComputeHash(byte[] data)
var hasher = CreateHasher();
var hash = hasher.ComputeHash(data);

// reverse the byte order for the little-endian encoding
return SrpInteger.FromBytes(hash.Reverse().ToArray());
// reverse the byte order for the little-endian encoding — doesn't take the sign into account
//return SrpInteger.FromBytes(hash.Reverse().ToArray());

// 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);
var hex = hash.Aggregate(new StringBuilder(), (sb, b) => sb.Append(b.ToString("X2")), sb => sb.ToString());
return SrpInteger.FromHex(hex);
}

private static byte[] EmptyBuffer = new byte[0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public SrpInteger(string hex, int? hexLength = null)
/// </summary>
private SrpInteger()
{
HexLength = 1;
Value = BigInteger.Zero;
}

/// <summary>
Expand All @@ -46,7 +48,7 @@ private static string NormalizeWhitespace(string hexNumber) =>
/// <summary>
/// The <see cref="SrpInteger"/> value representing 0.
/// </summary>
public static SrpInteger Zero { get; } = FromHex("0");
public static SrpInteger Zero { get; } = new SrpInteger();

private BigInteger Value { get; set; }

Expand Down Expand Up @@ -102,7 +104,7 @@ public string ToHex()
}

// ToString may add extra leading zeros to the positive BigIntegers, so we trim them first
return Value.ToString("X").TrimStart('0').PadLeft(HexLength.Value, '0');
return Value.ToString("x").TrimStart('0').PadLeft(HexLength.Value, '0');
}

/// <summary>
Expand All @@ -125,6 +127,48 @@ public string ToHex()
/// <param name="right">The right.</param>
public static bool operator !=(SrpInteger left, SrpInteger right) => !Equals(left, right);

/// <summary>
/// Implements the operator -.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
public static SrpInteger operator -(SrpInteger left, SrpInteger right)
{
return new SrpInteger
{
Value = left.Value - right.Value,
HexLength = left.HexLength,
};
}

/// <summary>
/// Implements the operator +.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
public static SrpInteger operator +(SrpInteger left, SrpInteger right)
{
return new SrpInteger
{
Value = left.Value + right.Value,
HexLength = left.HexLength,
};
}

/// <summary>
/// Implements the operator /.
/// </summary>
/// <param name="dividend">The dividend.</param>
/// <param name="divisor">The divisor.</param>
public static SrpInteger operator /(SrpInteger dividend, SrpInteger divisor)
{
return new SrpInteger
{
Value = dividend.Value / divisor.Value,
HexLength = dividend.HexLength,
};
}

/// <summary>
/// Implements the operator %.
/// </summary>
Expand All @@ -139,6 +183,34 @@ public string ToHex()
};
}

/// <summary>
/// Implements the operator *.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
public static SrpInteger operator *(SrpInteger left, SrpInteger right)
{
return new SrpInteger
{
Value = left.Value * right.Value,
HexLength = left.HexLength,
};
}

/// <summary>
/// Implements the operator ^ (xor).
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
public static SrpInteger operator ^(SrpInteger left, SrpInteger right)
{
return new SrpInteger
{
Value = left.Value ^ right.Value,
HexLength = left.HexLength,
};
}

/// <summary>
/// Returns a new <see cref="SrpInteger"/> instance from the given hexadecimal string.
/// </summary>
Expand Down Expand Up @@ -174,7 +246,7 @@ public static SrpInteger FromHex(string hex)
/// <inheritdoc/>
public override string ToString()
{
var hex = Value.ToString("X");
var hex = Value.ToString("x");
if (hex.Length > 16)
{
hex = hex.Substring(0, 16) + "...";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ 94B5C803 D89F7AE4 35DE236D 525F5475 9B65E372 FCD68EF2 0FA7111F
/// <summary>
/// Gets or sets the multiplier parameter (k = H(N, g) in SRP-6a, k = 3 for legacy SRP-6).
/// </summary>
public string K { get; set; }
public SrpInteger K { get; set; }

/// <summary>
/// Gets or sets the hash size in bytes.
Expand Down
Loading

0 comments on commit d1288b6

Please sign in to comment.