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.
OnlineMsgServer/Core/SecurityValidator.cs

56 lines
2.0 KiB
C#

using System.Security.Cryptography;
using OnlineMsgServer.Common;
namespace OnlineMsgServer.Core
{
internal static class SecurityValidator
{
public static string CreateNonce(int bytes = 24)
{
byte[] buffer = RandomNumberGenerator.GetBytes(bytes);
return Convert.ToBase64String(buffer);
}
public static bool IsTimestampAcceptable(long unixSeconds, int maxClockSkewSeconds, int replayWindowSeconds)
{
long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
long maxFuture = now + maxClockSkewSeconds;
long minPast = now - replayWindowSeconds;
return unixSeconds >= minPast && unixSeconds <= maxFuture;
}
public static bool VerifySignedMessage(string wsid, string type, string key, SignedMessagePayload payload, out string reason)
{
reason = "";
SecurityConfig config = SecurityRuntime.Config;
if (!IsTimestampAcceptable(payload.Timestamp, config.MaxClockSkewSeconds, config.ReplayWindowSeconds))
{
reason = "timestamp out of accepted window";
return false;
}
string? publicKey = UserService.GetUserPublicKeyByID(wsid);
if (string.IsNullOrWhiteSpace(publicKey))
{
reason = "sender public key missing";
return false;
}
string signingInput = SignedMessagePayload.BuildSigningInput(type, key, payload.Payload, payload.Timestamp, payload.Nonce);
if (!RsaService.VerifySignature(publicKey, signingInput, payload.Signature))
{
reason = "signature verify failed";
return false;
}
if (!UserService.TryRecordNonce(wsid, payload.Nonce, payload.Timestamp, config.ReplayWindowSeconds, out reason))
{
return false;
}
return true;
}
}
}