Использую библиотеку https://github.com/springjazzy/Xades
Только ее немного подправил. Отправил исправленную версию на почту.
Вызываю так:
public byte[] SignSoap(byte[] soap, EventLog eventLog, string tokenPassword)
{
return Encoding.UTF8.GetBytes(GisSignatureHelper.GetSignedRequestXades(Encoding.UTF8.GetString(soap), GetSertificate(tokenPassword, eventLog), GetRawSign, tokenPassword, eventLog));
}
Доп.методы:
private byte[] GetRawSign(byte[] file, EventLog eventLog1, string tokenPassword)
{
//eventLog1.WriteEntry("GetSign инициализация токена");
//var core = CryptoCore.getInstance(@"D:\SignService");
var core = CryptoCore.getInstance();
eventLog1.WriteEntry("GetSign получение списка устройств");
var devs = core.enumerateDevices();
eventLog1.WriteEntry("GetSign получение нашего устройства из списка");
var dev = devs[0];
eventLog1.WriteEntry("GetSign логирование на устройстве");
core.login(dev, tokenPassword);
eventLog1.WriteEntry("GetSign получение списка сертификатов");
var certs = core.enumerateCertificates(dev, 1);
eventLog1.WriteEntry("GetSign получение нашего сертификата");
var cert = certs[0];
//var keys = core.enumerateKeys(dev, "");
//var key = keys[1];
var key = core.getKeyByCertificate(dev, cert);
string data = "";
for (int i = 0; i < file.Length; i += 1)
{
// Convert the number expressed in base-16 to an integer.
//int value = BitConverter.ToInt32(file, i);
// Get the character corresponding to the integral value.
string hexOutput = String.Format("{0:X}", file[i]);
if (hexOutput.Length == 1)
hexOutput = "0" + hexOutput;
data += ":" + hexOutput;
}
data = data.Trim(':');
data = data.ToLower();
//data = Encoding.UTF8.GetString(file);
eventLog1.WriteEntry(data);
OptionsMap options = new OptionsMap
{
{"useHardwareHash", false},
{"computeHash", false},
{"invisible", false}
};
eventLog1.WriteEntry("GetSign получаю подпись");
string sign = core.rawSign(
dev,
key,
data,
options);
core.logout(dev);
eventLog1.WriteEntry(sign);
List<byte> result = new List<byte>();
string[] hexValuesSplit = sign.Split(':');
foreach (String hex in hexValuesSplit)
{
// Convert the number expressed in base-16 to an integer.
byte value = Convert.ToByte(hex, 16);
// Get the character corresponding to the integral value.
result.Add(value);
}
//result.Reverse();
return result.ToArray();
//return Encoding.UTF8.GetBytes(sign);
}
private X509Certificate2 GetSertificate(string tokenPassword, EventLog eventLog)
{
//var core = CryptoCore.getInstance(@"D:\SignService");
eventLog.WriteEntry("Получение сертификата");
var core = CryptoCore.getInstance();
var devs = core.enumerateDevices();
var dev = devs[0];
core.login(dev, tokenPassword);
var certs = core.enumerateCertificates(dev, 1);
var cert = certs[0];
var x = core.getCertificate(dev, cert);
var certificate = new X509Certificate2(Encoding.UTF8.GetBytes(core.getCertificate(dev, cert)));
core.logout(dev);
eventLog.WriteEntry("Получили сертификат");
return certificate;
}
Забыл упомянуть. Добавляю атрибут к исходному сообщению перед подписыванием:
XmlNamespaceManager namespaces = new XmlNamespaceManager(xmlDocument.NameTable);
namespaces.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
var childNode = xmlDocument.SelectNodes("//soap:Body", namespaces)[0].FirstChild;
XmlAttribute attr = xmlDocument.CreateAttribute("Id");
attr.InnerText = "signed-data-container";
childNode.Attributes.Append(attr);