online_security_project/client/Message.cs

72 lines
No EOL
1.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using lib;
namespace client;
public class Message
{
public uint Id { set; get; }
public string Sender { set; get; }
public bool IsAck { set; get; }
public string Content { set; get; }
public byte[] Signature { set; get; }
public Message(byte[] bytes)
{
if (bytes[0] != 0)
{
Console.WriteLine("Failed parsing message, unsupported version");
}
// skip the first byte for simplicity
bytes = bytes[1..];
Id = BitConverter.ToUInt32(bytes, 0);
Sender = Utils.BytesToNumber(bytes[4..12]);
IsAck = bytes[12] != 0;
Content = Encoding.UTF8.GetString(bytes[13..(bytes.Length - 32)]);
Signature = bytes[(bytes.Length - 32)..];
}
public Message(uint Id, string Sender, bool IsAck, string Content)
{
this.Id = Id;
this.Sender = Sender;
this.IsAck = IsAck;
this.Content = Content;
Signature = [];
}
public void CalculateSignature(RSA key)
{
Signature = key.SignData(Bytes(false), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
public bool IsSignatureValid(RSA key)
{
return key.VerifyData(Bytes(false), Signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
public byte[] Bytes(bool IncludeSignature = true)
{
List<byte> msg = [];
// 0..4
msg.AddRange(BitConverter.GetBytes(Id));
// 4..12
msg.AddRange(Utils.NumberToBytes(Sender));
// 12
msg.Add((byte)(IsAck ? 1 : 0));
// 13..(len - 32)
msg.AddRange(Encoding.UTF8.GetBytes(Content));
// (len - 32)..
if (IncludeSignature) // we dont want to include the signature when we sign/verify the data
{
msg.AddRange(Signature);
}
return [0, .. msg];
}
}