last ...
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
namespace xIds.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Api Key Generating Helper Class ...
|
||||
/// </summary>
|
||||
public static class XApiKeyHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Generate an Api Key ...
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static (string plainKey, string hash, string prefix) Generate()
|
||||
{
|
||||
//
|
||||
// Generate 32 bytes of cryptographically secure random data
|
||||
var randomBytes = new byte[32];
|
||||
using (var rng = RandomNumberGenerator.Create())
|
||||
{
|
||||
rng.GetBytes(randomBytes);
|
||||
}
|
||||
|
||||
//
|
||||
// Format: xapp_{base64url}
|
||||
var plainKey = $"xapp_{Convert.ToBase64String(randomBytes)
|
||||
.Replace("+", "-").Replace("/", "_").TrimEnd('=')}";
|
||||
|
||||
//
|
||||
// Hash with SHA256 for storage (never store plain key)
|
||||
using (var sha256 = SHA256.Create())
|
||||
{
|
||||
//
|
||||
var hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(plainKey));
|
||||
var hash = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
|
||||
|
||||
//
|
||||
// Prefix for quick identification (first 12 chars)
|
||||
var prefix = plainKey.Substring(0, 16) + "...";
|
||||
|
||||
//
|
||||
return (plainKey, hash, prefix);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify Generating Api Key ...
|
||||
/// </summary>
|
||||
/// <param name="plainKey"></param>
|
||||
/// <param name="storedHash"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Verify(
|
||||
string plainKey,
|
||||
string storedHash
|
||||
)
|
||||
{
|
||||
//
|
||||
using (var sha256 = SHA256.Create())
|
||||
{
|
||||
//
|
||||
var hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(plainKey));
|
||||
var computedHash = BitConverter.ToString(hashBytes)
|
||||
.Replace("-", "").ToLower();
|
||||
|
||||
//
|
||||
return computedHash == storedHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user