public CoaliteResource Action(CoaliteActionRequest coaliteActionRequest) { // Validate whole request var buffer = Encoding.UTF8.GetBytes(coaliteActionRequest.GetAsSignablePayload()); var signature = Convert.FromBase64String(coaliteActionRequest.Signature); var clientRsa = RSA.Create(); int bytesReadPk; var pk = coaliteActionRequest.SignerPublicKey.Split(' ').OrderByDescending(s => s.Length).FirstOrDefault(); clientRsa.ImportRSAPublicKey(Convert.FromBase64String(pk), out bytesReadPk); if (!clientRsa.VerifyData(buffer, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) { throw new CoalitingException((int)HttpStatusCode.BadRequest, "Signature does not match public key"); } Coalite coalite; lock (_dblock) { var dbcontext = GetDBConnection(); coalite = dbcontext.Coalites .Where(c => c.Coalid == coaliteActionRequest.Coalite.Coalid) .FirstOrDefault(); if (coalite == null) { throw new CoalitingException((int)HttpStatusCode.BadRequest, "Unexisting coalite"); } if (!coalite.EqualToResource(coaliteActionRequest.Coalite)) { throw new CoalitingException((int)HttpStatusCode.BadRequest, "Referenced coalite does not match last known coalite state"); } var payload = coalite.LoadPayload(); // Find coalite owner var lastClaimAction = payload.Signatures.LastOrDefault(s => s.Action == CoaliteAction.CLAIM); // Case 1: No owner and action is to claim // Case 2: Check if claimer has ownership rights if (lastClaimAction != null && lastClaimAction.SignerPublicKey != coaliteActionRequest.SignerPublicKey) { throw new CoalitingException((int)HttpStatusCode.BadRequest, "Coalite not owned by claimer public key"); } coalite.AppendSignedAction(coaliteActionRequest.Action, coaliteActionRequest.ActionPayload, coaliteActionRequest.SignerPublicKey, coaliteActionRequest.SignerId, coaliteActionRequest.ActionSignature); coalite.SignCoalite(_rsa, CoaliteAction.ACCEPT, "", _serverPublicKey, "System"); if (coaliteActionRequest.Action == CoaliteAction.CLAIM) { coalite.ClaimedBy = coaliteActionRequest.SignerId; } dbcontext.Update(coalite); dbcontext.SaveChanges(); return(new CoaliteResource(coalid: coalite.Coalid, signatures: coalite.LoadPayload().Signatures, seqid: coalite.FullSecondStamp, timestamp: _baseDate + TimeSpan.FromSeconds(coalite.FullSecondStamp))); } }
public ActionResult <CoaliteResource> Action([FromBody] CoaliteActionRequest coaliteActionRequest) { var coalite = _coaliter.Action(coaliteActionRequest); return(Ok(coalite)); }