Browse Source

SRP6 testing

master
Gregory Rudolph 3 years ago
parent
commit
ffa165d40c
Signed by: rudi
GPG Key ID: EF64F3CBD1A1EBDD
  1. 75
      Account.cs
  2. 40
      Pages/Account.cshtml
  3. 10
      Pages/Account.cshtml.cs

75
Account.cs

@ -1,6 +1,12 @@ @@ -1,6 +1,12 @@
using System;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Collections.Generic;
using System.Security.Cryptography;
using MySql.Data.MySqlClient;
using System.Globalization;
using MiscUtil.Conversion;
namespace NightmareCoreWeb2
{
@ -11,6 +17,7 @@ namespace NightmareCoreWeb2 @@ -11,6 +17,7 @@ namespace NightmareCoreWeb2
public string Username { get; set; }
public string Email { get; set; }
public string LastIP { get; set; }
public string Verifier {get; set;}
public DateTime LastLogin { get; set; }
public List<Character> Characters { get; set; }
public List<AccountAccess> Access { get; set; }
@ -46,7 +53,7 @@ namespace NightmareCoreWeb2 @@ -46,7 +53,7 @@ namespace NightmareCoreWeb2
MySqlConnection conn = new MySqlConnection(Program.connStr);
conn.Open();
string sql = "select id,username,email,last_ip,last_login from account where username=@username";
string sql = "select id,username,email,last_ip,last_login,verifier from account where username=@username";
MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("username", username);
MySqlDataReader rdr = cmd.ExecuteReader();
@ -60,6 +67,7 @@ namespace NightmareCoreWeb2 @@ -60,6 +67,7 @@ namespace NightmareCoreWeb2
this.Email = rdr.GetString(2);
this.LastIP = rdr.GetString(3);
this.LastLogin = rdr.GetDateTime(4);
this.Verifier = rdr.GetString(5);
}
catch (Exception e)
{
@ -116,10 +124,75 @@ namespace NightmareCoreWeb2 @@ -116,10 +124,75 @@ namespace NightmareCoreWeb2
conn.Close();
}
public bool AuthenticateAccount(string password)
{
MySqlConnection conn = new MySqlConnection(Program.connStr);
conn.Open();
string sql = "select salt,verifier from account where username=@username";
MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("username", this.Username);
MySqlDataReader rdr = cmd.ExecuteReader();
string salt = "", verifier = "";
while (rdr.Read())
{
try
{
salt = rdr.GetString(0);
verifier = rdr.GetString(1);
}
catch (Exception) { }
}
return VerifySRP6Login(this.Username, password, Encoding.ASCII.GetBytes(salt), Encoding.ASCII.GetBytes(verifier));
}
// https://gist.github.com/Rochet2/3bb0adaf6f3e9a9fbc78ba5ce9a43e09
public static byte[] CalculateSRP6Verifier(string username, string password, byte[] salt_bytes)
{
// algorithm constants
BigInteger g = 7;
BigInteger N = BigInteger.Parse("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7", NumberStyles.HexNumber);
SHA1 sha1 = SHA1.Create();
// calculate first hash
byte[] login_bytes = Encoding.ASCII.GetBytes((username + ':' + password).ToUpper());
byte[] h1_bytes = sha1.ComputeHash(login_bytes);
// calculate second hash
byte[] h2_bytes = sha1.ComputeHash(salt_bytes.Concat(h1_bytes).ToArray());
// convert to integer (little-endian)
BigInteger h2 = new BigInteger(h2_bytes.Reverse().ToArray());
Console.WriteLine(h2);
// g^h2 mod N
BigInteger verifier = BigInteger.ModPow(g, h2, N);
// convert back to a byte array (little-endian)
byte[] verifier_bytes = verifier.ToByteArray().Reverse().ToArray();
// pad to 32 bytes, remember that zeros go on the end in little-endian!
byte[] verifier_bytes_padded = new byte[Math.Max(32, verifier_bytes.Length)];
Buffer.BlockCopy(verifier_bytes, 0, verifier_bytes_padded, 0, verifier_bytes.Length);
// done!
return verifier_bytes_padded;
}
public static bool VerifySRP6Login(string username, string password, byte[] salt, byte[] verifier)
{
// re-calculate the verifier using the provided username + password and the stored salt
byte[] checkVerifier = CalculateSRP6Verifier(username, password, salt);
Console.WriteLine($"{Encoding.ASCII.GetString(verifier)}\n{Encoding.ASCII.GetString(checkVerifier)}");
// compare it against the stored verifier
return verifier.SequenceEqual(checkVerifier);
}
}
public class AccountAccess
{
public int SecurityLevel { get; set; }
public int RealmID { get; set; }
}
}

40
Pages/Account.cshtml

@ -6,6 +6,12 @@ @@ -6,6 +6,12 @@
@if (string.IsNullOrEmpty(Model.AuthToken))
{
<div id="LoginForm">
<div class="card">
<div class="card-header">
<h6>Login</h6>
</div>
<div class="card-body">
<form action="?handler=Login" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="UserEmail">E-mail:</label>
@ -15,8 +21,17 @@ @@ -15,8 +21,17 @@
<label for="UserPassword">Password:</label>
<input asp-for="UserPassword" type="password" id="UserPassword">
</div>
<input type="submit">
@Html.AntiForgeryToken()
</form>
</div>
</div>
</div>
<br/>
}
else
{
@ -55,10 +70,14 @@ @@ -55,10 +70,14 @@
<p class="card-text">@ticket.Description</p>
<br>
<a class="btn active" href="/Account?handler=CharacterAction&guid=@ticket.Id&action=1">Rename Character</a>
<a class="btn active" href="/Account?handler=CharacterAction&guid=@ticket.Id&action=8">Recustomize Character</a>
<a class="btn active" href="/Account?handler=CharacterAction&guid=@ticket.Id&action=64">Change Faction</a>
<a class="btn active" href="/Account?handler=CharacterAction&guid=@ticket.Id&action=128">Change Race</a>
<a class="btn active" href="/Account?handler=CharacterAction&guid=@ticket.Id&action=1">Rename
Character</a>
<a class="btn active"
href="/Account?handler=CharacterAction&guid=@ticket.Id&action=8">Recustomize Character</a>
<a class="btn active" href="/Account?handler=CharacterAction&guid=@ticket.Id&action=64">Change
Faction</a>
<a class="btn active" href="/Account?handler=CharacterAction&guid=@ticket.Id&action=128">Change
Race</a>
</div>
<div class="card-footer text-muted">
<p>Opened @ticket.CreateTime.ToLocalTime()</p>
@ -79,10 +98,15 @@ @@ -79,10 +98,15 @@
<h6>@character.Name</h6>
</div>
<div class="card-body">
<a class="btn active" href="/Account?handler=CharacterAction&guid=@character.guid&action=1">Rename Character</a>
<a class="btn active" href="/Account?handler=CharacterAction&guid=@character.guid&action=8">Recustomize Character</a>
<a class="btn active" href="/Account?handler=CharacterAction&guid=@character.guid&action=64">Change Faction</a>
<a class="btn active" href="/Account?handler=CharacterAction&guid=@character.guid&action=128">Change Race</a>
<a class="btn active"
href="/Account?handler=CharacterAction&guid=@character.guid&action=1">Rename Character</a>
<a class="btn active"
href="/Account?handler=CharacterAction&guid=@character.guid&action=8">Recustomize
Character</a>
<a class="btn active"
href="/Account?handler=CharacterAction&guid=@character.guid&action=64">Change Faction</a>
<a class="btn active"
href="/Account?handler=CharacterAction&guid=@character.guid&action=128">Change Race</a>
</div>
<div class="card-footer text-muted">
<p>Level @character.Level @character.GetRace() @character.GetClass()</p>

10
Pages/Account.cshtml.cs

@ -88,13 +88,17 @@ namespace NightmareCoreWeb2.Pages @@ -88,13 +88,17 @@ namespace NightmareCoreWeb2.Pages
public void OnPostLogin()
{
Console.WriteLine("Logging in!");
UserEmail = Request.Form["UserEmail"];
UserPassword = Request.Form["UserPassword"];
Username = UserEmail.Substring(0, UserEmail.IndexOf("@"));
AuthToken = Hash($"{Username.ToUpper()}:{UserPassword.ToUpper()}");
Account a = new Account(Username);
if (a.AuthenticateAccount(UserPassword))
{
Response.Cookies.Append("Username", Username);
Response.Cookies.Append("AuthToken", AuthToken);
Response.Cookies.Append("AuthToken", a.Verifier);
}
}
static string Hash(string input)

Loading…
Cancel
Save