Answer the question
In order to leave comments, you need to log in
How to beautifully implement the possibility of signing a data block?
Good afternoon!
There is a class:
public class MyClass<TData>
{
// хеш от результата применения эцп
public ISignature Signature {get;set}
// ПАРАМЕТРЫ
public long Param1 {get; set}
public string Param2 {get; set}
// и куча других полей
// ТУТ ДАННЫЕ
public TData InnerData {get;set}
}
public interface IClassHeader{
long Param1 {get;}
string Param2 {get;}
}
public interface IMyObj<THeader, TData> where THeader: IClassHeader{
ISignature Signature { get; }
THeader Header {get;}
TData InnerData {get;}
}
public class MyHeader: IClassHeader { ...}
public class MyObj: IMyObj<MyHeader, string> { ... }
public interface IMyObjValidator<TObj, THeader, TData>
where TObj: IMyObj<THeader, TData>
where THeader: IClassHeader {
bool CheckSignature(TObj inputObject);
}
public interface IObjectWithParams{ //пользователь расширяет именно его
ISignature Signature {get;}
long Param1 {get;}
string Param2 {get;}
}
public interface ICheckableObject {
bool CheckSignature(IMyObjValidationAlgorithm algorithm);
}
public interface ISignableObject {
void SignObject(ISignatureService service);
}
public interface IDataObject<TData> : IObjectWithParams {
TData Data {get;}
}
public interface IMyObject<TData>: IDataObject<TData>, ICheckableObject, ISignableObject {}
public class MyObject: IMyObject<string> {
...
private ISignature _signature = null;
void ISignableObject.Sign(ISignatureService service) {
var sign = service.Sign(this);
_signature = sign;
}
public ISignature Signature => _signature
}
Answer the question
In order to leave comments, you need to log in
As I understand the task: you have two entities, the implementation of which is unknown:
The object does not know what service it will be signed by, and the service does not know what structure the signed object has.
In this case, it is logical to introduce some intermediate entity into which the object can serialize itself, and the service will know how to sign it. In the simplest case, this can be an array, such as byte[]. You can come up with a more sophisticated way with streaming signature generation so as not to create an intermediate object.
Maybe I misunderstood the problem, but here's what I got.
Interfaces:
public interface ISignable
{
ISignature Signature { get; set; }
byte[] Serialize();
}
public interface ISignature
{
}
public interface ISignatureService
{
bool Validate(ISignable signable);
void Sign(ISignable signable);
}
class MyObject : ISignable
{
public ISignature Signature { get; set; }
public long Param1 { get; set; }
public string Param2 { get; set; }
public string InnerData { get; set; }
public byte[] Serialize()
{
return Encoding.UTF8.GetBytes(Param1 + Param2 + InnerData);
}
}
public class HashCodeSignatureService : ISignatureService
{
public void Sign(ISignable signable)
{
var signature = CalculateSignature(signable);
signable.Signature = signature;
}
public bool Validate(ISignable signable)
{
var s1 = CalculateSignature(signable);
var s2 = signable.Signature as SimpleHashCodeSignature;
return s1?.HashCode == s2?.HashCode;
}
private static SimpleHashCodeSignature CalculateSignature(ISignable signable)
{
var body = signable.Serialize();
var signature = new SimpleHashCodeSignature(body.Aggregate(0, (a, b) => a + b.GetHashCode()));
return signature;
}
}
public class SimpleHashCodeSignature : ISignature
{
public int HashCode { get; }
public SimpleHashCodeSignature(int hashCode)
{
HashCode = hashCode;
}
}
class Program
{
static void Main(string[] args)
{
var obj = new MyObject {Param1 = 1, Param2 = "asd", InnerData = "some data"};
var signatureService = new HashCodeSignatureService();
signatureService.Sign(obj);
// Passing the object across untrusted boundary
signatureService.Validate(obj);
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question