Optimize generating totp codes (#3512)

This commit is contained in:
Pavel Djundik
2025-11-24 12:11:46 +02:00
committed by GitHub
parent dfd2bd9ac4
commit 29cb094430

View File

@@ -23,6 +23,7 @@
using System; using System;
using System.Buffers; using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
@@ -101,53 +102,33 @@ public sealed class MobileAuthenticator : IDisposable {
throw new InvalidOperationException(nameof(SharedSecret)); throw new InvalidOperationException(nameof(SharedSecret));
} }
byte[] sharedSecret; Span<byte> sharedSecret = stackalloc byte[32];
try { if (!Convert.TryFromBase64String(SharedSecret, sharedSecret, out int bytesWritten)) {
sharedSecret = Convert.FromBase64String(SharedSecret);
} catch (FormatException e) {
Bot.ArchiLogger.LogGenericException(e);
Bot.ArchiLogger.LogGenericError(Strings.FormatErrorIsInvalid(nameof(SharedSecret))); Bot.ArchiLogger.LogGenericError(Strings.FormatErrorIsInvalid(nameof(SharedSecret)));
return null; return null;
} }
byte[] timeArray = BitConverter.GetBytes(time / CodeInterval); sharedSecret = sharedSecret[..bytesWritten];
if (BitConverter.IsLittleEndian) { Span<byte> timeArray = stackalloc byte[sizeof(long)];
Array.Reverse(timeArray); BinaryPrimitives.WriteInt64BigEndian(timeArray, (long) (time / CodeInterval));
}
Span<byte> hash = stackalloc byte[HMACSHA1.HashSizeInBytes];
#pragma warning disable CA5350 // This is actually a fair warning, but there is nothing we can do about Steam using weak cryptographic algorithms #pragma warning disable CA5350 // This is actually a fair warning, but there is nothing we can do about Steam using weak cryptographic algorithms
byte[] hash = HMACSHA1.HashData(sharedSecret, timeArray); _ = HMACSHA1.HashData(sharedSecret, timeArray, hash);
#pragma warning restore CA5350 // This is actually a fair warning, but there is nothing we can do about Steam using weak cryptographic algorithms #pragma warning restore CA5350 // This is actually a fair warning, but there is nothing we can do about Steam using weak cryptographic algorithms
// The last 4 bits of the mac say where the code starts // The last 4 bits of the mac say where the code starts
int start = hash[^1] & 0x0f; int start = hash[^1] & 0x0f;
uint fullCode;
// Extract those 4 bytes // Extract those 4 bytes
byte[] bytes = ArrayPool<byte>.Shared.Rent(4); Span<byte> bytes = hash[start..(start + 4)];
try { // Build the alphanumeric code
Array.Copy(hash, start, bytes, 0, 4); uint fullCode = BinaryPrimitives.ReadUInt32BigEndian(bytes) & 0x7fffffff;
Span<byte> span;
if (BitConverter.IsLittleEndian) {
Array.Reverse(bytes);
span = bytes.AsSpan()[^4..];
} else {
span = bytes.AsSpan()[..4];
}
// Build the alphanumeric code
fullCode = BitConverter.ToUInt32(span) & 0x7fffffff;
} finally {
ArrayPool<byte>.Shared.Return(bytes);
}
return string.Create( return string.Create(
CodeDigits, fullCode, static (buffer, state) => { CodeDigits, fullCode, static (buffer, state) => {