You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
4.9 KiB
C#
148 lines
4.9 KiB
C#
using System.Text.Json;
|
|
|
|
namespace OnlineMsgServer.Common
|
|
{
|
|
internal sealed class ClientRegistrationPayload
|
|
{
|
|
public string PublicKey { get; init; } = "";
|
|
public string Challenge { get; init; } = "";
|
|
public long Timestamp { get; init; }
|
|
public string Nonce { get; init; } = "";
|
|
public string Signature { get; init; } = "";
|
|
|
|
public static bool TryParse(dynamic? data, out ClientRegistrationPayload payload, out string error)
|
|
{
|
|
payload = new ClientRegistrationPayload();
|
|
error = "invalid data";
|
|
|
|
if (data is not JsonElement json || json.ValueKind != JsonValueKind.Object)
|
|
{
|
|
error = "data must be object";
|
|
return false;
|
|
}
|
|
|
|
if (!TryReadString(json, "publicKey", out string publicKey) ||
|
|
!TryReadString(json, "challenge", out string challenge) ||
|
|
!TryReadInt64(json, "timestamp", out long timestamp) ||
|
|
!TryReadString(json, "nonce", out string nonce) ||
|
|
!TryReadString(json, "signature", out string signature))
|
|
{
|
|
error = "missing registration fields";
|
|
return false;
|
|
}
|
|
|
|
payload = new ClientRegistrationPayload
|
|
{
|
|
PublicKey = publicKey,
|
|
Challenge = challenge,
|
|
Timestamp = timestamp,
|
|
Nonce = nonce,
|
|
Signature = signature
|
|
};
|
|
return true;
|
|
}
|
|
|
|
public static string BuildSigningInput(string userName, string publicKey, string challenge, long timestamp, string nonce)
|
|
{
|
|
return string.Join("\n", "publickey", userName, publicKey, challenge, timestamp, nonce);
|
|
}
|
|
|
|
private static bool TryReadString(JsonElement root, string property, out string value)
|
|
{
|
|
value = "";
|
|
if (!root.TryGetProperty(property, out JsonElement element) || element.ValueKind != JsonValueKind.String)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string? src = element.GetString();
|
|
if (string.IsNullOrWhiteSpace(src))
|
|
{
|
|
return false;
|
|
}
|
|
value = src.Trim();
|
|
return true;
|
|
}
|
|
|
|
private static bool TryReadInt64(JsonElement root, string property, out long value)
|
|
{
|
|
value = 0;
|
|
if (!root.TryGetProperty(property, out JsonElement element))
|
|
{
|
|
return false;
|
|
}
|
|
return element.TryGetInt64(out value);
|
|
}
|
|
}
|
|
|
|
internal sealed class SignedMessagePayload
|
|
{
|
|
public string Payload { get; init; } = "";
|
|
public long Timestamp { get; init; }
|
|
public string Nonce { get; init; } = "";
|
|
public string Signature { get; init; } = "";
|
|
|
|
public static bool TryParse(dynamic? data, out SignedMessagePayload payload, out string error)
|
|
{
|
|
payload = new SignedMessagePayload();
|
|
error = "invalid data";
|
|
|
|
if (data is not JsonElement json || json.ValueKind != JsonValueKind.Object)
|
|
{
|
|
error = "data must be object";
|
|
return false;
|
|
}
|
|
|
|
if (!TryReadString(json, "payload", out string messagePayload) ||
|
|
!TryReadInt64(json, "timestamp", out long timestamp) ||
|
|
!TryReadString(json, "nonce", out string nonce) ||
|
|
!TryReadString(json, "signature", out string signature))
|
|
{
|
|
error = "missing signed message fields";
|
|
return false;
|
|
}
|
|
|
|
payload = new SignedMessagePayload
|
|
{
|
|
Payload = messagePayload,
|
|
Timestamp = timestamp,
|
|
Nonce = nonce,
|
|
Signature = signature
|
|
};
|
|
return true;
|
|
}
|
|
|
|
public static string BuildSigningInput(string type, string key, string payload, long timestamp, string nonce)
|
|
{
|
|
return string.Join("\n", type, key, payload, timestamp, nonce);
|
|
}
|
|
|
|
private static bool TryReadString(JsonElement root, string property, out string value)
|
|
{
|
|
value = "";
|
|
if (!root.TryGetProperty(property, out JsonElement element) || element.ValueKind != JsonValueKind.String)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string? src = element.GetString();
|
|
if (string.IsNullOrWhiteSpace(src))
|
|
{
|
|
return false;
|
|
}
|
|
value = src;
|
|
return true;
|
|
}
|
|
|
|
private static bool TryReadInt64(JsonElement root, string property, out long value)
|
|
{
|
|
value = 0;
|
|
if (!root.TryGetProperty(property, out JsonElement element))
|
|
{
|
|
return false;
|
|
}
|
|
return element.TryGetInt64(out value);
|
|
}
|
|
}
|
|
}
|