mirror of
https://github.com/gnh1201/welsonjs.git
synced 2025-05-09 05:06:04 +00:00
Add TFA (TOTP) endpoint
This commit is contained in:
parent
8190c80f1a
commit
54af38b6b6
|
@ -125,6 +125,14 @@ namespace WelsonJS.Launcher.Tools
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Serve TFA request
|
||||||
|
const string tfaPrefix = "tfa/";
|
||||||
|
if (path.StartsWith(tfaPrefix, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
ServeTfaRequest(context, path.Substring(tfaPrefix.Length - 1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Serve a resource
|
// Serve a resource
|
||||||
ServeResource(context, GetResource(_resourceName), "text/html");
|
ServeResource(context, GetResource(_resourceName), "text/html");
|
||||||
}
|
}
|
||||||
|
@ -251,6 +259,24 @@ namespace WelsonJS.Launcher.Tools
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ServeTfaRequest(HttpListenerContext context, string endpoint)
|
||||||
|
{
|
||||||
|
Tfa _tfa = new Tfa();
|
||||||
|
|
||||||
|
if (endpoint.Equals("/pubkey"))
|
||||||
|
{
|
||||||
|
ServeResource(context, _tfa.GetPubKey(), "text/plain", 200);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServeResource(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ServeResource(HttpListenerContext context)
|
||||||
|
{
|
||||||
|
ServeResource(context, "<error>Not Found</error>", "application/xml", 404);
|
||||||
|
}
|
||||||
|
|
||||||
private void ServeResource(HttpListenerContext context, byte[] data, string mimeType = "text/html", int statusCode = 200)
|
private void ServeResource(HttpListenerContext context, byte[] data, string mimeType = "text/html", int statusCode = 200)
|
||||||
{
|
{
|
||||||
string xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
|
string xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
|
||||||
|
|
65
WelsonJS.Toolkit/WelsonJS.Launcher/Tools/Tfa.cs
Normal file
65
WelsonJS.Toolkit/WelsonJS.Launcher/Tools/Tfa.cs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace WelsonJS.Launcher.Tools
|
||||||
|
{
|
||||||
|
public class Tfa
|
||||||
|
{
|
||||||
|
private const string Base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||||
|
|
||||||
|
public int GetOtp(string key)
|
||||||
|
{
|
||||||
|
byte[] binaryKey = DecodeBase32(key.Replace(" ", ""));
|
||||||
|
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds() / 30;
|
||||||
|
byte[] timestampBytes = BitConverter.GetBytes(timestamp);
|
||||||
|
Array.Reverse(timestampBytes); // Ensure big-endian order
|
||||||
|
|
||||||
|
using (var hmac = new HMACSHA1(binaryKey))
|
||||||
|
{
|
||||||
|
byte[] hash = hmac.ComputeHash(timestampBytes);
|
||||||
|
int offset = hash[hash.Length - 1] & 0xF;
|
||||||
|
|
||||||
|
int otp = ((hash[offset] & 0x7F) << 24) |
|
||||||
|
((hash[offset + 1] & 0xFF) << 16) |
|
||||||
|
((hash[offset + 2] & 0xFF) << 8) |
|
||||||
|
(hash[offset + 3] & 0xFF);
|
||||||
|
|
||||||
|
return otp % 1000000; // Ensure 6-digit OTP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetPubKey()
|
||||||
|
{
|
||||||
|
var rand = new Random();
|
||||||
|
var key = new char[16];
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
key[i] = Base32Chars[rand.Next(Base32Chars.Length)];
|
||||||
|
}
|
||||||
|
return string.Join(" ", Enumerable.Range(0, 4).Select(i => new string(key, i * 4, 4)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] DecodeBase32(string key)
|
||||||
|
{
|
||||||
|
int buffer = 0, bitsLeft = 0;
|
||||||
|
var binaryKey = new List<byte>();
|
||||||
|
|
||||||
|
foreach (char c in key)
|
||||||
|
{
|
||||||
|
int value = Base32Chars.IndexOf(c);
|
||||||
|
if (value < 0) continue; // Ignore invalid characters
|
||||||
|
|
||||||
|
buffer = (buffer << 5) + value;
|
||||||
|
bitsLeft += 5;
|
||||||
|
if (bitsLeft >= 8)
|
||||||
|
{
|
||||||
|
bitsLeft -= 8;
|
||||||
|
binaryKey.Add((byte)((buffer >> bitsLeft) & 0xFF));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return binaryKey.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -101,6 +101,7 @@
|
||||||
<DependentUpon>GlobalSettingsForm.cs</DependentUpon>
|
<DependentUpon>GlobalSettingsForm.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Tools\ResourceServer.cs" />
|
<Compile Include="Tools\ResourceServer.cs" />
|
||||||
|
<Compile Include="Tools\Tfa.cs" />
|
||||||
<EmbeddedResource Include="EnvForm.resx">
|
<EmbeddedResource Include="EnvForm.resx">
|
||||||
<DependentUpon>EnvForm.cs</DependentUpon>
|
<DependentUpon>EnvForm.cs</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user