SRP6 testing
This commit is contained in:
75
Account.cs
75
Account.cs
@ -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
|
||||
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
|
||||
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
|
||||
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
|
||||
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; }
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,17 +6,32 @@
|
||||
@if (string.IsNullOrEmpty(Model.AuthToken))
|
||||
{
|
||||
<div id="LoginForm">
|
||||
<form action="?handler=Login" method="post" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label for="UserEmail">E-mail:</label>
|
||||
<input asp-for="UserEmail" type="text" id="UserEmail" />
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h6>Login</h6>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="UserPassword">Password:</label>
|
||||
<input asp-for="UserPassword" type="password" id="UserPassword">
|
||||
<div class="card-body">
|
||||
<form action="?handler=Login" method="post" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label for="UserEmail">E-mail:</label>
|
||||
<input asp-for="UserEmail" type="text" id="UserEmail" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="UserPassword">Password:</label>
|
||||
<input asp-for="UserPassword" type="password" id="UserPassword">
|
||||
</div>
|
||||
<input type="submit">
|
||||
@Html.AntiForgeryToken()
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -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 @@
|
||||
<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>
|
||||
|
||||
@ -11,7 +11,7 @@ namespace NightmareCoreWeb2.Pages
|
||||
{
|
||||
public class AccountModel : PageModel
|
||||
{
|
||||
public string UserEmail { get; set; }
|
||||
public string UserEmail { get; set; }
|
||||
public string UserPassword { get; set; }
|
||||
public string CharacterListType { get; set; }
|
||||
public string AuthToken { get; set; }
|
||||
@ -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", a.Verifier);
|
||||
}
|
||||
|
||||
Response.Cookies.Append("Username", Username);
|
||||
Response.Cookies.Append("AuthToken", AuthToken);
|
||||
}
|
||||
|
||||
static string Hash(string input)
|
||||
|
||||
Reference in New Issue
Block a user