117 lines
3.8 KiB
C#
117 lines
3.8 KiB
C#
using Hcs.Client.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.Client.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());
|
|
}
|
|
}
|
|
}
|