Address identity review feedback

This commit is contained in:
Sipke Schoorstra 2026-05-21 02:03:06 +02:00
parent 04429e81c6
commit 4a9840b3cd
No known key found for this signature in database
GPG key ID: 5C10502B28A4268F
4 changed files with 7 additions and 22 deletions

View file

@ -1,4 +1,3 @@
using System.Security.Cryptography;
using System.Text;
using Elsa.Identity.Contracts;
@ -13,7 +12,7 @@ public class DefaultApiKeyGeneratorAndParser : IApiKeyGenerator, IApiKeyParser
public string Generate(string clientId)
{
var hexIdentifier = Convert.ToHexString(Encoding.UTF8.GetBytes(clientId));
var id = new Guid(RandomNumberGenerator.GetBytes(16)).ToString("D");
var id = Guid.NewGuid().ToString("D");
return $"{hexIdentifier}-{id}";
}

View file

@ -1,5 +1,4 @@
using System.Security.Cryptography;
using System.Text;
using Elsa.Identity.Constants;
using Elsa.Identity.Contracts;
@ -11,16 +10,7 @@ public class DefaultRandomStringGenerator : IRandomStringGenerator
/// <inheritdoc />
public string Generate(int length = 32, char[]? chars = null)
{
var identifierBuilder = new StringBuilder(length);
chars ??= CharacterSequences.AlphanumericSequence;
for (var i = 0; i < length; i++)
{
var randomIndex = RandomNumberGenerator.GetInt32(chars.Length);
identifierBuilder.Append(chars[randomIndex]);
}
return identifierBuilder.ToString();
return RandomNumberGenerator.GetString(chars, length);
}
}

View file

@ -66,13 +66,13 @@ public class DefaultSecretHasher : ISecretHasher
var storedSecretBytes = hashedSecret.Secret;
var saltBytes = hashedSecret.Salt;
var clearTextBytes = Encoding.UTF8.GetBytes(clearTextSecret);
byte[]? expectedHash = null;
Span<byte> expectedHash = stackalloc byte[KeySize];
byte[]? providedHash = null;
byte[]? legacyHash = null;
try
{
if (TryReadPbkdf2Hash(storedSecretBytes, out var iterationCount, out expectedHash))
if (TryReadPbkdf2Hash(storedSecretBytes, expectedHash, out var iterationCount))
{
providedHash = HashSecret(clearTextBytes, saltBytes, iterationCount);
var matches = CryptographicOperations.FixedTimeEquals(providedHash, expectedHash);
@ -101,8 +101,7 @@ public class DefaultSecretHasher : ISecretHasher
if (legacyHash is not null)
CryptographicOperations.ZeroMemory(legacyHash);
if (expectedHash is not null)
CryptographicOperations.ZeroMemory(expectedHash);
CryptographicOperations.ZeroMemory(expectedHash);
}
}
@ -160,10 +159,9 @@ public class DefaultSecretHasher : ISecretHasher
return sha256.GetHashAndReset();
}
private static bool TryReadPbkdf2Hash(byte[] storedSecretBytes, out int iterationCount, out byte[] hash)
private static bool TryReadPbkdf2Hash(byte[] storedSecretBytes, Span<byte> hash, out int iterationCount)
{
iterationCount = 0;
hash = [];
var envelope = storedSecretBytes.AsSpan();
var algorithmSeparatorIndex = envelope.IndexOf(SeparatorByte);
@ -184,14 +182,12 @@ public class DefaultSecretHasher : ISecretHasher
return false;
var encodedHashBytes = iterationAndHashBytes[(iterationSeparatorIndex + 1)..];
hash = new byte[KeySize];
var status = Base64.DecodeFromUtf8(encodedHashBytes, hash, out var consumed, out var written);
if (status == OperationStatus.Done && consumed == encodedHashBytes.Length && written == KeySize)
return true;
iterationCount = 0;
CryptographicOperations.ZeroMemory(hash);
hash = [];
return false;
}
}

View file

@ -4,7 +4,7 @@ using Elsa.Identity.Models;
namespace Elsa.Identity.UnitTests.Services;
public class ISecretHasherTests
public class SecretHasherDefaultOverloadTests
{
private readonly ISecretHasher _hasher = new BackwardCompatibleSecretHasher();