Низкоуровневое программирование для подписи XML без класса SignedXml
Я провожу 2 недели, пытаясь заставить это работать, но безуспешно.
Я использую данные.NET Core v2.0 и X509Certificate2 (данные получены из хранилища ключей Azure).
Я не могу использовать SignedXml
класс из-за неверного xml от сторонней компании, который содержит максимум 6000 полей. Сторонним компаниям, занимающимся XML, более 12 лет, и она не изменит схему xml из-за проблем с интеграцией.
В качестве обходного пути я должен выполнить низкоуровневое программирование, чтобы выполнить эту работу, не полагаясь на.NET Core. SignedXml
учебный класс.
Сертификат и использование сторонней компании являются RSA и SHA1.
Это лучшее, что я могу сделать. Может кто-нибудь сказать мне, почему подписанный XML не удалось?
public class SignXmlTest
{
public SignXmlTest()
{
using(HashAlgorithm hashAlgorithm = SHA1.Create())
{
hashAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(this._bodyData));
this._hashSHA1 = hashAlgorithm.Hash;
}
// For SignatureValue.
_c14n = "<ds:SignedInfo>" +
"<ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>" +
"<ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>" +
"<ds:Reference URI=\"#" + string.Format("{0}", this._bodyId) + "\">" +
"<ds:Transforms>" +
"<ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>" +
"</ds:Transforms>" +
"<ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>" +
"<ds:DigestValue>" + string.Format("{0}", this.GetDigestValue()) + "</ds:DigestValue>" +
"</ds:Reference>" +
"</ds:SignedInfo>";
}
private X509Certificate2 _x509Certificate2 = new X509Certificate2(); //await this._azureWebClient.GetKeyVault_CertificateAsync(cancellationToken);
private string _bodyId = "Body";
private string _bodyData = "<foo>Foo Foo Foo Me</foo>";
private byte[] _hashSHA1;
private string _c14n;
private string GetDigestValue()
{
return Convert.ToBase64String(
this._hashSHA1
);
}
private string GetSignatureValue()
{
byte[] signature;
signature = this._x509Certificate2.GetRSAPrivateKey().SignData(
Encoding.UTF8.GetBytes(_c14n),
HashAlgorithmName.SHA1,
RSASignaturePadding.Pkcs1
);
return Convert.ToBase64String(
signature
);
}
public void Process()
{
var x509Certificate2 = new X509Certificate2(); //await this._azureWebClient.GetKeyVault_CertificateAsync(cancellationToken);
var xmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3c.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/s001/XMLSchema-instance\">" +
"<soap:Header>" +
"<soap-sec:Security xmlns:soap-sec=\"http://schemas.xmlsoap.org/soap/security/2000-12\">" +
"<soap-sec:Signature>" +
"<ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">" +
"<ds:SignedInfo>" +
"<ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>" +
"<ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>" +
"<ds:Reference URI=\"#" + string.Format("{0}", this._bodyId) + "\">" +
"<ds:Transforms>" +
"<ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>" +
"</ds:Transforms>" +
"<ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>" +
"<ds:DigestValue>" + string.Format("{0}", this.GetDigestValue()) + "</ds:DigestValue>" +
"</ds:Reference>" +
"</ds:SignedInfo>" +
"<ds:SignatureValue>" + string.Format("{0}", this.GetSignatureValue()) + "</ds:SignatureValue>" +
"<ds:KeyInfo>" +
"<ds:X509Data>" +
"<X509IssuerSerial>" +
"<X509IssuerName>" + string.Format("{0}", this._x509Certificate2.Issuer) + "</X509IssuerName>" +
"<X509SerialNumber>" +
string.Format("{0}",
new BigInteger(
this._x509Certificate2.GetSerialNumber()
).ToString()
) +
"</X509SerialNumber>" +
"</X509IssuerSerial>" +
"</ds:X509Data>" +
"</ds:KeyInfo>" +
"</ds:Signature>" +
"</soap-sec:Signature>" +
"</soap-sec:Security>" +
"</soap:Header>" +
"<soap:Body Id=\"" + string.Format("{0}", this._bodyId) + "\">" +
this._bodyData +
"</soap:Body>" +
"</soap:Envelope>";
}
}