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.
56 lines
2.0 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|