Fix signature validation
This commit is contained in:
@ -116,7 +116,7 @@ namespace Hcs.Broker.Api.Request
|
|||||||
var keyInfo = new CpKeyInfo();
|
var keyInfo = new CpKeyInfo();
|
||||||
keyInfo.AddClause(new CpKeyInfoX509Data(certificate));
|
keyInfo.AddClause(new CpKeyInfoX509Data(certificate));
|
||||||
|
|
||||||
var signedXml = new CpXadesSignedXml(doc)
|
var signedXml = new SignedXml(doc)
|
||||||
{
|
{
|
||||||
SigningKey = key,
|
SigningKey = key,
|
||||||
KeyInfo = keyInfo
|
KeyInfo = keyInfo
|
||||||
@ -131,9 +131,6 @@ namespace Hcs.Broker.Api.Request
|
|||||||
var signTransform = new CpXmlDsigEnvelopedSignatureTransform();
|
var signTransform = new CpXmlDsigEnvelopedSignatureTransform();
|
||||||
reference.AddTransform(signTransform);
|
reference.AddTransform(signTransform);
|
||||||
|
|
||||||
var c14nTransform = new CpXmlDsigC14NTransform();
|
|
||||||
reference.AddTransform(c14nTransform);
|
|
||||||
|
|
||||||
signedXml.AddReference(reference);
|
signedXml.AddReference(reference);
|
||||||
|
|
||||||
if (useDsPrefix)
|
if (useDsPrefix)
|
||||||
@ -147,7 +144,7 @@ namespace Hcs.Broker.Api.Request
|
|||||||
|
|
||||||
var element = doc.SelectNodes("//*[@Id='" + Constants.SIGNED_XML_ELEMENT_ID + "']")[0];
|
var element = doc.SelectNodes("//*[@Id='" + Constants.SIGNED_XML_ELEMENT_ID + "']")[0];
|
||||||
var xmlDigitalSignature = signedXml.GetXml();
|
var xmlDigitalSignature = signedXml.GetXml();
|
||||||
element.AppendChild(doc.ImportNode(xmlDigitalSignature, true));
|
element.PrependChild(doc.ImportNode(xmlDigitalSignature, true));
|
||||||
|
|
||||||
if (doc.FirstChild is XmlDeclaration)
|
if (doc.FirstChild is XmlDeclaration)
|
||||||
{
|
{
|
||||||
|
|||||||
240
Hcs.Broker/Api/Request/SignedXml.cs
Normal file
240
Hcs.Broker/Api/Request/SignedXml.cs
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
using CryptoPro.Security.Cryptography;
|
||||||
|
using CryptoPro.Security.Cryptography.X509Certificates;
|
||||||
|
using CryptoPro.Security.Cryptography.Xml;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace Hcs.Broker.Api.Request
|
||||||
|
{
|
||||||
|
internal class SignedXml(XmlDocument document) : CpXadesSignedXml(document)
|
||||||
|
{
|
||||||
|
private const string XADES_141_NAMESPACE_URL = "http://uri.etsi.org/01903/v1.4.1#";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OID алгоритма открытого ключа/цифровой подписи ГОСТ Р 34.10-2001
|
||||||
|
/// </summary>
|
||||||
|
private const string OID_CP_GOST_R3410EL = "1.2.643.2.2.19";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OID алгоритма открытого ключа/цифровой подписи ГОСТ Р 34.10-2012 256
|
||||||
|
/// </summary>
|
||||||
|
private const string OID_CP_GOST_R3410_12_256 = "1.2.643.7.1.1.1.1";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OID алгоритма открытого ключа/цифровой подписи ГОСТ Р 34.10-2012 512
|
||||||
|
/// </summary>
|
||||||
|
private const string OID_CP_GOST_R3410_12_512 = "1.2.643.7.1.1.1.2";
|
||||||
|
|
||||||
|
protected override void AddXadesProperties(
|
||||||
|
CpX509Certificate2 signingCertificate,
|
||||||
|
DateTime time,
|
||||||
|
string signatureId,
|
||||||
|
string objectId,
|
||||||
|
string? xmlDSigPrefix,
|
||||||
|
XadesPropertiesFlags xadesProperties)
|
||||||
|
{
|
||||||
|
if (_containingDocument == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("XmlDocument is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
var useCertificateV2 = xadesProperties.HasFlag(
|
||||||
|
XadesPropertiesFlags.UseSigningCertificateV2
|
||||||
|
);
|
||||||
|
var useCertificateV1 = xadesProperties.HasFlag(
|
||||||
|
XadesPropertiesFlags.UseSigningCertificateV1
|
||||||
|
);
|
||||||
|
if ((useCertificateV2 && useCertificateV1) || (!useCertificateV2 && !useCertificateV1))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Invalid flags");
|
||||||
|
}
|
||||||
|
|
||||||
|
var document = _containingDocument;
|
||||||
|
|
||||||
|
var parametersSignature = new CpReference
|
||||||
|
{
|
||||||
|
Uri = $"#{objectId}",
|
||||||
|
Type = XmlDsigSignatureProperties,
|
||||||
|
DigestMethod = XmlDsigGost3411_2012_256Url,
|
||||||
|
};
|
||||||
|
parametersSignature.AddTransform(new CpXmlDsigExcC14NTransform());
|
||||||
|
|
||||||
|
AddReference(parametersSignature);
|
||||||
|
|
||||||
|
var qualifyingPropertiesNode = document.CreateElement(
|
||||||
|
XadesPrefix,
|
||||||
|
"QualifyingProperties",
|
||||||
|
XadesNamespaceUrl
|
||||||
|
);
|
||||||
|
qualifyingPropertiesNode.SetAttribute("xmlns:xades141", XADES_141_NAMESPACE_URL);
|
||||||
|
qualifyingPropertiesNode.SetAttribute("Target", $"#{signatureId}");
|
||||||
|
|
||||||
|
var signedPropertiesNode = document.CreateElement(
|
||||||
|
XadesPrefix,
|
||||||
|
"SignedProperties",
|
||||||
|
XadesNamespaceUrl
|
||||||
|
);
|
||||||
|
signedPropertiesNode.SetAttribute("Id", objectId);
|
||||||
|
|
||||||
|
qualifyingPropertiesNode.AppendChild(signedPropertiesNode);
|
||||||
|
|
||||||
|
var signedSignaturePropertiesNode = document.CreateElement(
|
||||||
|
XadesPrefix,
|
||||||
|
"SignedSignatureProperties",
|
||||||
|
XadesNamespaceUrl
|
||||||
|
);
|
||||||
|
signedPropertiesNode.AppendChild(signedSignaturePropertiesNode);
|
||||||
|
|
||||||
|
var signingTime = document.CreateElement(XadesPrefix, "SigningTime", XadesNamespaceUrl);
|
||||||
|
signingTime.InnerText = time.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
|
||||||
|
|
||||||
|
signedSignaturePropertiesNode.AppendChild(signingTime);
|
||||||
|
|
||||||
|
var signingCertificateNodeName = useCertificateV2
|
||||||
|
? "SigningCertificateV2"
|
||||||
|
: "SigningCertificate";
|
||||||
|
var signingCertificateNode = document.CreateElement(
|
||||||
|
XadesPrefix,
|
||||||
|
signingCertificateNodeName,
|
||||||
|
XadesNamespaceUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
signedSignaturePropertiesNode.AppendChild(signingCertificateNode);
|
||||||
|
|
||||||
|
var certNode = document.CreateElement(XadesPrefix, "Cert", XadesNamespaceUrl);
|
||||||
|
signingCertificateNode.AppendChild(certNode);
|
||||||
|
|
||||||
|
var certDigestNode = document.CreateElement(
|
||||||
|
XadesPrefix,
|
||||||
|
"CertDigest",
|
||||||
|
XadesNamespaceUrl
|
||||||
|
);
|
||||||
|
certNode.AppendChild(certDigestNode);
|
||||||
|
|
||||||
|
var algIdString = signingCertificate.GetKeyAlgorithm();
|
||||||
|
(bool isGost, string? gostDigestAlgorithm) = algIdString switch
|
||||||
|
{
|
||||||
|
OID_CP_GOST_R3410EL => (true, XmlDsigGost3411Url),
|
||||||
|
OID_CP_GOST_R3410_12_256 => (
|
||||||
|
true,
|
||||||
|
XmlDsigGost3411_2012_256Url
|
||||||
|
),
|
||||||
|
OID_CP_GOST_R3410_12_512 => (
|
||||||
|
true,
|
||||||
|
XmlDsigGost3411_2012_512Url
|
||||||
|
),
|
||||||
|
_ => (false, null),
|
||||||
|
};
|
||||||
|
|
||||||
|
var digestMethodAlgorithmAtribute = document.CreateAttribute("Algorithm");
|
||||||
|
if (isGost)
|
||||||
|
{
|
||||||
|
digestMethodAlgorithmAtribute.InnerText = gostDigestAlgorithm!;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
digestMethodAlgorithmAtribute.InnerText = XmlDsigSHA1Url;
|
||||||
|
}
|
||||||
|
|
||||||
|
var digestMethod = document.CreateElement(
|
||||||
|
xmlDSigPrefix,
|
||||||
|
"DigestMethod",
|
||||||
|
XmlDsigNamespaceUrl
|
||||||
|
);
|
||||||
|
digestMethod.Attributes.Append(digestMethodAlgorithmAtribute);
|
||||||
|
|
||||||
|
certDigestNode.AppendChild(digestMethod);
|
||||||
|
|
||||||
|
var digestValue = document.CreateElement(
|
||||||
|
xmlDSigPrefix,
|
||||||
|
"DigestValue",
|
||||||
|
XmlDsigNamespaceUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isGost)
|
||||||
|
{
|
||||||
|
var hash =
|
||||||
|
CpCryptoConfig.CreateFromName(gostDigestAlgorithm!) as HashAlgorithm
|
||||||
|
?? throw new System.Exception(
|
||||||
|
$"Cannot find [{gostDigestAlgorithm}] alg in CpCryptoConfig!"
|
||||||
|
);
|
||||||
|
using (hash)
|
||||||
|
{
|
||||||
|
digestValue.InnerText = Convert.ToBase64String(
|
||||||
|
hash.ComputeHash(signingCertificate.RawData)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
digestValue.InnerText = Convert.ToBase64String(signingCertificate.GetCertHash());
|
||||||
|
}
|
||||||
|
|
||||||
|
certDigestNode.AppendChild(digestValue);
|
||||||
|
|
||||||
|
if (useCertificateV2)
|
||||||
|
{
|
||||||
|
var issuerSerialNode = document.CreateElement(
|
||||||
|
XadesPrefix,
|
||||||
|
"IssuerSerialV2",
|
||||||
|
XadesNamespaceUrl
|
||||||
|
);
|
||||||
|
issuerSerialNode.InnerText = Convert.ToBase64String(
|
||||||
|
X509EncodeIssuerAndSerialHelper.EncodeIssuerAndSerial(signingCertificate)
|
||||||
|
);
|
||||||
|
|
||||||
|
certNode.AppendChild(issuerSerialNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var issuerName = signingCertificate.IssuerName.Decode(X500DistinguishedNameFlags.DoNotUseQuotes);
|
||||||
|
var x509IssuerNameNode = document.CreateElement(
|
||||||
|
xmlDSigPrefix,
|
||||||
|
"X509IssuerName",
|
||||||
|
XmlDsigNamespaceUrl
|
||||||
|
);
|
||||||
|
x509IssuerNameNode.InnerText = GetOidRepresentation(issuerName);
|
||||||
|
|
||||||
|
var issuerSerialNode = document.CreateElement(
|
||||||
|
XadesPrefix,
|
||||||
|
"IssuerSerial",
|
||||||
|
XadesNamespaceUrl
|
||||||
|
);
|
||||||
|
issuerSerialNode.AppendChild(x509IssuerNameNode);
|
||||||
|
|
||||||
|
var x509SerialNumber = document.CreateElement(
|
||||||
|
xmlDSigPrefix,
|
||||||
|
"X509SerialNumber",
|
||||||
|
XmlDsigNamespaceUrl
|
||||||
|
);
|
||||||
|
x509SerialNumber.InnerText = BigInteger.Parse(signingCertificate.SerialNumber, NumberStyles.HexNumber).ToString();
|
||||||
|
|
||||||
|
issuerSerialNode.AppendChild(x509SerialNumber);
|
||||||
|
certNode.AppendChild(issuerSerialNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dataObject = new CpDataObject();
|
||||||
|
dataObject.Data = qualifyingPropertiesNode.SelectNodes(".");
|
||||||
|
|
||||||
|
AddObject(dataObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetOidRepresentation(string issuerName)
|
||||||
|
{
|
||||||
|
return issuerName
|
||||||
|
.Replace("\"", "\\\"")
|
||||||
|
.Replace("E=", "1.2.840.113549.1.9.1=")
|
||||||
|
.Replace("unstructuredName=", "1.2.840.113549.1.9.2=")
|
||||||
|
.Replace("ОГРН=", "1.2.643.100.1=")
|
||||||
|
.Replace("ИНН ЮЛ=", "1.2.643.100.4=")
|
||||||
|
.Replace("ИНН ФЛ=", "1.2.643.3.131.1.1=")
|
||||||
|
.Replace("ИНН=", "1.2.643.3.131.1.1=")
|
||||||
|
.Replace("СНИЛС=", "1.2.643.100.3=")
|
||||||
|
.Replace("ОГРНИП=", "1.2.643.100.5=")
|
||||||
|
.Replace("S=", "ST=");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user