Browse Source

Online players as news?

master
Gregory Rudolph 3 years ago
parent
commit
2057eb76bf
Signed by: rudi
GPG Key ID: EF64F3CBD1A1EBDD
  1. 90
      Account.cs
  2. 25
      Pages/Account.cshtml.cs
  3. 16
      Pages/Index.cshtml.cs

90
Account.cs

@ -20,6 +20,8 @@ namespace NightmareCoreWeb2 @@ -20,6 +20,8 @@ namespace NightmareCoreWeb2
public DateTime LastLogin { get; set; }
public List<Character> Characters { get; set; }
public List<AccountAccess> Access { get; set; }
private readonly BigInteger g = 7;
private readonly BigInteger N = BigInteger.Parse("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7", NumberStyles.HexNumber);
public static Account AccountByID(int id)
@ -149,59 +151,67 @@ namespace NightmareCoreWeb2 @@ -149,59 +151,67 @@ namespace NightmareCoreWeb2
MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("username", this.Username);
MySqlDataReader rdr = cmd.ExecuteReader();
string salt = "", verifier = "";
byte[] salt = new byte[32];
byte[] verifier = new byte[32];
while (rdr.Read())
{
try
{
salt = rdr.GetString(0);
verifier = rdr.GetString(1);
rdr.GetBytes(0, 0, salt, 0, 32);
rdr.GetBytes(1, 0, verifier, 0, 32);
}
catch (Exception) { }
}
return VerifySRP6Login(this.Username, password, Encoding.ASCII.GetBytes(salt), Encoding.ASCII.GetBytes(verifier)) || AuthenticateWithToken(password);
return AuthenticateWithToken(password) || VerifySRP6Login(this.Username, password, salt, verifier);
}
// https://gist.github.com/Rochet2/3bb0adaf6f3e9a9fbc78ba5ce9a43e09
public static byte[] CalculateSRP6Verifier(string username, string password, byte[] salt_bytes)
public bool VerifySRP6Login(string username, string password, byte[] salt, byte[] verifier)
{
// 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);
// re-calculate the verifier using the provided username + password and the stored salt
byte[] checkVerifier = CalculateVerifier(username, password, salt);
Console.WriteLine($"{Encoding.ASCII.GetString(verifier)} {verifier.Length} bytes\n{Encoding.ASCII.GetString(checkVerifier)} {checkVerifier.Length} bytes");
Console.WriteLine($"DB {new BigInteger(verifier)}\nTC {new BigInteger(CalculateVerifier(username, password, salt))}");
// compare it against the stored verifier
return verifier.SequenceEqual(checkVerifier.Reverse().ToArray());
}
public byte[] Hash(byte[] componentOne, byte[] componentTwo)
{
if (componentOne == null) throw new ArgumentNullException(nameof(componentOne));
if (componentTwo == null) throw new ArgumentNullException(nameof(componentTwo));
return Hash(componentOne.Concat(componentTwo).ToArray());
}
public byte[] Hash(byte[] bytes)
{
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
// done!
return verifier_bytes_padded;
//WoW expects non-secure SHA1 hashing. SRP6 is deprecated too. We need to do it anyway
using (SHA1 shaProvider = SHA1.Create())
{
return shaProvider.ComputeHash(bytes);
}
}
public static bool VerifySRP6Login(string username, string password, byte[] salt, byte[] verifier)
public byte[] CalculateVerifier(string username, string password, byte[] salt)
{
// 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);
using (SHA1 shaProvider = SHA1.Create())
{
if (BitConverter.IsLittleEndian)
{
return BigInteger.ModPow(
g,
new BigInteger(Hash(salt, Hash(Encoding.UTF8.GetBytes($"{username.ToUpper()}:{password.ToUpper()}")))),
N
).ToByteArray();
}
else
{
return BigInteger.ModPow(
g,
new BigInteger(Hash(salt, Hash(Encoding.UTF8.GetBytes($"{username.ToUpper()}:{password.ToUpper()}")).Reverse().ToArray())),
N
).ToByteArray();
}
}
}
}

25
Pages/Account.cshtml.cs

@ -39,6 +39,7 @@ namespace NightmareCoreWeb2.Pages @@ -39,6 +39,7 @@ namespace NightmareCoreWeb2.Pages
c.AtLogin |= (Character.AtLoginOptions)action;
}
c.SetAtLogin();
OnGet();
}
public void OnGet()
@ -46,10 +47,23 @@ namespace NightmareCoreWeb2.Pages @@ -46,10 +47,23 @@ namespace NightmareCoreWeb2.Pages
ViewData["Title"] = "Login";
AuthToken = Request.Cookies["AuthToken"];
Username = Request.Cookies["Username"];
if (!string.IsNullOrEmpty(Username))
if (!string.IsNullOrEmpty(AuthToken))
{
SetupAccount(Username);
conn.Open();
string sql = "select email from tokens.active_tokens where token=@token";
MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("token", AuthToken);
MySqlDataReader rdr = cmd.ExecuteReader();
string email = "";
while (rdr.Read())
{
try
{
email = rdr.GetString(0);
}
catch (Exception) { }
}
SetupAccount(email.Substring(0, email.IndexOf("@")));
}
}
public void SetupAccount(string Username)
@ -73,7 +87,6 @@ namespace NightmareCoreWeb2.Pages @@ -73,7 +87,6 @@ namespace NightmareCoreWeb2.Pages
public void OnPostLogin()
{
Console.WriteLine("Logging in!");
UserEmail = Request.Form["UserEmail"];
UserPassword = Request.Form["UserPassword"];
Username = UserEmail.Substring(0, UserEmail.IndexOf("@"));
@ -81,10 +94,10 @@ namespace NightmareCoreWeb2.Pages @@ -81,10 +94,10 @@ namespace NightmareCoreWeb2.Pages
if (a.AuthenticateAccount(UserPassword))
{
Response.Cookies.Append("Username", Username);
Response.Cookies.Append("AuthToken", a.Verifier);
Response.Cookies.Append("AuthToken", UserPassword);
Response.Redirect("/Account");
}
}

16
Pages/Index.cshtml.cs

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
using System.Collections.Generic;
using MySql.Data.MySqlClient;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace NightmareCoreWeb2.Pages
@ -110,5 +111,20 @@ namespace NightmareCoreWeb2.Pages @@ -110,5 +111,20 @@ namespace NightmareCoreWeb2.Pages
{
return false;
}
public ActionResult OnGetAlert() {
string ret = "";
if (this.OnlineCharacters.Count > 0) {
ret += "SERVERALERT:\nOnline Characters:\n";
foreach (Character c in OnlineCharacters) {
ret += $"{c.Username} as {c.Name}\n";
}
ret += "\n\r";
}
return Content(ret);
}
}
}

Loading…
Cancel
Save