Skip to content

Commit

Permalink
Improved the Xades signing
Browse files Browse the repository at this point in the history
  • Loading branch information
abdallahbeshi committed Dec 13, 2023
1 parent 16a3327 commit d7f07c3
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 121 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<RepositoryUrl>https://github.com/MewsSystems/fiscalizations</RepositoryUrl>
<Icon>https://raw.githubusercontent.com/msigut/eet/master/receipt.png</Icon>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageVersion>6.0.0</PackageVersion>
<PackageVersion>6.0.1</PackageVersion>
<LangVersion>12</LangVersion>
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>
Expand Down
21 changes: 12 additions & 9 deletions src/Basque/Mews.Fiscalizations.Basque/TicketBaiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Mews.Fiscalizations.Basque.Dto.Bizkaia;
using Mews.Fiscalizations.Basque.Model;
using Mews.Fiscalizations.Core.Xml;
using Mews.Fiscalizations.Core.Xml.Signing.Microsoft.Xades;

namespace Mews.Fiscalizations.Basque;

Expand Down Expand Up @@ -164,21 +165,23 @@ private SignatureDocument GetSignedInvoiceDocument(XmlDocument doc)
Region.Gipuzkoa, _ => "vSe1CH7eAFVkGN0X2Y7Nl9XGUoBnziDA5BGUSsyt8mg="
);

var signerRole = new SignerRole();
signerRole.CertifiedRoles.Add(Certificate);

var sigParams = new SignatureParameters(
var signatureParameters = new SignatureParameters(
xmlDocumentToSign: doc,
signer: new Signer(Certificate),
digestMethod: DigestMethod.SHA512,
signatureMethod: SignatureMethod.RSAwithSHA512,
digestMethod: DigestMethod.SHA256,
signatureMethod: SignatureMethod.RSAwithSHA256,
dataFormat: new DataFormat(MimeType: "text/xml"),
signerRole: signerRole,
signerRole: new SignerRole(Certificate.ToEnumerable()),
signingDate: DateTime.Now,
signaturePolicyInfo: new SignaturePolicyInfo(policyUri, policyHash, DigestMethod.SHA256, policyUri),
elementIdToSign: Guid.NewGuid().ToString()
);
var xadesService = new XadesService();
return xadesService.SignEnveloped(sigParams);
var signatureDocument = XadesService.SignEnveloped(signatureParameters);
var isValidSignature = signatureDocument.XadesSignature.XadesCheckSignature(XadesCheckSignatureMasks.AllChecks, DigestMethod.SHA256.GetHashAlgorithm());
if (!isValidSignature)
{
throw new Exception("Invalid signature.");
}
return signatureDocument;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<RepositoryUrl>https://github.com/MewsSystems/fiscalizations</RepositoryUrl>
<Icon>https://raw.githubusercontent.com/msigut/eet/master/receipt.png</Icon>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageVersion>6.0.2</PackageVersion>
<PackageVersion>6.0.3</PackageVersion>
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>

Expand All @@ -34,6 +34,13 @@
<PackageReference Include="System.Security.Cryptography.Xml" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
<None Remove="Xml\Signing\Microsoft.Xades\xmldsig-core-schema.xsd" />
<EmbeddedResource Include="Xml\Signing\Microsoft.Xades\xmldsig-core-schema.xsd" />
<None Remove="Xml\Signing\Microsoft.Xades\XAdES.xsd" />
<EmbeddedResource Include="Xml\Signing\Microsoft.Xades\XAdES.xsd" />
</ItemGroup>

<PropertyGroup>
<PackageId>Mews.Fiscalizations.Core</PackageId>
<Company>Mews</Company>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal enum KnownSignatureStandard
/// Bitmasks to indicate which checks need to be executed on the XAdES signature
/// </summary>
[Flags]
internal enum XadesCheckSignatureMasks : ulong
public enum XadesCheckSignatureMasks : ulong
{
/// <summary>
/// Check the signature of the underlying XMLDSIG signature
Expand Down Expand Up @@ -400,91 +400,88 @@ internal void AddXadesObject(XadesObject xadesObject)
/// with a bit in the mask has the same name as enum value name.</param>
/// <returns>If the function returns true the check was OK. If the
/// check fails an exception with a explanatory message is thrown.</returns>
private bool XadesCheckSignature(XadesCheckSignatureMasks xadesCheckSignatureMasks)
public bool XadesCheckSignature(XadesCheckSignatureMasks xadesCheckSignatureMasks, HashAlgorithm hashAlgorithm)
{
var retVal = true;
if (SignatureStandard != KnownSignatureStandard.Xades)
{
throw new Exception("SignatureStandard is not XAdES. CheckSignature returned: " + CheckSignature());
throw new Exception($"SignatureStandard is not XAdES. CheckSignature returned: {CheckSignature()}");
}
else
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckXmldsigSignature) != 0)
{
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckXmldsigSignature) != 0)
{
retVal &= CheckXmldsigSignature();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.ValidateAgainstSchema) != 0)
{
retVal &= ValidateAgainstSchema();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckSameCertificate) != 0)
{
retVal &= CheckSameCertificate();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckAllReferencesExistInAllDataObjectsTimeStamp) != 0)
{
retVal &= CheckAllReferencesExistInAllDataObjectsTimeStamp();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckAllHashDataInfosInIndividualDataObjectsTimeStamp) != 0)
{
retVal &= CheckAllHashDataInfosInIndividualDataObjectsTimeStamp();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckCounterSignatures) != 0)
{
retVal &= CheckCounterSignatures(xadesCheckSignatureMasks);
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckCounterSignaturesReference) != 0)
{
retVal &= CheckCounterSignaturesReference();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckObjectReferencesInCommitmentTypeIndication) != 0)
{
retVal &= CheckObjectReferencesInCommitmentTypeIndication();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckIfClaimedRolesOrCertifiedRolesPresentInSignerRole) != 0)
{
retVal &= CheckIfClaimedRolesOrCertifiedRolesPresentInSignerRole();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckHashDataInfoOfSignatureTimeStampPointsToSignatureValue) != 0)
{
retVal &= CheckHashDataInfoOfSignatureTimeStampPointsToSignatureValue();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckQualifyingPropertiesTarget) != 0)
{
retVal &= CheckQualifyingPropertiesTarget();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckQualifyingProperties) != 0)
{
retVal &= CheckQualifyingProperties();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckSigAndRefsTimeStampHashDataInfos) != 0)
{
retVal &= CheckSigAndRefsTimeStampHashDataInfos();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckRefsOnlyTimeStampHashDataInfos) != 0)
{
retVal &= CheckRefsOnlyTimeStampHashDataInfos();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckArchiveTimeStampHashDataInfos) != 0)
{
retVal &= CheckArchiveTimeStampHashDataInfos();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckXadesCIsXadesT) != 0)
{
retVal &= CheckXadesCIsXadesT();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckXadesXLIsXadesX) != 0)
{
retVal &= CheckXadesXLIsXadesX();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckCertificateValuesMatchCertificateRefs) != 0)
{
retVal &= CheckCertificateValuesMatchCertificateRefs();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckRevocationValuesMatchRevocationRefs) != 0)
{
retVal &= CheckRevocationValuesMatchRevocationRefs();
}
retVal &= CheckXmldsigSignature();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.ValidateAgainstSchema) != 0)
{
retVal &= ValidateAgainstSchema();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckSameCertificate) != 0)
{
retVal &= CheckSameCertificate(hashAlgorithm);
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckAllReferencesExistInAllDataObjectsTimeStamp) != 0)
{
retVal &= CheckAllReferencesExistInAllDataObjectsTimeStamp();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckAllHashDataInfosInIndividualDataObjectsTimeStamp) != 0)
{
retVal &= CheckAllHashDataInfosInIndividualDataObjectsTimeStamp();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckCounterSignatures) != 0)
{
retVal &= CheckCounterSignatures(xadesCheckSignatureMasks, hashAlgorithm);
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckCounterSignaturesReference) != 0)
{
retVal &= CheckCounterSignaturesReference();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckObjectReferencesInCommitmentTypeIndication) != 0)
{
retVal &= CheckObjectReferencesInCommitmentTypeIndication();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckIfClaimedRolesOrCertifiedRolesPresentInSignerRole) != 0)
{
retVal &= CheckIfClaimedRolesOrCertifiedRolesPresentInSignerRole();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckHashDataInfoOfSignatureTimeStampPointsToSignatureValue) != 0)
{
retVal &= CheckHashDataInfoOfSignatureTimeStampPointsToSignatureValue();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckQualifyingPropertiesTarget) != 0)
{
retVal &= CheckQualifyingPropertiesTarget();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckQualifyingProperties) != 0)
{
retVal &= CheckQualifyingProperties();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckSigAndRefsTimeStampHashDataInfos) != 0)
{
retVal &= CheckSigAndRefsTimeStampHashDataInfos();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckRefsOnlyTimeStampHashDataInfos) != 0)
{
retVal &= CheckRefsOnlyTimeStampHashDataInfos();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckArchiveTimeStampHashDataInfos) != 0)
{
retVal &= CheckArchiveTimeStampHashDataInfos();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckXadesCIsXadesT) != 0)
{
retVal &= CheckXadesCIsXadesT();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckXadesXLIsXadesX) != 0)
{
retVal &= CheckXadesXLIsXadesX();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckCertificateValuesMatchCertificateRefs) != 0)
{
retVal &= CheckCertificateValuesMatchCertificateRefs();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckRevocationValuesMatchRevocationRefs) != 0)
{
retVal &= CheckRevocationValuesMatchRevocationRefs();
}

return retVal;
Expand Down Expand Up @@ -512,7 +509,7 @@ private bool CheckXmldsigSignature()
var retVal = false;
IEnumerable<XmlAttribute> namespaces = GetAllNamespaces(GetSignatureElement());

if (KeyInfo == null)
if (KeyInfo is null)
{
var keyInfo = new KeyInfo();
X509Certificate xmldsigCert = GetSigningCertificate();
Expand Down Expand Up @@ -565,7 +562,7 @@ private bool CheckXmldsigSignature()
throw new CryptographicException("CheckXmldsigSignature() failed");
}

return retVal;
return true;
}

/// <summary>
Expand All @@ -582,14 +579,14 @@ private bool ValidateAgainstSchema()

try
{
var schemaStream = assembly.GetManifestResourceStream("Microsoft.Xades.xmldsig-core-schema.xsd");
var xmlSchema = XmlSchema.Read(schemaStream, new ValidationEventHandler(SchemaValidationHandler));
var schemaStream = assembly.GetManifestResourceStream("Mews.Fiscalizations.Core.Xml.Signing.Microsoft.Xades.xmldsig-core-schema.xsd");
var xmlSchema = XmlSchema.Read(schemaStream, SchemaValidationHandler);
schemaSet.Add(xmlSchema);
schemaStream.Close();


schemaStream = assembly.GetManifestResourceStream("Microsoft.Xades.XAdES.xsd");
xmlSchema = XmlSchema.Read(schemaStream, new ValidationEventHandler(SchemaValidationHandler));
schemaStream = assembly.GetManifestResourceStream("Mews.Fiscalizations.Core.Xml.Signing.Microsoft.Xades.XAdES.xsd");
xmlSchema = XmlSchema.Read(schemaStream, SchemaValidationHandler);
schemaSet.Add(xmlSchema);
schemaStream.Close();

Expand All @@ -604,7 +601,7 @@ private bool ValidateAgainstSchema()
}

var xmlReaderSettings = new XmlReaderSettings();
xmlReaderSettings.ValidationEventHandler += new ValidationEventHandler(XmlValidationHandler);
xmlReaderSettings.ValidationEventHandler += XmlValidationHandler;
xmlReaderSettings.ValidationType = ValidationType.Schema;
xmlReaderSettings.Schemas = schemaSet;
xmlReaderSettings.ConformanceLevel = ConformanceLevel.Auto;
Expand All @@ -619,10 +616,13 @@ private bool ValidateAgainstSchema()
var reader = XmlReader.Create(txtReader, xmlReaderSettings);
try
{
while (reader.Read()) ;
while (reader.Read())
{
}

if (validationErrorOccurred)
{
throw new CryptographicException("Schema validation error: " + validationErrorDescription);
throw new CryptographicException($"Schema validation error: {validationErrorDescription}");
}
}
catch (Exception exception)
Expand All @@ -640,12 +640,12 @@ private bool ValidateAgainstSchema()
/// Check to see if first XMLDSIG certificate has same hashvalue as first XAdES SignatureCertificate
/// </summary>
/// <returns>If the function returns true the check was OK</returns>
private bool CheckSameCertificate()
private bool CheckSameCertificate(HashAlgorithm hashAlgorithm)
{
X509Certificate xmldsigCert = GetSigningCertificate();
var xmldsigCertHash = Convert.ToBase64String(xmldsigCert.GetCertHash());

var xadesSigningCertificateCollection = XadesObject.QualifyingProperties.SignedProperties.SignedSignatureProperties.SigningCertificate.CertCollection;
var xmldsigCert = GetSigningCertificate();
var xmldsigCertHash = Convert.ToBase64String(hashAlgorithm.ComputeHash(xmldsigCert.GetRawCertData()));

if (xadesSigningCertificateCollection.Count <= 0)
{
throw new CryptographicException("Certificate not found in SigningCertificate element while doing CheckSameCertificate()");
Expand Down Expand Up @@ -713,7 +713,7 @@ private bool CheckAllHashDataInfosInIndividualDataObjectsTimeStamp()
/// </summary>
/// <param name="counterSignatureMask">Check mask applied to counter signatures</param>
/// <returns>If the function returns true the check was OK</returns>
private bool CheckCounterSignatures(XadesCheckSignatureMasks counterSignatureMask)
private bool CheckCounterSignatures(XadesCheckSignatureMasks counterSignatureMask, HashAlgorithm hashAlgorithm)
{
var retVal = true;
var counterSignatureCollection = XadesObject.QualifyingProperties.UnsignedProperties.UnsignedSignatureProperties.CounterSignatureCollection;
Expand All @@ -722,7 +722,7 @@ private bool CheckCounterSignatures(XadesCheckSignatureMasks counterSignatureMas
var counterSignature = counterSignatureCollection[counterSignatureCounter];
if (counterSignature.SignatureStandard == KnownSignatureStandard.Xades)
{
retVal &= counterSignature.XadesCheckSignature(counterSignatureMask);
retVal &= counterSignature.XadesCheckSignature(counterSignatureMask, hashAlgorithm);
}
else
{
Expand Down Expand Up @@ -1433,7 +1433,7 @@ private bool CheckDigestedReferences()
{
var references = m_signature.SignedInfo.References;

var System_Security_Assembly = Assembly.Load("System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
var System_Security_Assembly = Assembly.Load("System.Security.Cryptography.Xml");
var CanonicalXmlNodeList_Type = System_Security_Assembly.GetType("System.Security.Cryptography.Xml.CanonicalXmlNodeList");
var CanonicalXmlNodeList_Constructor = CanonicalXmlNodeList_Type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { }, null);

Expand Down Expand Up @@ -1475,10 +1475,6 @@ private bool CheckSignedInfo(AsymmetricAlgorithm key)
throw new CryptographicException("signature description can't be created");
}

var ta = Type.GetType(signatureDescription.KeyAlgorithm);
var tb = key.GetType();
if ((ta != tb) && !ta.IsSubclassOf(tb) && !tb.IsSubclassOf(ta)) return false;

var hashAlgorithm = signatureDescription.CreateDigest();
if (hashAlgorithm == null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

namespace Mews.Fiscalizations.Core.Xml.Signing.Signature.Parameters;

public sealed class SignerRole(List<X509Certificate> certifiedRoles = null, List<string> claimedRoles = null)
public sealed class SignerRole(IEnumerable<X509Certificate2> certifiedRoles = null, IEnumerable<string> claimedRoles = null)
{
public List<X509Certificate> CertifiedRoles { get; } = certifiedRoles ?? [];
public IReadOnlyList<X509Certificate2> CertifiedRoles { get; } = certifiedRoles?.ToReadOnlyList() ?? [];

public List<string> ClaimedRoles { get; } = claimedRoles ?? [];
public IReadOnlyList<string> ClaimedRoles { get; } = claimedRoles?.ToReadOnlyList() ?? [];
}
Loading

0 comments on commit d7f07c3

Please sign in to comment.