Files
Microsoft.SelfService.Porta…/Services/ApiClientSecretHasher.cs
Torsten Brendgen dc93ea0813 feat: Implement API client and token models with hashing and JWT authentication
- Added ApiClientModel and ApiTokenModel for managing API clients and tokens.
- Introduced ConfigurationDefinitionModel and ConfigurationValueModel for configuration management.
- Created CredentialSecretModel for storing credential secrets.
- Developed DeploymentArtifactModel and DeploymentBatchModel for deployment management.
- Enhanced DeploymentTargetModel and DeploymentTemplateSelectionModel to support template revisions.
- Added TemplateRevisionModel and TemplateVersionModel for versioning templates.
- Implemented ApiClientSecretHasher for secure secret hashing.
- Created ApiTokenService for generating and validating JWT tokens.
- Updated QueueJobService to handle deployment requests with artifacts.
- Configured authentication settings in appsettings.json for JWT and Negotiate authentication.
2026-07-09 14:44:38 +02:00

59 lines
2.0 KiB
C#

using System.Security.Cryptography;
namespace Microsoft.SelfService.Portal.Core.API.Services
{
public static class ApiClientSecretHasher
{
private const int SaltSize = 16;
private const int KeySize = 32;
private const int DefaultIterations = 100_000;
public static string HashSecret(string secret)
{
var salt = RandomNumberGenerator.GetBytes(SaltSize);
var hash = Rfc2898DeriveBytes.Pbkdf2(secret, salt, DefaultIterations, HashAlgorithmName.SHA256, KeySize);
return string.Join(
'.',
"PBKDF2-SHA256",
DefaultIterations.ToString(),
Convert.ToBase64String(salt),
Convert.ToBase64String(hash));
}
public static bool VerifySecret(string secret, string storedHash)
{
var parts = storedHash.Split('.');
if (parts.Length != 4 || parts[0] != "PBKDF2-SHA256")
{
return false;
}
if (!int.TryParse(parts[1], out var iterations))
{
return false;
}
var salt = Convert.FromBase64String(parts[2]);
var expectedHash = Convert.FromBase64String(parts[3]);
var actualHash = Rfc2898DeriveBytes.Pbkdf2(secret, salt, iterations, HashAlgorithmName.SHA256, expectedHash.Length);
return CryptographicOperations.FixedTimeEquals(actualHash, expectedHash);
}
internal static string HashSecretForDemoData(string secret, string saltText)
{
var salt = System.Text.Encoding.UTF8.GetBytes(saltText);
Array.Resize(ref salt, SaltSize);
var hash = Rfc2898DeriveBytes.Pbkdf2(secret, salt, DefaultIterations, HashAlgorithmName.SHA256, KeySize);
return string.Join(
'.',
"PBKDF2-SHA256",
DefaultIterations.ToString(),
Convert.ToBase64String(salt),
Convert.ToBase64String(hash));
}
}
}