Skip to content

Commit b4d8baf

Browse files
committed
Eliminate allocations when computing fingerprint hash.
Signed-off-by: Bradley Grainger <[email protected]>
1 parent 2aea924 commit b4d8baf

File tree

1 file changed

+26
-11
lines changed

1 file changed

+26
-11
lines changed

src/MySqlConnector/Core/ServerSession.cs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -628,9 +628,9 @@ private bool ValidateFingerprint(byte[]? validationHash, ReadOnlySpan<byte> chal
628628
break;
629629

630630
case "client_ed25519":
631-
AuthenticationPlugins.TryGetPlugin("client_ed25519", out var ed25519Plugin);
631+
AuthenticationPlugins.TryGetPlugin(m_pluginName, out var ed25519Plugin);
632632
if (ed25519Plugin is IAuthenticationPlugin2 plugin2)
633-
passwordHashResult = plugin2!.CreatePasswordHash(password, challenge);
633+
passwordHashResult = plugin2.CreatePasswordHash(password, challenge);
634634
break;
635635
}
636636
if (passwordHashResult is null)
@@ -641,19 +641,34 @@ private bool ValidateFingerprint(byte[]? validationHash, ReadOnlySpan<byte> chal
641641
challenge.CopyTo(combined[passwordHashResult.Length..]);
642642
m_sha2Thumbprint!.CopyTo(combined[(passwordHashResult.Length + challenge.Length)..]);
643643

644-
byte[] hashBytes;
644+
Span<byte> hashBytes = stackalloc byte[32];
645645
#if NET5_0_OR_GREATER
646-
hashBytes = SHA256.HashData(combined);
646+
SHA256.TryHashData(combined, hashBytes, out _);
647647
#else
648-
using (var sha256 = SHA256.Create())
649-
{
650-
hashBytes = sha256.ComputeHash(combined.ToArray());
651-
}
648+
using var sha256 = SHA256.Create();
649+
sha256.TryComputeHash(combined, hashBytes, out _);
652650
#endif
653651

654-
var clientGeneratedHash = hashBytes.Aggregate(string.Empty, (str, hashByte) => str + hashByte.ToString("X2", CultureInfo.InvariantCulture));
655-
var serverGeneratedHash = Encoding.ASCII.GetString(validationHash, 1, validationHash.Length - 1);
656-
return string.Equals(clientGeneratedHash, serverGeneratedHash, StringComparison.Ordinal);
652+
Span<byte> serverHash = combined[0..32];
653+
return TryConvertFromHexString(validationHash.AsSpan(1), serverHash) && serverHash.SequenceEqual(hashBytes);
654+
655+
static bool TryConvertFromHexString(ReadOnlySpan<byte> hexChars, Span<byte> data)
656+
{
657+
ReadOnlySpan<byte> hexDigits = "0123456789ABCDEFabcdef"u8;
658+
for (var i = 0; i < hexChars.Length; i += 2)
659+
{
660+
var high = hexDigits.IndexOf(hexChars[i]);
661+
var low = hexDigits.IndexOf(hexChars[i + 1]);
662+
if (high == -1 || low == -1)
663+
return false;
664+
if (high > 15)
665+
high -= 6;
666+
if (low > 15)
667+
low -= 6;
668+
data[i / 2] = (byte) ((high << 4) | low);
669+
}
670+
return true;
671+
}
657672
}
658673

659674
public static async ValueTask<ServerSession> ConnectAndRedirectAsync(ILogger connectionLogger, ILogger poolLogger, IConnectionPoolMetadata pool, ConnectionSettings cs, ILoadBalancer? loadBalancer, MySqlConnection connection, Action<ILogger, int, string, Exception?>? logMessage, long startingTimestamp, Activity? activity, IOBehavior ioBehavior, CancellationToken cancellationToken)

0 commit comments

Comments
 (0)