Files
hcs/Hcs.ClientNet/Client/Api/Request/GostSigningMessageInspector.cs

117 lines
3.8 KiB
C#

using Hcs.ClientNet.Internal;
using GostXades;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Text;
using System.Xml;
namespace Hcs.ClientNet.Api.Request
{
/// <summary>
/// Фильтр сообщений добавляет в XML-сообщение электронную подпись XADES/GOST
/// </summary>
internal class GostSigningMessageInspector(ClientBase client) : IClientMessageInspector
{
private readonly ClientBase client = client;
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
try
{
var filterHeader = "[Message Inspector]";
PurgeDebuggerHeaders(ref request);
var messageBody = GetMessageBodyString(ref request, Encoding.UTF8);
if (!messageBody.Contains(Constants.SIGNED_XML_ELEMENT_ID))
{
client.TryCaptureMessage(true, messageBody);
}
else
{
var certInfo = X509Tools.GetFullnameWithExpirationDateStr(client.Certificate);
client.TryLog($"{filterHeader} signing message with key [{certInfo}]...");
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
var service = new GostXadesBesService(client.CryptoProviderType);
var signedXml = service.Sign(messageBody,
Constants.SIGNED_XML_ELEMENT_ID,
client.CertificateThumbprint,
client.CertificatePassword);
stopwatch.Stop();
client.TryLog($"{filterHeader} message signed in {stopwatch.ElapsedMilliseconds} ms");
client.TryCaptureMessage(true, signedXml);
request = Message.CreateMessage(
XmlReaderFromString(signedXml), int.MaxValue, request.Version);
}
}
catch (System.Exception ex)
{
throw new System.Exception($"Exception occured in {GetType().Name}", ex);
}
return null;
}
private void PurgeDebuggerHeaders(ref Message request)
{
var limit = request.Headers.Count;
for (var i = 0; i < limit; ++i)
{
if (request.Headers[i].Name.Equals("VsDebuggerCausalityData"))
{
request.Headers.RemoveAt(i);
break;
}
}
}
private string GetMessageBodyString(ref Message request, Encoding encoding)
{
var mb = request.CreateBufferedCopy(int.MaxValue);
request = mb.CreateMessage();
var s = new MemoryStream();
var xw = XmlWriter.Create(s);
mb.CreateMessage().WriteMessage(xw);
xw.Flush();
s.Position = 0;
var bXML = new byte[s.Length];
s.Read(bXML, 0, (int)s.Length);
if (bXML[0] != (byte)'<')
{
return encoding.GetString(bXML, 3, bXML.Length - 3);
}
else
{
return encoding.GetString(bXML, 0, bXML.Length);
}
}
private XmlReader XmlReaderFromString(string xml)
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(xml);
writer.Flush();
stream.Position = 0;
return XmlReader.Create(stream);
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
client.TryCaptureMessage(false, reply.ToString());
}
}
}