diff --git a/Console/App.config b/Console/App.config
index 56efbc7..4bfa005 100644
--- a/Console/App.config
+++ b/Console/App.config
@@ -1,6 +1,6 @@
-
+
-
+
-
\ No newline at end of file
+
diff --git a/Console/Ed25519.cs b/Console/Ed25519.cs
new file mode 100644
index 0000000..20d1480
--- /dev/null
+++ b/Console/Ed25519.cs
@@ -0,0 +1,322 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Numerics;
+using System.Security.Cryptography;
+
+namespace Cryptographic
+{
+ /* Ported and refactored from Java to C# by Hans Wolff, 10/10/2013
+ * Released to the public domain
+ * /
+
+ /* Java code written by k3d3
+ * Source: https://github.com/k3d3/ed25519-java/blob/master/ed25519.java
+ * Released to the public domain
+ */
+
+ public class Ed25519
+ {
+ private static byte[] ComputeHash(byte[] m)
+ {
+ using (var sha512 = SHA512.Create()) // System.Security.Cryptography
+ {
+ return sha512.ComputeHash(m);
+ }
+ }
+
+ private static BigInteger ExpMod(BigInteger number, BigInteger exponent, BigInteger modulo)
+ {
+ BigInteger result = BigInteger.One;
+ BigInteger baseVal = number.Mod(modulo);
+
+ while (exponent > 0)
+ {
+ if (!exponent.IsEven)
+ {
+ result = (result * baseVal).Mod(modulo);
+ }
+ baseVal = (baseVal * baseVal).Mod(modulo);
+ exponent /= 2;
+ }
+
+ return result;
+ }
+
+
+ private static readonly Dictionary InverseCache = new Dictionary();
+
+ private static BigInteger Inv(BigInteger x)
+ {
+ if (!InverseCache.ContainsKey(x))
+ {
+ InverseCache[x] = ExpMod(x, Qm2, Q);
+ }
+ return InverseCache[x];
+ }
+
+ private static BigInteger RecoverX(BigInteger y)
+ {
+ BigInteger y2 = y * y;
+ BigInteger xx = (y2 - 1) * Inv(D * y2 + 1);
+ BigInteger x = ExpMod(xx, Qp3 / Eight, Q);
+ if (!(x * x - xx).Mod(Q).Equals(BigInteger.Zero))
+ {
+ x = (x * I).Mod(Q);
+ }
+ if (!x.IsEven)
+ {
+ x = Q - x;
+ }
+ return x;
+ }
+
+ private static Tuple Edwards(BigInteger px, BigInteger py, BigInteger qx, BigInteger qy)
+ {
+ BigInteger xx12 = px * qx;
+ BigInteger yy12 = py * qy;
+ BigInteger dtemp = D * xx12 * yy12;
+ BigInteger x3 = (px * qy + qx * py) * (Inv(1 + dtemp));
+ BigInteger y3 = (py * qy + xx12) * (Inv(1 - dtemp));
+ return new Tuple(x3.Mod(Q), y3.Mod(Q));
+ }
+
+ private static Tuple EdwardsSquare(BigInteger x, BigInteger y)
+ {
+ BigInteger xx = x * x;
+ BigInteger yy = y * y;
+ BigInteger dtemp = D * xx * yy;
+ BigInteger x3 = (2 * x * y) * (Inv(1 + dtemp));
+ BigInteger y3 = (yy + xx) * (Inv(1 - dtemp));
+ return new Tuple(x3.Mod(Q), y3.Mod(Q));
+ }
+ private static Tuple ScalarMul(Tuple point, BigInteger scalar)
+ {
+ var result = new Tuple(BigInteger.Zero, BigInteger.One); // Neutral element
+ var basePoint = point;
+
+ while (scalar > 0)
+ {
+ if (!scalar.IsEven) // If the current bit is set, add the base point to the result
+ {
+ result = Edwards(result.Item1, result.Item2, basePoint.Item1, basePoint.Item2);
+ }
+
+ basePoint = EdwardsSquare(basePoint.Item1, basePoint.Item2); // Double the point
+ scalar >>= 1; // Move to the next bit in the scalar
+ }
+
+ return result;
+ }
+
+ public static byte[] EncodeInt(BigInteger y)
+ {
+ byte[] nin = y.ToByteArray();
+ var nout = new byte[Math.Max(nin.Length, 32)];
+ Array.Copy(nin, nout, nin.Length);
+ return nout;
+ }
+
+ public static byte[] EncodePoint(BigInteger x, BigInteger y)
+ {
+ byte[] nout = EncodeInt(y);
+ nout[nout.Length - 1] |= (x.IsEven ? (byte)0 : (byte)0x80);
+ return nout;
+ }
+
+ private static int GetBit(byte[] h, int i)
+ {
+ return h[i / 8] >> (i % 8) & 1;
+ }
+
+ public static byte[] PublicKey(byte[] signingKey)
+ {
+ byte[] h = ComputeHash(signingKey);
+ BigInteger a = TwoPowBitLengthMinusTwo;
+ for (int i = 3; i < (BitLength - 2); i++)
+ {
+ var bit = GetBit(h, i);
+ if (bit != 0)
+ {
+ a += TwoPowCache[i];
+ }
+ }
+ var bigA = ScalarMul(B, a);
+ return EncodePoint(bigA.Item1, bigA.Item2);
+ }
+
+ private static BigInteger HashInt(byte[] m)
+ {
+ byte[] h = ComputeHash(m);
+ BigInteger hsum = BigInteger.Zero;
+ for (int i = 0; i < 2 * BitLength; i++)
+ {
+ var bit = GetBit(h, i);
+ if (bit != 0)
+ {
+ hsum += TwoPowCache[i];
+ }
+ }
+ return hsum;
+ }
+
+ public static byte[] Signature(byte[] message, byte[] signingKey, byte[] publicKey)
+ {
+ byte[] h = ComputeHash(signingKey);
+ BigInteger a = TwoPowBitLengthMinusTwo;
+ for (int i = 3; i < (BitLength - 2); i++)
+ {
+ var bit = GetBit(h, i);
+ if (bit != 0)
+ {
+ a += TwoPowCache[i];
+ }
+ }
+
+ BigInteger r;
+ using (var rsub = new MemoryStream((BitLength / 8) + message.Length))
+ {
+ rsub.Write(h, BitLength / 8, BitLength / 4 - BitLength / 8);
+ rsub.Write(message, 0, message.Length);
+ r = HashInt(rsub.ToArray());
+ }
+ var bigR = ScalarMul(B, r);
+ BigInteger s;
+ var encodedBigR = EncodePoint(bigR.Item1, bigR.Item2);
+ using (var stemp = new MemoryStream(32 + publicKey.Length + message.Length))
+ {
+ stemp.Write(encodedBigR, 0, encodedBigR.Length);
+ stemp.Write(publicKey, 0, publicKey.Length);
+ stemp.Write(message, 0, message.Length);
+ s = (r+ HashInt(stemp.ToArray()) * a).Mod(L);
+ }
+
+ using (var nout = new MemoryStream(64))
+ {
+ nout.Write(encodedBigR, 0, encodedBigR.Length);
+ var encodeInt = EncodeInt(s);
+ nout.Write(encodeInt, 0, encodeInt.Length);
+ return nout.ToArray();
+ }
+ }
+
+ private static bool IsOnCurve(BigInteger x, BigInteger y)
+ {
+ BigInteger xx = x * x;
+ BigInteger yy = y * y;
+ BigInteger dxxyy = D * yy * xx;
+ return (yy - xx - dxxyy - 1).Mod(Q).Equals(BigInteger.Zero);
+ }
+
+ private static BigInteger DecodeInt(byte[] s)
+ {
+ return new BigInteger(s) & Un;
+ }
+
+ private static Tuple DecodePoint(byte[] pointBytes)
+ {
+ BigInteger y = new BigInteger(pointBytes) & Un;
+ BigInteger x = RecoverX(y);
+ if ((x.IsEven ? 0 : 1) != GetBit(pointBytes, BitLength - 1))
+ {
+ x = Q - x;
+ }
+ var point = new Tuple(x, y);
+ if (!IsOnCurve(x, y)) throw new ArgumentException("Decoding point that is not on curve");
+ return point;
+ }
+
+ public static bool CheckValid(byte[] signature, byte[] message, byte[] publicKey)
+ {
+ Console.Write("."); // ... dots in console
+ if (signature.Length != BitLength / 4) throw new ArgumentException("Signature length is wrong");
+ if (publicKey.Length != BitLength / 8) throw new ArgumentException("Public key length is wrong");
+
+ byte[] rByte = Arrays.CopyOfRange(signature, 0, BitLength / 8);
+
+ var r = DecodePoint(rByte);
+ var a = DecodePoint(publicKey);
+
+ byte[] sByte = Arrays.CopyOfRange(signature, BitLength / 8, BitLength / 4);
+
+ BigInteger s = DecodeInt(sByte);
+ BigInteger h;
+
+ using (var stemp = new MemoryStream(32 + publicKey.Length + message.Length))
+ {
+ var encodePoint = EncodePoint(r.Item1, r.Item2);
+ stemp.Write(encodePoint, 0, encodePoint.Length);
+ stemp.Write(publicKey, 0, publicKey.Length);
+ stemp.Write(message, 0, message.Length);
+ h = HashInt(stemp.ToArray());
+ }
+
+ Console.Write("."); // ... dots in console
+ var ra = ScalarMul(B, s);
+ Console.Write("."); // ... dots in console
+ var ah = ScalarMul(a, h);
+ var rb = Edwards(r.Item1, r.Item2, ah.Item1, ah.Item2);
+ if (!ra.Item1.Equals(rb.Item1) || !ra.Item2.Equals(rb.Item2))
+ return false;
+ return true;
+ }
+
+ private const int BitLength = 256;
+
+ private static readonly BigInteger TwoPowBitLengthMinusTwo = BigInteger.Pow(2, BitLength - 2);
+ private static readonly BigInteger[] TwoPowCache = Enumerable.Range(0, 2 * BitLength).Select(i => BigInteger.Pow(2, i)).ToArray();
+
+ private static readonly BigInteger Q =
+ BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819949");
+
+ private static readonly BigInteger Qm2 =
+ BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819947");
+
+ private static readonly BigInteger Qp3 =
+ BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819952");
+
+ private static readonly BigInteger L =
+ BigInteger.Parse("7237005577332262213973186563042994240857116359379907606001950938285454250989");
+
+ private static readonly BigInteger D =
+ BigInteger.Parse("-4513249062541557337682894930092624173785641285191125241628941591882900924598840740");
+
+ private static readonly BigInteger I =
+ BigInteger.Parse("19681161376707505956807079304988542015446066515923890162744021073123829784752");
+
+ private static readonly BigInteger By =
+ BigInteger.Parse("46316835694926478169428394003475163141307993866256225615783033603165251855960");
+
+ private static readonly BigInteger Bx =
+ BigInteger.Parse("15112221349535400772501151409588531511454012693041857206046113283949847762202");
+
+ private static readonly Tuple B = new Tuple(Bx.Mod(Q), By.Mod(Q));
+
+ private static readonly BigInteger Un =
+ BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819967");
+
+ private static readonly BigInteger Two = new BigInteger(2);
+ private static readonly BigInteger Eight = new BigInteger(8);
+ }
+
+ internal static class Arrays
+ {
+ public static byte[] CopyOfRange(byte[] original, int from, int to)
+ {
+ int length = to - from;
+ var result = new byte[length];
+ Array.Copy(original, from, result, 0, length);
+ return result;
+ }
+ }
+
+ internal static class BigIntegerHelpers
+ {
+ public static BigInteger Mod(this BigInteger num, BigInteger modulo)
+ {
+ var result = num % modulo;
+ return result < 0 ? result + modulo : result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Console/KeyAuth.cs b/Console/KeyAuth.cs
index 5044222..88f39f4 100644
--- a/Console/KeyAuth.cs
+++ b/Console/KeyAuth.cs
@@ -12,41 +12,51 @@
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Threading;
-using System.Runtime.CompilerServices;
+using Cryptographic;
+using System.Runtime.InteropServices;
namespace KeyAuth
{
public class api
{
- public string name, ownerid, secret, version, path;
- public static long responseTime;
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern IntPtr GetCurrentProcess();
+
+ // Import the required Atom Table functions from kernel32.dll
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ private static extern ushort GlobalAddAtom(string lpString);
+
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ private static extern ushort GlobalFindAtom(string lpString);
+
+ public string name, ownerid, version, path, seed;
///
/// Set up your application credentials in order to use keyauth
///
/// Application Name
/// Your OwnerID, found in your account settings.
- /// Application Secret
/// Application Version, if version doesnt match it will open the download link you set up in your application settings and close the app, if empty the app will close
- public api(string name, string ownerid, string secret, string version, string path = null)
+ public api(string name, string ownerid, string version, string path = null)
{
- if (ownerid.Length != 10 || secret.Length != 64)
+ if (ownerid.Length != 10)
{
Process.Start("https://youtube.com/watch?v=RfDTdiBq4_o");
Process.Start("https://keyauth.cc/app/");
Thread.Sleep(2000);
error("Application not setup correctly. Please watch the YouTube video for setup.");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
this.name = name;
this.ownerid = ownerid;
- this.secret = secret;
-
this.version = version;
- this.path = path;
+ this.path = path;
}
#region structures
@@ -71,6 +81,9 @@ private class response_structure
[DataMember]
public string message { get; set; }
+ [DataMember]
+ public string ownerid { get; set; }
+
[DataMember]
public string download { get; set; }
@@ -141,20 +154,35 @@ private class app_data_structure
///
public void init()
{
- string sentKey = encryption.iv_key();
- enckey = sentKey + "-" + secret;
+ Random random = new Random();
+
+ // Generate a random length for the string (let's assume between 5 and 50 characters)
+ int length = random.Next(5, 51); // Min length: 5, Max length: 50
+
+ StringBuilder sb = new StringBuilder(length);
+
+ // Define the range of printable ASCII characters (32-126)
+ for (int i = 0; i < length; i++)
+ {
+ // Generate a random printable ASCII character
+ char randomChar = (char)random.Next(32, 127); // ASCII 32 to 126
+ sb.Append(randomChar);
+ }
+
+ seed = sb.ToString();
+ checkAtom();
+
var values_to_upload = new NameValueCollection
{
["type"] = "init",
["ver"] = version,
["hash"] = checksum(Process.GetCurrentProcess().MainModule.FileName),
- ["enckey"] = sentKey,
["name"] = name,
["ownerid"] = ownerid
};
- if (!string.IsNullOrEmpty(path))
- {
+ if (!string.IsNullOrEmpty(path))
+ {
values_to_upload.Add("token", File.ReadAllText(path));
values_to_upload.Add("thash", TokenHash(path));
}
@@ -164,28 +192,50 @@ public void init()
if (response == "KeyAuth_Invalid")
{
error("Application not found");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
+ if (json.ownerid == ownerid)
{
- if(json.newSession)
+ load_response_struct(json);
+ if (json.success)
+ {
+ sessionid = json.sessionid;
+ initialized = true;
+ }
+ else if (json.message == "invalidver")
{
- Thread.Sleep(100);
+ app_data.downloadLink = json.download;
}
- sessionid = json.sessionid;
- initialized = true;
}
- else if (json.message == "invalidver")
+ else
{
- app_data.downloadLink = json.download;
+ TerminateProcess(GetCurrentProcess(), 1);
}
+ }
+
+ void checkAtom()
+ {
+ Thread atomCheckThread = new Thread(() =>
+ {
+ while (true)
+ {
+ Thread.Sleep(60000); // give people 1 minute to login
+ ushort foundAtom = GlobalFindAtom(seed);
+ if (foundAtom == 0)
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
+ }
+ });
+
+ atomCheckThread.IsBackground = true; // Ensure the thread does not block program exit
+ atomCheckThread.Start();
}
- public static string TokenHash(string tokenPath)
+ public static string TokenHash(string tokenPath)
{
using (var sha256 = SHA256.Create())
{
@@ -204,7 +254,7 @@ public void CheckInit()
if (!initialized)
{
error("You must run the function KeyAuthApp.init(); first");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
}
@@ -261,9 +311,19 @@ public void register(string username, string pass, string key, string email = ""
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
- load_user_data(json.info);
+ if (json.ownerid == ownerid)
+ {
+ GlobalAddAtom(seed);
+ GlobalAddAtom(ownerid);
+
+ load_response_struct(json);
+ if (json.success)
+ load_user_data(json.info);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
///
/// Allow users to enter their account information and recieve an email to reset their password.
@@ -314,9 +374,19 @@ public void login(string username, string pass)
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
- load_user_data(json.info);
+ if (json.ownerid == ownerid)
+ {
+ GlobalAddAtom(seed);
+ GlobalAddAtom(ownerid);
+
+ load_response_struct(json);
+ if (json.success)
+ load_user_data(json.info);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
public void logout()
@@ -334,7 +404,14 @@ public void logout()
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
public void web_login()
@@ -403,26 +480,35 @@ public void web_login()
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
-
bool success = true;
-
- if (json.success)
+ if (json.ownerid == ownerid)
{
- load_user_data(json.info);
+ GlobalAddAtom(seed);
+ GlobalAddAtom(ownerid);
+
+ load_response_struct(json);
+
+ if (json.success)
+ {
+ load_user_data(json.info);
- responsepp.StatusCode = 420;
- responsepp.StatusDescription = "SHEESH";
+ responsepp.StatusCode = 420;
+ responsepp.StatusDescription = "SHEESH";
+ }
+ else
+ {
+ Console.WriteLine(json.message);
+ responsepp.StatusCode = (int)HttpStatusCode.OK;
+ responsepp.StatusDescription = json.message;
+ success = false;
+ }
}
else
{
- Console.WriteLine(json.message);
- responsepp.StatusCode = (int)HttpStatusCode.OK;
- responsepp.StatusDescription = json.message;
- success = false;
+ TerminateProcess(GetCurrentProcess(), 1);
}
- byte[] buffer = Encoding.UTF8.GetBytes("Whats up?");
+ byte[] buffer = Encoding.UTF8.GetBytes("Complete");
responsepp.ContentLength64 = buffer.Length;
Stream output = responsepp.OutputStream;
@@ -431,7 +517,7 @@ public void web_login()
listener.Stop();
if (!success)
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
@@ -498,8 +584,15 @@ public void upgrade(string username, string key)
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- json.success = false;
- load_response_struct(json);
+ if (json.ownerid == ownerid)
+ {
+ json.success = false;
+ load_response_struct(json);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
///
@@ -525,9 +618,20 @@ public void license(string key)
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
- load_user_data(json.info);
+
+ if (json.ownerid == ownerid)
+ {
+ GlobalAddAtom(seed);
+ GlobalAddAtom(ownerid);
+
+ load_response_struct(json);
+ if (json.success)
+ load_user_data(json.info);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
///
/// Checks if the current session is validated or not
@@ -547,7 +651,14 @@ public void check()
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
///
/// Change the data of an existing user variable, *User must be logged in*
@@ -571,7 +682,14 @@ public void setvar(string var, string data)
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
///
/// Gets the an existing user variable
@@ -594,9 +712,16 @@ public string getvar(string var)
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
- return json.response;
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ if (json.success)
+ return json.response;
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
return null;
}
///
@@ -618,7 +743,14 @@ public void ban(string reason = null)
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
///
/// Gets an existing global variable
@@ -641,9 +773,16 @@ public string var(string varid)
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
- return json.message;
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ if (json.success)
+ return json.message;
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
return null;
}
///
@@ -771,10 +910,19 @@ public bool checkblack()
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
- return true;
- return false;
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ if (json.success)
+ return true;
+ else
+ return false;
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
+ return true; // return yes blacklisted if the OwnerID is spoofed
}
///
/// Sends a request to a webhook that you've added in the dashboard in a safe way without it being showed for example a http debugger
@@ -803,9 +951,16 @@ public string webhook(string webid, string param, string body = "", string contt
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
- return json.response;
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ if (json.success)
+ return json.response;
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
return null;
}
///
@@ -911,7 +1066,6 @@ public static void LogEvent(string content)
content = RedactField(content, "sessionid");
content = RedactField(content, "ownerid");
content = RedactField(content, "app");
- content = RedactField(content, "secret");
content = RedactField(content, "version");
content = RedactField(content, "fileid");
content = RedactField(content, "webhooks");
@@ -963,7 +1117,7 @@ public static void error(string message)
RedirectStandardError = true,
UseShellExecute = false
});
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
private static string req(NameValueCollection post_data)
@@ -976,17 +1130,11 @@ private static string req(NameValueCollection post_data)
ServicePointManager.ServerCertificateValidationCallback += assertSSL;
- Stopwatch stopwatch = new Stopwatch();
- stopwatch.Start();
-
- var raw_response = client.UploadValues("https://keyauth.win/api/1.2/", post_data);
-
- stopwatch.Stop();
- responseTime = stopwatch.ElapsedMilliseconds;
+ var raw_response = client.UploadValues("https://keyauth.win/api/1.3/", post_data);
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
- sigCheck(Encoding.UTF8.GetString(raw_response), client.ResponseHeaders["signature"], post_data.Get(0));
+ sigCheck(Encoding.UTF8.GetString(raw_response), client.ResponseHeaders, post_data.Get(0));
LogEvent(Encoding.Default.GetString(raw_response) + "\n");
@@ -1001,12 +1149,12 @@ private static string req(NameValueCollection post_data)
case (HttpStatusCode)429: // client hit our rate limit
error("You're connecting too fast to loader, slow down.");
LogEvent("You're connecting too fast to loader, slow down.");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
return "";
default: // site won't resolve. you should use keyauth.uk domain since it's not blocked by any ISPs
error("Connection failure. Please try again, or contact us for help.");
LogEvent("Connection failure. Please try again, or contact us for help.");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
return "";
}
}
@@ -1023,28 +1171,61 @@ private static bool assertSSL(object sender, X509Certificate certificate, X509Ch
return true;
}
- private static void sigCheck(string resp, string signature, string type)
+ private static void sigCheck(string resp, WebHeaderCollection headers, string type)
{
if(type == "log" || type == "file") // log doesn't return a response.
{
return;
}
-
+
try
{
- string clientComputed = encryption.HashHMAC((type == "init") ? enckey.Substring(17, 64) : enckey, resp);
- if (!encryption.CheckStringsFixedTime(clientComputed, signature))
+ string signature = headers["x-signature-ed25519"];
+ string timestamp = headers["x-signature-timestamp"];
+
+ // Try to parse the input string to a long Unix timestamp
+ if (!long.TryParse(timestamp, out long unixTimestamp))
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
+
+ // Convert the Unix timestamp to a DateTime object (in UTC)
+ DateTime timestampTime = DateTimeOffset.FromUnixTimeSeconds(unixTimestamp).UtcDateTime;
+
+ // Get the current UTC time
+ DateTime currentTime = DateTime.UtcNow;
+
+ // Calculate the difference between the current time and the timestamp
+ TimeSpan timeDifference = currentTime - timestampTime;
+
+ // Check if the timestamp is within 15 seconds of the current time
+ if (timeDifference.TotalSeconds > 15)
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
+
+ var byteSig = encryption.str_to_byte_arr(signature);
+ var byteKey = encryption.str_to_byte_arr("5586b4bc69c7a4b487e4563a4cd96afd39140f919bd31cea7d1c6a1e8439422b");
+ // ... read the body from the request ...
+ // ... add the timestamp and convert it to a byte[] ...
+ string body = timestamp + resp;
+ var byteBody = Encoding.Default.GetBytes(body);
+
+ Console.Write(" Authenticating"); // there's also ... dots being created inside the CheckValid() function BELOW
+
+ bool signatureValid = Ed25519.CheckValid(byteSig, byteBody, byteKey); // the ... dots in the console are from this function!
+ if (!signatureValid)
{
error("Signature checksum failed. Request was tampered with or session ended most likely. & echo: & echo Response: " + resp);
LogEvent(resp + "\n");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
}
catch
{
error("Signature checksum failed. Request was tampered with or session ended most likely. & echo: & echo Response: " + resp);
LogEvent(resp + "\n");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
}
@@ -1122,6 +1303,12 @@ private void load_response_struct(response_structure data)
public static class encryption
{
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern IntPtr GetCurrentProcess();
+
public static string HashHMAC(string enckey, string resp)
{
byte[] key = Encoding.UTF8.GetBytes(enckey);
@@ -1151,25 +1338,10 @@ public static byte[] str_to_byte_arr(string hex)
catch
{
api.error("The session has ended, open program again.");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
return null;
}
}
-
- [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
- public static bool CheckStringsFixedTime(string str1, string str2)
- {
- if (str1.Length != str2.Length)
- {
- return false;
- }
- var result = 0;
- for (var i = 0; i < str1.Length; i++)
- {
- result |= str1[i] ^ str2[i];
- }
- return result == 0;
- }
public static string iv_key() =>
Guid.NewGuid().ToString().Substring(0, 16);
diff --git a/Console/Loader.csproj b/Console/Loader.csproj
index ca6625c..d5b83a1 100644
--- a/Console/Loader.csproj
+++ b/Console/Loader.csproj
@@ -8,7 +8,7 @@
Exe
Loader
Loader
- v4.7.2
+ v4.8
512
true
true
@@ -27,6 +27,7 @@
false
false
true
+
AnyCPU
@@ -54,11 +55,13 @@
+
+
diff --git a/Console/Program.cs b/Console/Program.cs
index 5570eae..2014845 100644
--- a/Console/Program.cs
+++ b/Console/Program.cs
@@ -1,6 +1,11 @@
using System;
using System.Diagnostics;
+using System.Linq;
using System.Net;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Text;
using System.Threading;
using System.Windows.Forms;
@@ -18,22 +23,26 @@ class Program
*/
public static api KeyAuthApp = new api(
- name: "",
- ownerid: "",
- secret: "",
- version: "1.0"/*,
- path: @"PathToCheckToken" NOTE: THE "@" IS IF THE TOKEN.TXT FILE IS IN THE SAME DIRECTORY AS THE .EXE*/
+ name: "", // Application Name
+ ownerid: "", // Owner ID
+ version: "" // Application Version /*
+ //path: @"Your_Path_Here" // (OPTIONAL) see tutorial here https://www.youtube.com/watch?v=I9rxt821gMk&t=1s
);
- // This will display how long it took to make a request in ms. The param "type" is for "login", "register", "init", etc... but that is optional, as well as this function. Ideally you can just put Console.WriteLine($"Request took {api.responseTime}"), but either works.
- // if you would like to use this method, simply put it in any function and pass the param ... ShowResponse("TypeHere");
- private void ShowResponse(string type)
- {
- Console.WriteLine($"It took {api.responseTime} ms to {type}");
- }
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern IntPtr GetCurrentProcess();
+
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ private static extern ushort GlobalFindAtom(string lpString);
static void Main(string[] args)
{
+
+ securityChecks();
+
Console.Title = "Loader";
Console.WriteLine("\n\n Connecting..");
KeyAuthApp.init();
@@ -44,7 +53,7 @@ static void Main(string[] args)
{
Console.WriteLine("\n Status: " + KeyAuthApp.response.message);
Thread.Sleep(1500);
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
Console.Write("\n [1] Login\n [2] Register\n [3] Upgrade\n [4] License key only\n [5] Forgot password\n\n Choose option: ");
@@ -81,7 +90,7 @@ static void Main(string[] args)
// don't proceed to app, user hasn't authenticated yet.
Console.WriteLine("\n Status: " + KeyAuthApp.response.message);
Thread.Sleep(2500);
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
break;
case 4:
Console.Write("\n\n Enter license: ");
@@ -97,12 +106,12 @@ static void Main(string[] args)
// don't proceed to app, user hasn't authenticated yet.
Console.WriteLine("\n Status: " + KeyAuthApp.response.message);
Thread.Sleep(2500);
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
break;
default:
Console.WriteLine("\n\n Invalid Selection");
Thread.Sleep(2500);
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
break; // no point in this other than to not get error from IDE
}
@@ -110,18 +119,20 @@ static void Main(string[] args)
{
Console.WriteLine("\n Status: " + KeyAuthApp.response.message);
Thread.Sleep(2500);
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
Console.WriteLine("\n Logged In!"); // at this point, the client has been authenticated. Put the code you want to run after here
+ if(string.IsNullOrEmpty(KeyAuthApp.response.message)) TerminateProcess(GetCurrentProcess(), 1);
+
// user data
Console.WriteLine("\n User data:");
Console.WriteLine(" Username: " + KeyAuthApp.user_data.username);
Console.WriteLine(" IP address: " + KeyAuthApp.user_data.ip);
Console.WriteLine(" Hardware-Id: " + KeyAuthApp.user_data.hwid);
Console.WriteLine(" Created at: " + UnixTimeToDateTime(long.Parse(KeyAuthApp.user_data.createdate)));
- if (!String.IsNullOrEmpty(KeyAuthApp.user_data.lastlogin)) // don't show last login on register since there is no last login at that point
+ if (!string.IsNullOrEmpty(KeyAuthApp.user_data.lastlogin)) // don't show last login on register since there is no last login at that point
Console.WriteLine(" Last login at: " + UnixTimeToDateTime(long.Parse(KeyAuthApp.user_data.lastlogin)));
Console.WriteLine(" Your subscription(s):");
for (var i = 0; i < KeyAuthApp.user_data.subscriptions.Count; i++)
@@ -130,7 +141,7 @@ static void Main(string[] args)
}
Console.WriteLine("\n Closing in five seconds...");
- Thread.Sleep(5000);
+ Thread.Sleep(-1);
Environment.Exit(0);
}
@@ -155,6 +166,52 @@ public static DateTime UnixTimeToDateTime(long unixtime)
return dtDateTime;
}
+ static void checkAtom()
+ {
+ Thread atomCheckThread = new Thread(() =>
+ {
+ while (true)
+ {
+ Thread.Sleep(60000); // give people 1 minute to login
+
+ ushort foundAtom = GlobalFindAtom(KeyAuthApp.ownerid);
+ if (foundAtom == 0)
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
+ }
+ });
+
+ atomCheckThread.IsBackground = true; // Ensure the thread does not block program exit
+ atomCheckThread.Start();
+ }
+
+ static void securityChecks()
+ {
+ // check if the Loader was executed by a different program
+ var frames = new StackTrace().GetFrames();
+ foreach (var frame in frames)
+ {
+ MethodBase method = frame.GetMethod();
+ if (method != null && method.DeclaringType?.Assembly != Assembly.GetExecutingAssembly())
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
+ }
+
+ // check if HarmonyLib is attempting to poison our program
+ var harmonyAssembly = AppDomain.CurrentDomain
+ .GetAssemblies()
+ .FirstOrDefault(a => a.GetName().Name == "0Harmony");
+
+ if (harmonyAssembly != null)
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
+
+ checkAtom();
+ }
+
static void autoUpdate()
{
if (KeyAuthApp.response.message == "invalidver")
diff --git a/Form/Ed25519.cs b/Form/Ed25519.cs
new file mode 100644
index 0000000..20d1480
--- /dev/null
+++ b/Form/Ed25519.cs
@@ -0,0 +1,322 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Numerics;
+using System.Security.Cryptography;
+
+namespace Cryptographic
+{
+ /* Ported and refactored from Java to C# by Hans Wolff, 10/10/2013
+ * Released to the public domain
+ * /
+
+ /* Java code written by k3d3
+ * Source: https://github.com/k3d3/ed25519-java/blob/master/ed25519.java
+ * Released to the public domain
+ */
+
+ public class Ed25519
+ {
+ private static byte[] ComputeHash(byte[] m)
+ {
+ using (var sha512 = SHA512.Create()) // System.Security.Cryptography
+ {
+ return sha512.ComputeHash(m);
+ }
+ }
+
+ private static BigInteger ExpMod(BigInteger number, BigInteger exponent, BigInteger modulo)
+ {
+ BigInteger result = BigInteger.One;
+ BigInteger baseVal = number.Mod(modulo);
+
+ while (exponent > 0)
+ {
+ if (!exponent.IsEven)
+ {
+ result = (result * baseVal).Mod(modulo);
+ }
+ baseVal = (baseVal * baseVal).Mod(modulo);
+ exponent /= 2;
+ }
+
+ return result;
+ }
+
+
+ private static readonly Dictionary InverseCache = new Dictionary();
+
+ private static BigInteger Inv(BigInteger x)
+ {
+ if (!InverseCache.ContainsKey(x))
+ {
+ InverseCache[x] = ExpMod(x, Qm2, Q);
+ }
+ return InverseCache[x];
+ }
+
+ private static BigInteger RecoverX(BigInteger y)
+ {
+ BigInteger y2 = y * y;
+ BigInteger xx = (y2 - 1) * Inv(D * y2 + 1);
+ BigInteger x = ExpMod(xx, Qp3 / Eight, Q);
+ if (!(x * x - xx).Mod(Q).Equals(BigInteger.Zero))
+ {
+ x = (x * I).Mod(Q);
+ }
+ if (!x.IsEven)
+ {
+ x = Q - x;
+ }
+ return x;
+ }
+
+ private static Tuple Edwards(BigInteger px, BigInteger py, BigInteger qx, BigInteger qy)
+ {
+ BigInteger xx12 = px * qx;
+ BigInteger yy12 = py * qy;
+ BigInteger dtemp = D * xx12 * yy12;
+ BigInteger x3 = (px * qy + qx * py) * (Inv(1 + dtemp));
+ BigInteger y3 = (py * qy + xx12) * (Inv(1 - dtemp));
+ return new Tuple(x3.Mod(Q), y3.Mod(Q));
+ }
+
+ private static Tuple EdwardsSquare(BigInteger x, BigInteger y)
+ {
+ BigInteger xx = x * x;
+ BigInteger yy = y * y;
+ BigInteger dtemp = D * xx * yy;
+ BigInteger x3 = (2 * x * y) * (Inv(1 + dtemp));
+ BigInteger y3 = (yy + xx) * (Inv(1 - dtemp));
+ return new Tuple(x3.Mod(Q), y3.Mod(Q));
+ }
+ private static Tuple ScalarMul(Tuple point, BigInteger scalar)
+ {
+ var result = new Tuple(BigInteger.Zero, BigInteger.One); // Neutral element
+ var basePoint = point;
+
+ while (scalar > 0)
+ {
+ if (!scalar.IsEven) // If the current bit is set, add the base point to the result
+ {
+ result = Edwards(result.Item1, result.Item2, basePoint.Item1, basePoint.Item2);
+ }
+
+ basePoint = EdwardsSquare(basePoint.Item1, basePoint.Item2); // Double the point
+ scalar >>= 1; // Move to the next bit in the scalar
+ }
+
+ return result;
+ }
+
+ public static byte[] EncodeInt(BigInteger y)
+ {
+ byte[] nin = y.ToByteArray();
+ var nout = new byte[Math.Max(nin.Length, 32)];
+ Array.Copy(nin, nout, nin.Length);
+ return nout;
+ }
+
+ public static byte[] EncodePoint(BigInteger x, BigInteger y)
+ {
+ byte[] nout = EncodeInt(y);
+ nout[nout.Length - 1] |= (x.IsEven ? (byte)0 : (byte)0x80);
+ return nout;
+ }
+
+ private static int GetBit(byte[] h, int i)
+ {
+ return h[i / 8] >> (i % 8) & 1;
+ }
+
+ public static byte[] PublicKey(byte[] signingKey)
+ {
+ byte[] h = ComputeHash(signingKey);
+ BigInteger a = TwoPowBitLengthMinusTwo;
+ for (int i = 3; i < (BitLength - 2); i++)
+ {
+ var bit = GetBit(h, i);
+ if (bit != 0)
+ {
+ a += TwoPowCache[i];
+ }
+ }
+ var bigA = ScalarMul(B, a);
+ return EncodePoint(bigA.Item1, bigA.Item2);
+ }
+
+ private static BigInteger HashInt(byte[] m)
+ {
+ byte[] h = ComputeHash(m);
+ BigInteger hsum = BigInteger.Zero;
+ for (int i = 0; i < 2 * BitLength; i++)
+ {
+ var bit = GetBit(h, i);
+ if (bit != 0)
+ {
+ hsum += TwoPowCache[i];
+ }
+ }
+ return hsum;
+ }
+
+ public static byte[] Signature(byte[] message, byte[] signingKey, byte[] publicKey)
+ {
+ byte[] h = ComputeHash(signingKey);
+ BigInteger a = TwoPowBitLengthMinusTwo;
+ for (int i = 3; i < (BitLength - 2); i++)
+ {
+ var bit = GetBit(h, i);
+ if (bit != 0)
+ {
+ a += TwoPowCache[i];
+ }
+ }
+
+ BigInteger r;
+ using (var rsub = new MemoryStream((BitLength / 8) + message.Length))
+ {
+ rsub.Write(h, BitLength / 8, BitLength / 4 - BitLength / 8);
+ rsub.Write(message, 0, message.Length);
+ r = HashInt(rsub.ToArray());
+ }
+ var bigR = ScalarMul(B, r);
+ BigInteger s;
+ var encodedBigR = EncodePoint(bigR.Item1, bigR.Item2);
+ using (var stemp = new MemoryStream(32 + publicKey.Length + message.Length))
+ {
+ stemp.Write(encodedBigR, 0, encodedBigR.Length);
+ stemp.Write(publicKey, 0, publicKey.Length);
+ stemp.Write(message, 0, message.Length);
+ s = (r+ HashInt(stemp.ToArray()) * a).Mod(L);
+ }
+
+ using (var nout = new MemoryStream(64))
+ {
+ nout.Write(encodedBigR, 0, encodedBigR.Length);
+ var encodeInt = EncodeInt(s);
+ nout.Write(encodeInt, 0, encodeInt.Length);
+ return nout.ToArray();
+ }
+ }
+
+ private static bool IsOnCurve(BigInteger x, BigInteger y)
+ {
+ BigInteger xx = x * x;
+ BigInteger yy = y * y;
+ BigInteger dxxyy = D * yy * xx;
+ return (yy - xx - dxxyy - 1).Mod(Q).Equals(BigInteger.Zero);
+ }
+
+ private static BigInteger DecodeInt(byte[] s)
+ {
+ return new BigInteger(s) & Un;
+ }
+
+ private static Tuple DecodePoint(byte[] pointBytes)
+ {
+ BigInteger y = new BigInteger(pointBytes) & Un;
+ BigInteger x = RecoverX(y);
+ if ((x.IsEven ? 0 : 1) != GetBit(pointBytes, BitLength - 1))
+ {
+ x = Q - x;
+ }
+ var point = new Tuple(x, y);
+ if (!IsOnCurve(x, y)) throw new ArgumentException("Decoding point that is not on curve");
+ return point;
+ }
+
+ public static bool CheckValid(byte[] signature, byte[] message, byte[] publicKey)
+ {
+ Console.Write("."); // ... dots in console
+ if (signature.Length != BitLength / 4) throw new ArgumentException("Signature length is wrong");
+ if (publicKey.Length != BitLength / 8) throw new ArgumentException("Public key length is wrong");
+
+ byte[] rByte = Arrays.CopyOfRange(signature, 0, BitLength / 8);
+
+ var r = DecodePoint(rByte);
+ var a = DecodePoint(publicKey);
+
+ byte[] sByte = Arrays.CopyOfRange(signature, BitLength / 8, BitLength / 4);
+
+ BigInteger s = DecodeInt(sByte);
+ BigInteger h;
+
+ using (var stemp = new MemoryStream(32 + publicKey.Length + message.Length))
+ {
+ var encodePoint = EncodePoint(r.Item1, r.Item2);
+ stemp.Write(encodePoint, 0, encodePoint.Length);
+ stemp.Write(publicKey, 0, publicKey.Length);
+ stemp.Write(message, 0, message.Length);
+ h = HashInt(stemp.ToArray());
+ }
+
+ Console.Write("."); // ... dots in console
+ var ra = ScalarMul(B, s);
+ Console.Write("."); // ... dots in console
+ var ah = ScalarMul(a, h);
+ var rb = Edwards(r.Item1, r.Item2, ah.Item1, ah.Item2);
+ if (!ra.Item1.Equals(rb.Item1) || !ra.Item2.Equals(rb.Item2))
+ return false;
+ return true;
+ }
+
+ private const int BitLength = 256;
+
+ private static readonly BigInteger TwoPowBitLengthMinusTwo = BigInteger.Pow(2, BitLength - 2);
+ private static readonly BigInteger[] TwoPowCache = Enumerable.Range(0, 2 * BitLength).Select(i => BigInteger.Pow(2, i)).ToArray();
+
+ private static readonly BigInteger Q =
+ BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819949");
+
+ private static readonly BigInteger Qm2 =
+ BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819947");
+
+ private static readonly BigInteger Qp3 =
+ BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819952");
+
+ private static readonly BigInteger L =
+ BigInteger.Parse("7237005577332262213973186563042994240857116359379907606001950938285454250989");
+
+ private static readonly BigInteger D =
+ BigInteger.Parse("-4513249062541557337682894930092624173785641285191125241628941591882900924598840740");
+
+ private static readonly BigInteger I =
+ BigInteger.Parse("19681161376707505956807079304988542015446066515923890162744021073123829784752");
+
+ private static readonly BigInteger By =
+ BigInteger.Parse("46316835694926478169428394003475163141307993866256225615783033603165251855960");
+
+ private static readonly BigInteger Bx =
+ BigInteger.Parse("15112221349535400772501151409588531511454012693041857206046113283949847762202");
+
+ private static readonly Tuple B = new Tuple(Bx.Mod(Q), By.Mod(Q));
+
+ private static readonly BigInteger Un =
+ BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819967");
+
+ private static readonly BigInteger Two = new BigInteger(2);
+ private static readonly BigInteger Eight = new BigInteger(8);
+ }
+
+ internal static class Arrays
+ {
+ public static byte[] CopyOfRange(byte[] original, int from, int to)
+ {
+ int length = to - from;
+ var result = new byte[length];
+ Array.Copy(original, from, result, 0, length);
+ return result;
+ }
+ }
+
+ internal static class BigIntegerHelpers
+ {
+ public static BigInteger Mod(this BigInteger num, BigInteger modulo)
+ {
+ var result = num % modulo;
+ return result < 0 ? result + modulo : result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Form/KeyAuth.cs b/Form/KeyAuth.cs
index b930669..88f39f4 100644
--- a/Form/KeyAuth.cs
+++ b/Form/KeyAuth.cs
@@ -12,41 +12,51 @@
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Threading;
-using System.Runtime.CompilerServices;
+using Cryptographic;
+using System.Runtime.InteropServices;
namespace KeyAuth
{
public class api
{
- public string name, ownerid, secret, version, path;
- public static long responseTime;
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern IntPtr GetCurrentProcess();
+
+ // Import the required Atom Table functions from kernel32.dll
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ private static extern ushort GlobalAddAtom(string lpString);
+
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ private static extern ushort GlobalFindAtom(string lpString);
+
+ public string name, ownerid, version, path, seed;
///
/// Set up your application credentials in order to use keyauth
///
/// Application Name
/// Your OwnerID, found in your account settings.
- /// Application Secret
/// Application Version, if version doesnt match it will open the download link you set up in your application settings and close the app, if empty the app will close
- public api(string name, string ownerid, string secret, string version, string path = null)
+ public api(string name, string ownerid, string version, string path = null)
{
- if (ownerid.Length != 10 || secret.Length != 64)
+ if (ownerid.Length != 10)
{
Process.Start("https://youtube.com/watch?v=RfDTdiBq4_o");
Process.Start("https://keyauth.cc/app/");
Thread.Sleep(2000);
error("Application not setup correctly. Please watch the YouTube video for setup.");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
this.name = name;
this.ownerid = ownerid;
- this.secret = secret;
-
this.version = version;
- this.path = path;
+ this.path = path;
}
#region structures
@@ -71,6 +81,9 @@ private class response_structure
[DataMember]
public string message { get; set; }
+ [DataMember]
+ public string ownerid { get; set; }
+
[DataMember]
public string download { get; set; }
@@ -141,62 +154,98 @@ private class app_data_structure
///
public void init()
{
- string sentKey = encryption.iv_key();
- enckey = sentKey + "-" + secret;
+ Random random = new Random();
+
+ // Generate a random length for the string (let's assume between 5 and 50 characters)
+ int length = random.Next(5, 51); // Min length: 5, Max length: 50
+
+ StringBuilder sb = new StringBuilder(length);
+
+ // Define the range of printable ASCII characters (32-126)
+ for (int i = 0; i < length; i++)
+ {
+ // Generate a random printable ASCII character
+ char randomChar = (char)random.Next(32, 127); // ASCII 32 to 126
+ sb.Append(randomChar);
+ }
+
+ seed = sb.ToString();
+ checkAtom();
+
var values_to_upload = new NameValueCollection
{
["type"] = "init",
["ver"] = version,
["hash"] = checksum(Process.GetCurrentProcess().MainModule.FileName),
- ["enckey"] = sentKey,
["name"] = name,
["ownerid"] = ownerid
};
- if (!string.IsNullOrEmpty(path))
- {
+ if (!string.IsNullOrEmpty(path))
+ {
values_to_upload.Add("token", File.ReadAllText(path));
values_to_upload.Add("thash", TokenHash(path));
- }
+ }
var response = req(values_to_upload);
if (response == "KeyAuth_Invalid")
{
error("Application not found");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
+ if (json.ownerid == ownerid)
{
- if (json.newSession)
+ load_response_struct(json);
+ if (json.success)
+ {
+ sessionid = json.sessionid;
+ initialized = true;
+ }
+ else if (json.message == "invalidver")
{
- Thread.Sleep(100);
+ app_data.downloadLink = json.download;
}
- sessionid = json.sessionid;
- initialized = true;
}
- else if (json.message == "invalidver")
+ else
{
- app_data.downloadLink = json.download;
+ TerminateProcess(GetCurrentProcess(), 1);
}
+ }
+
+ void checkAtom()
+ {
+ Thread atomCheckThread = new Thread(() =>
+ {
+ while (true)
+ {
+ Thread.Sleep(60000); // give people 1 minute to login
+ ushort foundAtom = GlobalFindAtom(seed);
+ if (foundAtom == 0)
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
+ }
+ });
+
+ atomCheckThread.IsBackground = true; // Ensure the thread does not block program exit
+ atomCheckThread.Start();
}
public static string TokenHash(string tokenPath)
{
- using (var sha256 = SHA256.Create())
- {
+ using (var sha256 = SHA256.Create())
+ {
using (var s = File.OpenRead(tokenPath))
{
- byte[] bytes = sha256.ComputeHash(s);
- return BitConverter.ToString(bytes).Replace("-", string.Empty);
+ byte[] bytes = sha256.ComputeHash(s);
+ return BitConverter.ToString(bytes).Replace("-", string.Empty);
}
}
- }
-
+ }
///
/// Checks if Keyauth is been Initalized
///
@@ -205,7 +254,7 @@ public void CheckInit()
if (!initialized)
{
error("You must run the function KeyAuthApp.init(); first");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
}
@@ -214,7 +263,7 @@ public void CheckInit()
///
/// Subscription Number
/// You can choose between Days,Hours,Months
- public string expirydaysleft(string Type, int subscription)
+ public string expirydaysleft(string Type,int subscription)
{
CheckInit();
@@ -262,9 +311,19 @@ public void register(string username, string pass, string key, string email = ""
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
- load_user_data(json.info);
+ if (json.ownerid == ownerid)
+ {
+ GlobalAddAtom(seed);
+ GlobalAddAtom(ownerid);
+
+ load_response_struct(json);
+ if (json.success)
+ load_user_data(json.info);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
///
/// Allow users to enter their account information and recieve an email to reset their password.
@@ -315,12 +374,22 @@ public void login(string username, string pass)
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
- load_user_data(json.info);
+ if (json.ownerid == ownerid)
+ {
+ GlobalAddAtom(seed);
+ GlobalAddAtom(ownerid);
+
+ load_response_struct(json);
+ if (json.success)
+ load_user_data(json.info);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
- public void logout()
+ public void logout()
{
CheckInit();
@@ -335,7 +404,14 @@ public void logout()
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
public void web_login()
@@ -346,7 +422,7 @@ public void web_login()
string datastore, datastore2, outputten;
- start:
+ start:
HttpListener listener = new HttpListener();
@@ -404,26 +480,35 @@ public void web_login()
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
-
bool success = true;
-
- if (json.success)
+ if (json.ownerid == ownerid)
{
- load_user_data(json.info);
+ GlobalAddAtom(seed);
+ GlobalAddAtom(ownerid);
+
+ load_response_struct(json);
- responsepp.StatusCode = 420;
- responsepp.StatusDescription = "SHEESH";
+ if (json.success)
+ {
+ load_user_data(json.info);
+
+ responsepp.StatusCode = 420;
+ responsepp.StatusDescription = "SHEESH";
+ }
+ else
+ {
+ Console.WriteLine(json.message);
+ responsepp.StatusCode = (int)HttpStatusCode.OK;
+ responsepp.StatusDescription = json.message;
+ success = false;
+ }
}
else
{
- Console.WriteLine(json.message);
- responsepp.StatusCode = (int)HttpStatusCode.OK;
- responsepp.StatusDescription = json.message;
- success = false;
+ TerminateProcess(GetCurrentProcess(), 1);
}
- byte[] buffer = Encoding.UTF8.GetBytes("Whats up?");
+ byte[] buffer = Encoding.UTF8.GetBytes("Complete");
responsepp.ContentLength64 = buffer.Length;
Stream output = responsepp.OutputStream;
@@ -432,7 +517,7 @@ public void web_login()
listener.Stop();
if (!success)
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
@@ -499,8 +584,15 @@ public void upgrade(string username, string key)
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- json.success = false;
- load_response_struct(json);
+ if (json.ownerid == ownerid)
+ {
+ json.success = false;
+ load_response_struct(json);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
///
@@ -526,9 +618,20 @@ public void license(string key)
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
- load_user_data(json.info);
+
+ if (json.ownerid == ownerid)
+ {
+ GlobalAddAtom(seed);
+ GlobalAddAtom(ownerid);
+
+ load_response_struct(json);
+ if (json.success)
+ load_user_data(json.info);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
///
/// Checks if the current session is validated or not
@@ -548,7 +651,14 @@ public void check()
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
///
/// Change the data of an existing user variable, *User must be logged in*
@@ -572,7 +682,14 @@ public void setvar(string var, string data)
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
///
/// Gets the an existing user variable
@@ -595,9 +712,16 @@ public string getvar(string var)
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
- return json.response;
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ if (json.success)
+ return json.response;
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
return null;
}
///
@@ -619,7 +743,14 @@ public void ban(string reason = null)
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
}
///
/// Gets an existing global variable
@@ -642,9 +773,16 @@ public string var(string varid)
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
- return json.message;
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ if (json.success)
+ return json.message;
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
return null;
}
///
@@ -772,10 +910,19 @@ public bool checkblack()
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
- return true;
- return false;
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ if (json.success)
+ return true;
+ else
+ return false;
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
+ return true; // return yes blacklisted if the OwnerID is spoofed
}
///
/// Sends a request to a webhook that you've added in the dashboard in a safe way without it being showed for example a http debugger
@@ -804,9 +951,16 @@ public string webhook(string webid, string param, string body = "", string contt
var response = req(values_to_upload);
var json = response_decoder.string_to_generic(response);
- load_response_struct(json);
- if (json.success)
- return json.response;
+ if (json.ownerid == ownerid)
+ {
+ load_response_struct(json);
+ if (json.success)
+ return json.response;
+ }
+ else
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
return null;
}
///
@@ -893,7 +1047,7 @@ public static string checksum(string filename)
return result;
}
- public static void LogEvent(string content)
+ public static void LogEvent(string content)
{
string exeName = Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Location);
@@ -912,7 +1066,6 @@ public static void LogEvent(string content)
content = RedactField(content, "sessionid");
content = RedactField(content, "ownerid");
content = RedactField(content, "app");
- content = RedactField(content, "secret");
content = RedactField(content, "version");
content = RedactField(content, "fileid");
content = RedactField(content, "webhooks");
@@ -931,6 +1084,7 @@ public static void LogEvent(string content)
private static string RedactField(string content, string fieldName)
{
+ // Basic pattern matching to replace values of sensitive fields
string pattern = $"\"{fieldName}\":\"[^\"]*\"";
string replacement = $"\"{fieldName}\":\"REDACTED\"";
@@ -955,7 +1109,7 @@ public static void error(string message)
}
File.AppendAllText(file, DateTime.Now + $" > {message}" + Environment.NewLine);
-
+
Process.Start(new ProcessStartInfo("cmd.exe", $"/c start cmd /C \"color b && title Error && echo {message} && timeout /t 5\"")
{
CreateNoWindow = true,
@@ -963,9 +1117,9 @@ public static void error(string message)
RedirectStandardError = true,
UseShellExecute = false
});
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
-
+
private static string req(NameValueCollection post_data)
{
try
@@ -976,17 +1130,11 @@ private static string req(NameValueCollection post_data)
ServicePointManager.ServerCertificateValidationCallback += assertSSL;
- Stopwatch stopwatch = new Stopwatch();
- stopwatch.Start();
-
- var raw_response = client.UploadValues("https://keyauth.win/api/1.2/", post_data);
-
- stopwatch.Stop();
- responseTime = stopwatch.ElapsedMilliseconds;
+ var raw_response = client.UploadValues("https://keyauth.win/api/1.3/", post_data);
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
- sigCheck(Encoding.UTF8.GetString(raw_response), client.ResponseHeaders["signature"], post_data.Get(0));
+ sigCheck(Encoding.UTF8.GetString(raw_response), client.ResponseHeaders, post_data.Get(0));
LogEvent(Encoding.Default.GetString(raw_response) + "\n");
@@ -1001,19 +1149,19 @@ private static string req(NameValueCollection post_data)
case (HttpStatusCode)429: // client hit our rate limit
error("You're connecting too fast to loader, slow down.");
LogEvent("You're connecting too fast to loader, slow down.");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
return "";
default: // site won't resolve. you should use keyauth.uk domain since it's not blocked by any ISPs
error("Connection failure. Please try again, or contact us for help.");
LogEvent("Connection failure. Please try again, or contact us for help.");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
return "";
}
}
}
private static bool assertSSL(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
- {
+ {
if ((!certificate.Issuer.Contains("Google Trust Services") && !certificate.Issuer.Contains("Let's Encrypt")) || sslPolicyErrors != SslPolicyErrors.None)
{
error("SSL assertion fail, make sure you're not debugging Network. Disable internet firewall on router if possible. & echo: & echo If not, ask the developer of the program to use custom domains to fix this.");
@@ -1023,28 +1171,61 @@ private static bool assertSSL(object sender, X509Certificate certificate, X509Ch
return true;
}
- private static void sigCheck(string resp, string signature, string type)
+ private static void sigCheck(string resp, WebHeaderCollection headers, string type)
{
- if (type == "log" || type == "file") // log doesn't return a response.
+ if(type == "log" || type == "file") // log doesn't return a response.
{
return;
}
try
{
- string clientComputed = encryption.HashHMAC((type == "init") ? enckey.Substring(17, 64) : enckey, resp);
- if (!encryption.CheckStringsFixedTime(clientComputed, signature))
+ string signature = headers["x-signature-ed25519"];
+ string timestamp = headers["x-signature-timestamp"];
+
+ // Try to parse the input string to a long Unix timestamp
+ if (!long.TryParse(timestamp, out long unixTimestamp))
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
+
+ // Convert the Unix timestamp to a DateTime object (in UTC)
+ DateTime timestampTime = DateTimeOffset.FromUnixTimeSeconds(unixTimestamp).UtcDateTime;
+
+ // Get the current UTC time
+ DateTime currentTime = DateTime.UtcNow;
+
+ // Calculate the difference between the current time and the timestamp
+ TimeSpan timeDifference = currentTime - timestampTime;
+
+ // Check if the timestamp is within 15 seconds of the current time
+ if (timeDifference.TotalSeconds > 15)
+ {
+ TerminateProcess(GetCurrentProcess(), 1);
+ }
+
+ var byteSig = encryption.str_to_byte_arr(signature);
+ var byteKey = encryption.str_to_byte_arr("5586b4bc69c7a4b487e4563a4cd96afd39140f919bd31cea7d1c6a1e8439422b");
+ // ... read the body from the request ...
+ // ... add the timestamp and convert it to a byte[] ...
+ string body = timestamp + resp;
+ var byteBody = Encoding.Default.GetBytes(body);
+
+ Console.Write(" Authenticating"); // there's also ... dots being created inside the CheckValid() function BELOW
+
+ bool signatureValid = Ed25519.CheckValid(byteSig, byteBody, byteKey); // the ... dots in the console are from this function!
+ if (!signatureValid)
{
error("Signature checksum failed. Request was tampered with or session ended most likely. & echo: & echo Response: " + resp);
LogEvent(resp + "\n");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
}
catch
{
error("Signature checksum failed. Request was tampered with or session ended most likely. & echo: & echo Response: " + resp);
LogEvent(resp + "\n");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
}
}
@@ -1122,6 +1303,12 @@ private void load_response_struct(response_structure data)
public static class encryption
{
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern IntPtr GetCurrentProcess();
+
public static string HashHMAC(string enckey, string resp)
{
byte[] key = Encoding.UTF8.GetBytes(enckey);
@@ -1151,26 +1338,11 @@ public static byte[] str_to_byte_arr(string hex)
catch
{
api.error("The session has ended, open program again.");
- Environment.Exit(0);
+ TerminateProcess(GetCurrentProcess(), 1);
return null;
}
}
- [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
- public static bool CheckStringsFixedTime(string str1, string str2)
- {
- if (str1.Length != str2.Length)
- {
- return false;
- }
- var result = 0;
- for (var i = 0; i < str1.Length; i++)
- {
- result |= str1[i] ^ str2[i];
- }
- return result == 0;
- }
-
public static string iv_key() =>
Guid.NewGuid().ToString().Substring(0, 16);
}
diff --git a/Form/Loader.csproj b/Form/Loader.csproj
index 605c715..04891b5 100644
--- a/Form/Loader.csproj
+++ b/Form/Loader.csproj
@@ -39,6 +39,7 @@
+
@@ -47,6 +48,7 @@
+
Form
diff --git a/Form/Login.cs b/Form/Login.cs
index 2a8aeba..a440a60 100644
--- a/Form/Login.cs
+++ b/Form/Login.cs
@@ -20,19 +20,10 @@ public partial class Login : Form
public static api KeyAuthApp = new api(
name: "", // Application Name
ownerid: "", // Owner ID
- secret: "", // Application Secret
version: "" // Application Version /*
//path: @"Your_Path_Here" // (OPTIONAL) see tutorial here https://www.youtube.com/watch?v=I9rxt821gMk&t=1s
);
- //This will display how long it took to make a request in ms. The param "type" is for "login", "register", "init", etc... but that is optional, as well as this function. Ideally you can just put a label or MessageBox.Show($"Request took {api.responseTime}"), but either works.
- // if you would like to use this method, simply put it in any function and pass the param ... ShowResponse("TypeHere");
- private void ShowResponse(string type)
- {
- //responseTimeLbl.Text = $"It took {api.responseTime} ms to {type}"; // you need to create a label called responseTimeLbl to display to a label.
- MessageBox.Show($"It took {api.responseTime} msg to {type}");
- }
-
public Login()
{
InitializeComponent();
diff --git a/Form/bin/Debug/Siticone.UI.dll b/Form/bin/Debug/Siticone.UI.dll
deleted file mode 100644
index 7e25dd8..0000000
Binary files a/Form/bin/Debug/Siticone.UI.dll and /dev/null differ