54 lines
No EOL
1.5 KiB
C#
54 lines
No EOL
1.5 KiB
C#
using System.Diagnostics.CodeAnalysis;
|
|
using System.Security.Cryptography;
|
|
|
|
namespace DataTransfer.Client.Shared;
|
|
|
|
/// <summary>Generates and parses the one-time codes used to pair two participants.</summary>
|
|
public static class ConnectionCode
|
|
{
|
|
public const int Length = 10;
|
|
|
|
// Ambiguous characters (0/O, 1/I) are excluded. 32 symbols ^ 10 = 50 bits of entropy.
|
|
private const string Alphabet = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
|
|
public static string Generate() => RandomNumberGenerator.GetString(Alphabet, Length);
|
|
|
|
/// <summary>Accepts user input case-insensitively, ignoring whitespace and dashes.</summary>
|
|
public static bool TryNormalize(string? input, [NotNullWhen(true)] out string? code)
|
|
{
|
|
code = null;
|
|
if (string.IsNullOrWhiteSpace(input))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Span<char> buffer = stackalloc char[Length];
|
|
var count = 0;
|
|
foreach (var c in input)
|
|
{
|
|
if (char.IsWhiteSpace(c) || c == '-')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var upper = char.ToUpperInvariant(c);
|
|
if (count == Length || !Alphabet.Contains(upper))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
buffer[count++] = upper;
|
|
}
|
|
|
|
if (count != Length)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
code = new string(buffer);
|
|
return true;
|
|
}
|
|
|
|
public static string Format(string code) =>
|
|
code.Length == Length ? $"{code[..5]}-{code[5..]}" : code;
|
|
} |