mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2025-12-16 06:20:34 +00:00
Optimize generating totp codes (#3512)
This commit is contained in:
@@ -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) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user