// XadesSignedXml.cs
//
// XAdES Starter Kit for Microsoft .NET 3.5 (and above)
// 2010 Microsoft France
// Published under the CECILL-B Free Software license agreement.
// (http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt)
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
// WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// THE ENTIRE RISK OF USE OR RESULTS IN CONNECTION WITH THE USE OF THIS CODE
// AND INFORMATION REMAINS WITH THE USER.
using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.Xml;
using System.Xml.Schema;
namespace Microsoft.Xades
{
///
/// Types of signature standards that can be contained in XadesSignedXml class instance
///
public enum KnownSignatureStandard
{
///
/// XML Digital Signature (XMLDSIG)
///
XmlDsig,
///
/// XML Advanced Electronic Signature (XAdES)
///
Xades
}
///
/// Bitmasks to indicate which checks need to be executed on the XAdES signature
///
[FlagsAttribute]
public enum XadesCheckSignatureMasks : ulong
{
///
/// Check the signature of the underlying XMLDSIG signature
///
CheckXmldsigSignature = 0x01,
///
/// Validate the XML representation of the signature against the XAdES and XMLDSIG schemas
///
ValidateAgainstSchema = 0x02,
///
/// Check to see if first XMLDSIG certificate has same hashvalue as first XAdES SignatureCertificate
///
CheckSameCertificate = 0x04,
///
/// Check if there is a HashDataInfo for each reference if there is a AllDataObjectsTimeStamp
///
CheckAllReferencesExistInAllDataObjectsTimeStamp = 0x08,
///
/// Check if the HashDataInfo of each IndividualDataObjectsTimeStamp points to existing Reference
///
CheckAllHashDataInfosInIndividualDataObjectsTimeStamp = 0x10,
///
/// Perform XAdES checks on contained counter signatures
///
CheckCounterSignatures = 0x20,
///
/// Counter signatures should all contain a reference to the parent signature SignatureValue element
///
CheckCounterSignaturesReference = 0x40,
///
/// Check if each ObjectReference in CommitmentTypeIndication points to Reference element
///
CheckObjectReferencesInCommitmentTypeIndication = 0x80,
///
/// Check if at least ClaimedRoles or CertifiedRoles present in SignerRole
///
CheckIfClaimedRolesOrCertifiedRolesPresentInSignerRole = 0x0100,
///
/// Check if HashDataInfo of SignatureTimeStamp points to SignatureValue
///
CheckHashDataInfoOfSignatureTimeStampPointsToSignatureValue = 0x0200,
///
/// Check if the QualifyingProperties Target attribute points to the signature element
///
CheckQualifyingPropertiesTarget = 0x0400,
///
/// Check that QualifyingProperties occur in one Object, check that there is only one QualifyingProperties and that signed properties occur in one QualifyingProperties element
///
CheckQualifyingProperties = 0x0800,
///
/// Check if all required HashDataInfos are present on SigAndRefsTimeStamp
///
CheckSigAndRefsTimeStampHashDataInfos = 0x1000,
///
/// Check if all required HashDataInfos are present on RefsOnlyTimeStamp
///
CheckRefsOnlyTimeStampHashDataInfos = 0x2000,
///
/// Check if all required HashDataInfos are present on ArchiveTimeStamp
///
CheckArchiveTimeStampHashDataInfos = 0x4000,
///
/// Check if a XAdES-C signature is also a XAdES-T signature
///
CheckXadesCIsXadesT = 0x8000,
///
/// Check if a XAdES-XL signature is also a XAdES-X signature
///
CheckXadesXLIsXadesX = 0x010000,
///
/// Check if CertificateValues match CertificateRefs
///
CheckCertificateValuesMatchCertificateRefs = 0x020000,
///
/// Check if RevocationValues match RevocationRefs
///
CheckRevocationValuesMatchRevocationRefs = 0x040000,
///
/// Do all known tests on XAdES signature
///
AllChecks = 0xFFFFFF
}
///
/// Facade class for the XAdES signature library. The class inherits from
/// the System.Security.Cryptography.Xml.SignedXml class and is backwards
/// compatible with it, so this class can host xmldsig signatures and XAdES
/// signatures. The property SignatureStandard will indicate the type of the
/// signature: XMLDSIG or XAdES.
///
public class XadesSignedXml : System.Security.Cryptography.Xml.SignedXml
{
#region Constants
///
/// The XAdES XML namespace URI
///
public const string XadesNamespaceUri = "http://uri.etsi.org/01903/v1.3.2#";
///
/// Mandated type name for the Uri reference to the SignedProperties element
///
// TODO: Проверить комментарий
//public const string SignedPropertiesType = "http://uri.etsi.org/01903/v1.3.2#SignedProperties";
public const string SignedPropertiesType = "http://uri.etsi.org/01903#SignedProperties";
#endregion
#region Private variables
private static readonly string[] idAttrs = new string[]
{
"_id",
"_Id",
"_ID",
"id",
"Id",
"ID",
"iD"
};
private KnownSignatureStandard signatureStandard;
private XmlDocument cachedXadesObjectDocument;
private string signedPropertiesIdBuffer;
private string signatureValueId;
private bool validationErrorOccurred;
private string validationErrorDescription;
// TODO: Проверить комментарий
//private string signedInfoIdBuffer = null;
#endregion
#region Public properties
///
/// Property indicating the type of signature (XmlDsig or XAdES)
///
public KnownSignatureStandard SignatureStandard
{
get
{
return this.signatureStandard;
}
}
///
/// Read-only property containing XAdES information
///
public XadesObject XadesObject
{
get
{
XadesObject retVal = new XadesObject();
retVal.LoadXml(this.GetXadesObjectElement(this.GetXml()), this.GetXml());
return retVal;
}
}
///
/// Setting this property will add an ID attribute to the SignatureValue element.
/// This is required when constructing a XAdES-T signature.
///
public string SignatureValueId
{
get
{
return this.signatureValueId;
}
set
{
this.signatureValueId = value;
}
}
///
/// This property allows to access and modify the unsigned properties
/// after the XAdES object has been added to the signature.
/// Because the unsigned properties are part of a location in the
/// signature that is not used when computing the signature, it is save
/// to modify them even after the XMLDSIG signature has been computed.
/// This is needed when XAdES objects that depend on the XMLDSIG
/// signature value need to be added to the signature. The
/// SignatureTimeStamp element is such a property, it can only be
/// created when the XMLDSIG signature has been computed.
///
public UnsignedProperties UnsignedProperties
{
get
{
XmlElement dataObjectXmlElement;
System.Security.Cryptography.Xml.DataObject xadesDataObject;
XmlNamespaceManager xmlNamespaceManager;
XmlNodeList xmlNodeList;
UnsignedProperties retVal;
retVal = new UnsignedProperties();
xadesDataObject = this.GetXadesDataObject();
if (xadesDataObject != null)
{
dataObjectXmlElement = xadesDataObject.GetXml();
xmlNamespaceManager = new XmlNamespaceManager(dataObjectXmlElement.OwnerDocument.NameTable);
xmlNamespaceManager.AddNamespace("xsd", XadesSignedXml.XadesNamespaceUri);
xmlNodeList = dataObjectXmlElement.SelectNodes("xsd:QualifyingProperties/xsd:UnsignedProperties", xmlNamespaceManager);
if (xmlNodeList.Count != 0)
{
retVal = new UnsignedProperties();
retVal.LoadXml((XmlElement)xmlNodeList[0], (XmlElement)xmlNodeList[0]);
}
}
else
{
throw new CryptographicException("XAdES object not found. Use AddXadesObject() before accessing UnsignedProperties.");
}
return retVal;
}
set
{
XmlElement dataObjectXmlElement = null;
System.Security.Cryptography.Xml.DataObject xadesDataObject, newXadesDataObject;
XmlNamespaceManager xmlNamespaceManager;
XmlNodeList qualifyingPropertiesXmlNodeList;
XmlNodeList unsignedPropertiesXmlNodeList;
xadesDataObject = this.GetXadesDataObject();
if (xadesDataObject != null)
{
dataObjectXmlElement = xadesDataObject.GetXml();
xmlNamespaceManager = new XmlNamespaceManager(dataObjectXmlElement.OwnerDocument.NameTable);
xmlNamespaceManager.AddNamespace("xsd", XadesSignedXml.XadesNamespaceUri);
qualifyingPropertiesXmlNodeList = dataObjectXmlElement.SelectNodes("xsd:QualifyingProperties", xmlNamespaceManager);
unsignedPropertiesXmlNodeList = dataObjectXmlElement.SelectNodes("xsd:QualifyingProperties/xsd:UnsignedProperties", xmlNamespaceManager);
if (unsignedPropertiesXmlNodeList.Count != 0)
{
qualifyingPropertiesXmlNodeList[0].RemoveChild(unsignedPropertiesXmlNodeList[0]);
}
qualifyingPropertiesXmlNodeList[0].AppendChild(dataObjectXmlElement.OwnerDocument.ImportNode(value.GetXml(), true));
newXadesDataObject = new DataObject();
newXadesDataObject.LoadXml(dataObjectXmlElement);
xadesDataObject.Data = newXadesDataObject.Data;
}
else
{
throw new CryptographicException("XAdES object not found. Use AddXadesObject() before accessing UnsignedProperties.");
}
}
}
///
/// This property contains xml document node id,
/// which will be singed by XAdES
///
public string SignedElementId { get; set; }
#endregion
#region Constructors
///
/// Default constructor for the XadesSignedXml class
///
public XadesSignedXml() : base()
{
this.cachedXadesObjectDocument = null;
this.signatureStandard = KnownSignatureStandard.XmlDsig;
}
///
/// Constructor for the XadesSignedXml class
///
/// XmlElement used to create the instance
public XadesSignedXml(XmlElement signatureElement) : base(signatureElement)
{
this.cachedXadesObjectDocument = null;
}
///
/// Constructor for the XadesSignedXml class
///
/// XmlDocument used to create the instance
public XadesSignedXml(System.Xml.XmlDocument signatureDocument) : base(signatureDocument)
{
this.cachedXadesObjectDocument = null;
}
///
/// Constructor for the XadesSignedXml class
///
/// XmlDocument used to create the instance
/// XmlDocument signed node identifier
public XadesSignedXml(System.Xml.XmlDocument signatureDocument, string signedElementId) : base(signatureDocument)
{
this.cachedXadesObjectDocument = null;
this.SignedElementId = signedElementId;
}
#endregion
#region Public methods
///
/// Load state from an XML element
///
/// The XML element from which to load the XadesSignedXml state
public new void LoadXml(System.Xml.XmlElement xmlElement)
{
this.cachedXadesObjectDocument = null;
this.signatureValueId = null;
base.LoadXml(xmlElement);
XmlNode idAttribute = xmlElement.Attributes.GetNamedItem("Id");
if (idAttribute != null)
{
this.Signature.Id = idAttribute.Value;
}
this.SetSignatureStandard(xmlElement);
XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(xmlElement.OwnerDocument.NameTable);
xmlNamespaceManager.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
XmlNodeList xmlNodeList = xmlElement.SelectNodes("ds:SignatureValue", xmlNamespaceManager);
if (xmlNodeList.Count > 0)
{
if (((XmlElement)xmlNodeList[0]).HasAttribute("Id"))
{
this.signatureValueId = ((XmlElement)xmlNodeList[0]).Attributes["Id"].Value;
}
}
}
///
/// Returns the XML representation of the this object
///
/// XML element containing the state of this object
public new XmlElement GetXml()
{
XmlElement retVal;
XmlNodeList xmlNodeList;
XmlNamespaceManager xmlNamespaceManager;
retVal = base.GetXml();
if (this.signatureValueId != null && this.signatureValueId != "")
{
//Id on Signature value is needed for XAdES-T. We inject it here.
xmlNamespaceManager = new XmlNamespaceManager(retVal.OwnerDocument.NameTable);
xmlNamespaceManager.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
xmlNodeList = retVal.SelectNodes("ds:SignatureValue", xmlNamespaceManager);
if (xmlNodeList.Count > 0)
{
((XmlElement)xmlNodeList[0]).SetAttribute("Id", this.signatureValueId);
}
}
// Add "ds" namespace prefix to all XmlDsig nodes in the signature
SetPrefix("ds", retVal);
return retVal;
}
///
/// Overridden virtual method to be able to find the nested SignedProperties
/// element inside of the XAdES object
///
/// Document in which to find the Id
/// Value of the Id to look for
/// XmlElement with requested Id
public override XmlElement GetIdElement(XmlDocument xmlDocument, string idValue)
{
XmlElement retVal = base.GetIdElement(xmlDocument, idValue);
if (retVal != null)
return retVal;
foreach (var customId in idAttrs)
{
var found = xmlDocument.SelectSingleNode("//*[@" + customId + "=\"" + idValue + "\"]") as XmlElement;
if (found != null)
{
return found;
}
}
if (Signature != null && Signature.SignedInfo != null && Signature.SignatureValue != null)
{
var signature = new XmlDocument();
signature.AppendChild(signature.ImportNode(Signature.GetXml(), true));
signature.DocumentElement.SetAttribute("xmlns:ds", SignedXml.XmlDsigNamespaceUrl);
retVal = base.GetIdElement(signature, idValue);
if (retVal != null)
{
return retVal;
}
// If not, search for custom ids
foreach (string idAttr in idAttrs)
{
retVal = signature.SelectSingleNode("//*[@" + idAttr + "=\"" + idValue + "\"]") as XmlElement;
if (retVal != null)
{
return retVal;
}
}
}
if (idValue == this.signedPropertiesIdBuffer)
{
var xmlDocumentCloned = new XmlDocument();
xmlDocumentCloned.LoadXml(xmlDocument.OuterXml);
var signedDataContainer = this.GetIdElement(xmlDocumentCloned, SignedElementId);
signedDataContainer.InsertBefore(xmlDocumentCloned.ImportNode(cachedXadesObjectDocument.DocumentElement, true), signedDataContainer.FirstChild);
// TODO: Проверить комментарий
//xmlDocumentCloned.DocumentElement.AppendChild(xmlDocumentCloned.ImportNode(cachedXadesObjectDocument.DocumentElement, true));
retVal = base.GetIdElement(xmlDocumentCloned, idValue);
if (retVal != null)
{
return retVal;
}
// If not, search for custom ids
foreach (string idAttr in idAttrs)
{
retVal = this.cachedXadesObjectDocument.SelectSingleNode("//*[@" + idAttr + "=\"" + idValue + "\"]") as XmlElement;
if (retVal != null)
{
break;
}
}
}
else
{
if (xmlDocument != null)
{
retVal = base.GetIdElement(xmlDocument, idValue);
if (retVal != null)
{
return retVal;
}
// If not, search for custom ids
foreach (string idAttr in idAttrs)
{
retVal = xmlDocument.SelectSingleNode("//*[@" + idAttr + "=\"" + idValue + "\"]") as XmlElement;
if (retVal != null)
{
break;
}
}
}
}
return retVal;
}
///
/// Add a XAdES object to the signature
///
/// XAdES object to add to signature
public void AddXadesObject(XadesObject xadesObject)
{
Reference reference;
DataObject dataObject;
XmlElement bufferXmlElement;
if (this.SignatureStandard != KnownSignatureStandard.Xades)
{
dataObject = new DataObject();
dataObject.Id = xadesObject.Id;
dataObject.Data = xadesObject.GetXml().ChildNodes;
this.AddObject(dataObject);
reference = new Reference();
reference.DigestMethod = "http://www.w3.org/2001/04/xmldsig-more#gostr3411";
signedPropertiesIdBuffer = xadesObject.QualifyingProperties.SignedProperties.Id;
reference.Uri = "#" + signedPropertiesIdBuffer;
reference.Type = SignedPropertiesType;
this.AddReference(reference);
this.cachedXadesObjectDocument = new XmlDocument();
bufferXmlElement = xadesObject.GetXml();
// Add "ds" namespace prefix to all XmlDsig nodes in the XAdES object
SetPrefix("ds", bufferXmlElement);
this.cachedXadesObjectDocument.PreserveWhitespace = true;
this.cachedXadesObjectDocument.LoadXml(bufferXmlElement.OuterXml);
this.signatureStandard = KnownSignatureStandard.Xades;
}
else
{
throw new CryptographicException("Can't add XAdES object, the signature already contains a XAdES object");
}
}
///
/// Additional tests for XAdES signatures. These tests focus on
/// XMLDSIG verification and correct form of the XAdES XML structure
/// (schema validation and completeness as defined by the XAdES standard).
///
///
/// Because of the fact that the XAdES library is intentionally
/// independent of standards like TSP (RFC3161) or OCSP (RFC2560),
/// these tests do NOT include any verification of timestamps nor OCSP
/// responses.
/// These checks are important and have to be done in the application
/// built on top of the XAdES library.
///
/// Thrown when the signature is not
/// a XAdES signature. SignatureStandard should be equal to
/// KnownSignatureStandard.Xades.
/// Use the CheckSignature method for non-XAdES signatures.
/// Bitmask to indicate which
/// tests need to be done. This function will call a public virtual
/// methods for each bit that has been set in this mask.
/// See the XadesCheckSignatureMasks
/// enum for the bitmask definitions. The virtual test method associated
/// with a bit in the mask has the same name as enum value name.
/// If the function returns true the check was OK. If the
/// check fails an exception with a explanatory message is thrown.
public bool XadesCheckSignature(XadesCheckSignatureMasks xadesCheckSignatureMasks)
{
bool retVal;
retVal = true;
if (this.SignatureStandard != KnownSignatureStandard.Xades)
{
throw new Exception("SignatureStandard is not XAdES. CheckSignature returned: " + this.CheckSignature());
}
else
{
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckXmldsigSignature) != 0)
{
retVal &= this.CheckXmldsigSignature();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.ValidateAgainstSchema) != 0)
{
retVal &= this.ValidateAgainstSchema();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckSameCertificate) != 0)
{
retVal &= this.CheckSameCertificate();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckAllReferencesExistInAllDataObjectsTimeStamp) != 0)
{
retVal &= this.CheckAllReferencesExistInAllDataObjectsTimeStamp();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckAllHashDataInfosInIndividualDataObjectsTimeStamp) != 0)
{
retVal &= this.CheckAllHashDataInfosInIndividualDataObjectsTimeStamp();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckCounterSignatures) != 0)
{
retVal &= this.CheckCounterSignatures(xadesCheckSignatureMasks);
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckCounterSignaturesReference) != 0)
{
retVal &= this.CheckCounterSignaturesReference();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckObjectReferencesInCommitmentTypeIndication) != 0)
{
retVal &= this.CheckObjectReferencesInCommitmentTypeIndication();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckIfClaimedRolesOrCertifiedRolesPresentInSignerRole) != 0)
{
retVal &= this.CheckIfClaimedRolesOrCertifiedRolesPresentInSignerRole();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckHashDataInfoOfSignatureTimeStampPointsToSignatureValue) != 0)
{
retVal &= this.CheckHashDataInfoOfSignatureTimeStampPointsToSignatureValue();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckQualifyingPropertiesTarget) != 0)
{
retVal &= this.CheckQualifyingPropertiesTarget();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckQualifyingProperties) != 0)
{
retVal &= this.CheckQualifyingProperties();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckSigAndRefsTimeStampHashDataInfos) != 0)
{
retVal &= this.CheckSigAndRefsTimeStampHashDataInfos();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckRefsOnlyTimeStampHashDataInfos) != 0)
{
retVal &= this.CheckRefsOnlyTimeStampHashDataInfos();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckArchiveTimeStampHashDataInfos) != 0)
{
retVal &= this.CheckArchiveTimeStampHashDataInfos();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckXadesCIsXadesT) != 0)
{
retVal &= this.CheckXadesCIsXadesT();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckXadesXLIsXadesX) != 0)
{
retVal &= this.CheckXadesXLIsXadesX();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckCertificateValuesMatchCertificateRefs) != 0)
{
retVal &= this.CheckCertificateValuesMatchCertificateRefs();
}
if ((xadesCheckSignatureMasks & XadesCheckSignatureMasks.CheckRevocationValuesMatchRevocationRefs) != 0)
{
retVal &= this.CheckRevocationValuesMatchRevocationRefs();
}
}
return retVal;
}
#region XadesCheckSignature routines
///
/// Check the signature of the underlying XMLDSIG signature
///
/// If the function returns true the check was OK
public virtual bool CheckXmldsigSignature()
{
bool retVal = false;
// TODO: Проверить комментарий
//KeyInfo keyInfo = new KeyInfo();
//X509Certificate xmldsigCert = new X509Certificate(System.Text.Encoding.ASCII.GetBytes(this.KeyInfo.GetXml().InnerText));
//keyInfo.AddClause(new KeyInfoX509Data(xmldsigCert));
//this.KeyInfo = keyInfo;
retVal = this.CheckSignature();
if (retVal == false)
{
throw new CryptographicException("CheckXmldsigSignature() failed");
}
return retVal;
}
///
/// Validate the XML representation of the signature against the XAdES and XMLDSIG schemas
///
/// If the function returns true the check was OK
public virtual bool ValidateAgainstSchema()
{
bool retValue = false;
Assembly assembly = Assembly.GetExecutingAssembly();
XmlSchemaSet schemaSet = new XmlSchemaSet();
XmlSchema xmlSchema;
Stream schemaStream;
NameTable xadesNameTable;
XmlNamespaceManager xmlNamespaceManager;
XmlParserContext xmlParserContext;
this.validationErrorOccurred = false;
this.validationErrorDescription = "";
try
{
schemaStream = assembly.GetManifestResourceStream("Microsoft.Xades.xmldsig-core-schema.xsd");
xmlSchema = XmlSchema.Read(schemaStream, new ValidationEventHandler(this.SchemaValidationHandler));
schemaSet.Add(xmlSchema);
schemaStream.Close();
schemaStream = assembly.GetManifestResourceStream("Microsoft.Xades.XAdES.xsd");
xmlSchema = XmlSchema.Read(schemaStream, new ValidationEventHandler(this.SchemaValidationHandler));
schemaSet.Add(xmlSchema);
schemaStream.Close();
if (this.validationErrorOccurred)
{
throw new CryptographicException("Schema read validation error: " + this.validationErrorDescription);
}
}
catch (Exception exception)
{
throw new CryptographicException("Problem during access of validation schemas", exception);
}
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
xmlReaderSettings.ValidationEventHandler += new ValidationEventHandler(this.XmlValidationHandler);
xmlReaderSettings.ValidationType = ValidationType.Schema;
xmlReaderSettings.Schemas = schemaSet;
xmlReaderSettings.ConformanceLevel = ConformanceLevel.Auto;
xadesNameTable = new NameTable();
xmlNamespaceManager = new XmlNamespaceManager(xadesNameTable);
xmlNamespaceManager.AddNamespace("xsd", XadesSignedXml.XadesNamespaceUri);
xmlParserContext = new XmlParserContext(null, xmlNamespaceManager, null, XmlSpace.None);
XmlTextReader txtReader = new XmlTextReader(this.GetXml().OuterXml, XmlNodeType.Element, xmlParserContext);
XmlReader reader = XmlReader.Create(txtReader, xmlReaderSettings);
try
{
while (reader.Read()) ;
if (this.validationErrorOccurred)
{
throw new CryptographicException("Schema validation error: " + this.validationErrorDescription);
}
}
catch (Exception exception)
{
throw new CryptographicException("Schema validation error", exception);
}
finally
{
reader.Close();
}
retValue = true;
return retValue;
}
///
/// Check to see if first XMLDSIG certificate has same hashvalue as first XAdES SignatureCertificate
///
/// If the function returns true the check was OK
public virtual bool CheckSameCertificate()
{
bool retVal = false;
// TODO: Проверить комментарий
//KeyInfoX509Data keyInfoX509Data = new KeyInfoX509Data();
//keyInfoX509Data.LoadXml(this.KeyInfo.GetXml());
//if (keyInfoX509Data.Certificates.Count <= 0)
//{
// throw new CryptographicException("Certificate not found in XMLDSIG signature while doing CheckSameCertificate()");
//}
//string xmldsigCertHash = Convert.ToBase64String(((X509Certificate)keyInfoX509Data.Certificates[0]).GetCertHash());
X509Certificate xmldsigCert = new X509Certificate(System.Text.Encoding.ASCII.GetBytes(this.KeyInfo.GetXml().InnerText));
string xmldsigCertHash = Convert.ToBase64String(xmldsigCert.GetCertHash());
CertCollection xadesSigningCertificateCollection = this.XadesObject.QualifyingProperties.SignedProperties.SignedSignatureProperties.SigningCertificate.CertCollection;
if (xadesSigningCertificateCollection.Count <= 0)
{
throw new CryptographicException("Certificate not found in SigningCertificate element while doing CheckSameCertificate()");
}
string xadesCertHash = Convert.ToBase64String(((Cert)xadesSigningCertificateCollection[0]).CertDigest.DigestValue);
if (String.Compare(xmldsigCertHash, xadesCertHash, true, CultureInfo.InvariantCulture) != 0)
{
throw new CryptographicException("Certificate in XMLDSIG signature doesn't match certificate in SigningCertificate element");
}
retVal = true;
return retVal;
}
///
/// Check if there is a HashDataInfo for each reference if there is a AllDataObjectsTimeStamp
///
/// If the function returns true the check was OK
public virtual bool CheckAllReferencesExistInAllDataObjectsTimeStamp()
{
AllDataObjectsTimeStampCollection allDataObjectsTimeStampCollection;
bool allHashDataInfosExist;
TimeStamp timeStamp;
int timeStampCounter;
bool retVal;
allHashDataInfosExist = true;
retVal = false;
allDataObjectsTimeStampCollection = this.XadesObject.QualifyingProperties.SignedProperties.SignedDataObjectProperties.AllDataObjectsTimeStampCollection;
if (allDataObjectsTimeStampCollection.Count > 0)
{
for (timeStampCounter = 0; allHashDataInfosExist && (timeStampCounter < allDataObjectsTimeStampCollection.Count); timeStampCounter++)
{
timeStamp = allDataObjectsTimeStampCollection[timeStampCounter];
allHashDataInfosExist &= this.CheckHashDataInfosForTimeStamp(timeStamp);
}
if (!allHashDataInfosExist)
{
throw new CryptographicException("At least one HashDataInfo is missing in AllDataObjectsTimeStamp element");
}
}
retVal = true;
return retVal;
}
///
/// Check if the HashDataInfo of each IndividualDataObjectsTimeStamp points to existing Reference
///
/// If the function returns true the check was OK
public virtual bool CheckAllHashDataInfosInIndividualDataObjectsTimeStamp()
{
IndividualDataObjectsTimeStampCollection individualDataObjectsTimeStampCollection;
bool hashDataInfoExists;
TimeStamp timeStamp;
int timeStampCounter;
bool retVal;
hashDataInfoExists = true;
retVal = false;
individualDataObjectsTimeStampCollection = this.XadesObject.QualifyingProperties.SignedProperties.SignedDataObjectProperties.IndividualDataObjectsTimeStampCollection;
if (individualDataObjectsTimeStampCollection.Count > 0)
{
for (timeStampCounter = 0; hashDataInfoExists && (timeStampCounter < individualDataObjectsTimeStampCollection.Count); timeStampCounter++)
{
timeStamp = individualDataObjectsTimeStampCollection[timeStampCounter];
hashDataInfoExists &= this.CheckHashDataInfosExist(timeStamp);
}
if (hashDataInfoExists == false)
{
throw new CryptographicException("At least one HashDataInfo is pointing to non-existing reference in IndividualDataObjectsTimeStamp element");
}
}
retVal = true;
return retVal;
}
///
/// Perform XAdES checks on contained counter signatures. If couter signature is XMLDSIG, only XMLDSIG check (CheckSignature()) is done.
///
/// Check mask applied to counter signatures
/// If the function returns true the check was OK
public virtual bool CheckCounterSignatures(XadesCheckSignatureMasks counterSignatureMask)
{
CounterSignatureCollection counterSignatureCollection;
XadesSignedXml counterSignature;
bool retVal;
retVal = true;
counterSignatureCollection = this.XadesObject.QualifyingProperties.UnsignedProperties.UnsignedSignatureProperties.CounterSignatureCollection;
for (int counterSignatureCounter = 0; (retVal == true) && (counterSignatureCounter < counterSignatureCollection.Count); counterSignatureCounter++)
{
counterSignature = counterSignatureCollection[counterSignatureCounter];
if (counterSignature.signatureStandard == KnownSignatureStandard.Xades)
{
retVal &= counterSignature.XadesCheckSignature(counterSignatureMask);
}
else
{
retVal &= counterSignature.CheckSignature();
}
}
if (retVal == false)
{
throw new CryptographicException("XadesCheckSignature() failed on at least one counter signature");
}
retVal = true;
return retVal;
}
///
/// Counter signatures should all contain a reference to the parent signature SignatureValue element
///
/// If the function returns true the check was OK
public virtual bool CheckCounterSignaturesReference()
{
CounterSignatureCollection counterSignatureCollection;
XadesSignedXml counterSignature;
string referenceUri;
ArrayList parentSignatureValueChain;
bool referenceToParentSignatureFound;
bool retVal;
retVal = true;
parentSignatureValueChain = new ArrayList();
parentSignatureValueChain.Add("#" + this.signatureValueId);
counterSignatureCollection = this.XadesObject.QualifyingProperties.UnsignedProperties.UnsignedSignatureProperties.CounterSignatureCollection;
for (int counterSignatureCounter = 0; (retVal == true) && (counterSignatureCounter < counterSignatureCollection.Count); counterSignatureCounter++)
{
counterSignature = counterSignatureCollection[counterSignatureCounter];
referenceToParentSignatureFound = false;
for (int referenceCounter = 0; referenceToParentSignatureFound == false && (referenceCounter < counterSignature.SignedInfo.References.Count); referenceCounter++)
{
referenceUri = ((Reference)counterSignature.SignedInfo.References[referenceCounter]).Uri;
if (parentSignatureValueChain.BinarySearch(referenceUri) >= 0)
{
referenceToParentSignatureFound = true;
}
parentSignatureValueChain.Add("#" + counterSignature.SignatureValueId);
parentSignatureValueChain.Sort();
}
retVal = referenceToParentSignatureFound;
}
if (retVal == false)
{
throw new CryptographicException("CheckCounterSignaturesReference() failed on at least one counter signature");
}
retVal = true;
return retVal;
}
///
/// Check if each ObjectReference in CommitmentTypeIndication points to Reference element
///
/// If the function returns true the check was OK
public virtual bool CheckObjectReferencesInCommitmentTypeIndication()
{
CommitmentTypeIndicationCollection commitmentTypeIndicationCollection;
CommitmentTypeIndication commitmentTypeIndication;
bool objectReferenceOK;
bool retVal;
retVal = true;
commitmentTypeIndicationCollection = this.XadesObject.QualifyingProperties.SignedProperties.SignedDataObjectProperties.CommitmentTypeIndicationCollection;
if (commitmentTypeIndicationCollection.Count > 0)
{
for (int commitmentTypeIndicationCounter = 0; (retVal == true) && (commitmentTypeIndicationCounter < commitmentTypeIndicationCollection.Count); commitmentTypeIndicationCounter++)
{
commitmentTypeIndication = commitmentTypeIndicationCollection[commitmentTypeIndicationCounter];
objectReferenceOK = true;
foreach (ObjectReference objectReference in commitmentTypeIndication.ObjectReferenceCollection)
{
objectReferenceOK &= this.CheckObjectReference(objectReference);
}
retVal = objectReferenceOK;
}
if (retVal == false)
{
throw new CryptographicException("At least one ObjectReference in CommitmentTypeIndication did not point to a Reference");
}
}
return retVal;
}
///
/// Check if at least ClaimedRoles or CertifiedRoles present in SignerRole
///
/// If the function returns true the check was OK
public virtual bool CheckIfClaimedRolesOrCertifiedRolesPresentInSignerRole()
{
SignerRole signerRole;
bool retVal;
retVal = false;
signerRole = this.XadesObject.QualifyingProperties.SignedProperties.SignedSignatureProperties.SignerRole;
if (signerRole != null)
{
if (signerRole.CertifiedRoles != null)
{
retVal = (signerRole.CertifiedRoles.CertifiedRoleCollection.Count > 0);
}
if (retVal == false)
{
if (signerRole.ClaimedRoles != null)
{
retVal = (signerRole.ClaimedRoles.ClaimedRoleCollection.Count > 0);
}
}
if (retVal == false)
{
throw new CryptographicException("SignerRole element must contain at least one CertifiedRole or ClaimedRole element");
}
}
else
{
retVal = true;
}
return retVal;
}
///
/// Check if HashDataInfo of SignatureTimeStamp points to SignatureValue
///
/// If the function returns true the check was OK
public virtual bool CheckHashDataInfoOfSignatureTimeStampPointsToSignatureValue()
{
SignatureTimeStampCollection signatureTimeStampCollection;
bool hashDataInfoPointsToSignatureValue;
TimeStamp timeStamp;
int timeStampCounter;
bool retVal;
hashDataInfoPointsToSignatureValue = true;
retVal = false;
signatureTimeStampCollection = this.XadesObject.QualifyingProperties.UnsignedProperties.UnsignedSignatureProperties.SignatureTimeStampCollection;
if (signatureTimeStampCollection.Count > 0)
{
for (timeStampCounter = 0; hashDataInfoPointsToSignatureValue && (timeStampCounter < signatureTimeStampCollection.Count); timeStampCounter++)
{
timeStamp = signatureTimeStampCollection[timeStampCounter];
hashDataInfoPointsToSignatureValue &= this.CheckHashDataInfoPointsToSignatureValue(timeStamp);
}
if (hashDataInfoPointsToSignatureValue == false)
{
throw new CryptographicException("HashDataInfo of SignatureTimeStamp doesn't point to signature value element");
}
}
retVal = true;
return retVal;
}
///
/// Check if the QualifyingProperties Target attribute points to the signature element
///
/// If the function returns true the check was OK
public virtual bool CheckQualifyingPropertiesTarget()
{
string qualifyingPropertiesTarget;
bool retVal;
retVal = true;
qualifyingPropertiesTarget = this.XadesObject.QualifyingProperties.Target;
if (this.Signature.Id == null)
{
retVal = false;
}
else
{
if (qualifyingPropertiesTarget != ("#" + this.Signature.Id))
{
retVal = false;
}
}
if (retVal == false)
{
throw new CryptographicException("Qualifying properties target doesn't point to signature element or signature element doesn't have an Id");
}
return retVal;
}
///
/// Check that QualifyingProperties occur in one Object, check that there is only one QualifyingProperties and that signed properties occur in one QualifyingProperties element
///
/// If the function returns true the check was OK
public virtual bool CheckQualifyingProperties()
{
XmlElement signatureElement;
XmlNamespaceManager xmlNamespaceManager;
XmlNodeList xmlNodeList;
signatureElement = this.GetXml();
xmlNamespaceManager = new XmlNamespaceManager(signatureElement.OwnerDocument.NameTable);
xmlNamespaceManager.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
xmlNamespaceManager.AddNamespace("xsd", XadesSignedXml.XadesNamespaceUri);
xmlNodeList = signatureElement.SelectNodes("ds:Object/xsd:QualifyingProperties", xmlNamespaceManager);
if (xmlNodeList.Count > 1)
{
throw new CryptographicException("More than one Object contains a QualifyingProperties element");
}
return true;
}
///
/// Check if all required HashDataInfos are present on SigAndRefsTimeStamp
///
/// If the function returns true the check was OK
public virtual bool CheckSigAndRefsTimeStampHashDataInfos()
{
SignatureTimeStampCollection signatureTimeStampCollection;
TimeStamp timeStamp;
bool allRequiredhashDataInfosFound;
bool retVal;
retVal = true;
signatureTimeStampCollection = this.XadesObject.QualifyingProperties.UnsignedProperties.UnsignedSignatureProperties.SigAndRefsTimeStampCollection;
if (signatureTimeStampCollection.Count > 0)
{
allRequiredhashDataInfosFound = true;
for (int timeStampCounter = 0; allRequiredhashDataInfosFound && (timeStampCounter < signatureTimeStampCollection.Count); timeStampCounter++)
{
timeStamp = signatureTimeStampCollection[timeStampCounter];
allRequiredhashDataInfosFound &= this.CheckHashDataInfosOfSigAndRefsTimeStamp(timeStamp);
}
if (allRequiredhashDataInfosFound == false)
{
throw new CryptographicException("At least one required HashDataInfo is missing in a SigAndRefsTimeStamp element");
}
}
return retVal;
}
///
/// Check if all required HashDataInfos are present on RefsOnlyTimeStamp
///
/// If the function returns true the check was OK
public virtual bool CheckRefsOnlyTimeStampHashDataInfos()
{
SignatureTimeStampCollection signatureTimeStampCollection;
TimeStamp timeStamp;
bool allRequiredhashDataInfosFound;
bool retVal;
retVal = true;
signatureTimeStampCollection = this.XadesObject.QualifyingProperties.UnsignedProperties.UnsignedSignatureProperties.RefsOnlyTimeStampCollection;
if (signatureTimeStampCollection.Count > 0)
{
allRequiredhashDataInfosFound = true;
for (int timeStampCounter = 0; allRequiredhashDataInfosFound && (timeStampCounter < signatureTimeStampCollection.Count); timeStampCounter++)
{
timeStamp = signatureTimeStampCollection[timeStampCounter];
allRequiredhashDataInfosFound &= this.CheckHashDataInfosOfRefsOnlyTimeStamp(timeStamp);
}
if (allRequiredhashDataInfosFound == false)
{
throw new CryptographicException("At least one required HashDataInfo is missing in a RefsOnlyTimeStamp element");
}
}
return retVal;
}
///
/// Check if all required HashDataInfos are present on ArchiveTimeStamp
///
/// If the function returns true the check was OK
public virtual bool CheckArchiveTimeStampHashDataInfos()
{
SignatureTimeStampCollection signatureTimeStampCollection;
TimeStamp timeStamp;
bool allRequiredhashDataInfosFound;
bool retVal;
retVal = true;
signatureTimeStampCollection = this.XadesObject.QualifyingProperties.UnsignedProperties.UnsignedSignatureProperties.ArchiveTimeStampCollection;
if (signatureTimeStampCollection.Count > 0)
{
allRequiredhashDataInfosFound = true;
for (int timeStampCounter = 0; allRequiredhashDataInfosFound && (timeStampCounter < signatureTimeStampCollection.Count); timeStampCounter++)
{
timeStamp = signatureTimeStampCollection[timeStampCounter];
allRequiredhashDataInfosFound &= this.CheckHashDataInfosOfArchiveTimeStamp(timeStamp);
}
if (allRequiredhashDataInfosFound == false)
{
throw new CryptographicException("At least one required HashDataInfo is missing in a ArchiveTimeStamp element");
}
}
return retVal;
}
///
/// Check if a XAdES-C signature is also a XAdES-T signature
///
/// If the function returns true the check was OK
public virtual bool CheckXadesCIsXadesT()
{
UnsignedSignatureProperties unsignedSignatureProperties;
bool retVal;
retVal = true;
unsignedSignatureProperties = this.XadesObject.QualifyingProperties.UnsignedProperties.UnsignedSignatureProperties;
if (((unsignedSignatureProperties.CompleteCertificateRefs != null) && (unsignedSignatureProperties.CompleteCertificateRefs.HasChanged()))
|| ((unsignedSignatureProperties.CompleteCertificateRefs != null) && (unsignedSignatureProperties.CompleteCertificateRefs.HasChanged())))
{
if (unsignedSignatureProperties.SignatureTimeStampCollection.Count == 0)
{
throw new CryptographicException("XAdES-C signature should also contain a SignatureTimeStamp element");
}
}
return retVal;
}
///
/// Check if a XAdES-XL signature is also a XAdES-X signature
///
/// If the function returns true the check was OK
public virtual bool CheckXadesXLIsXadesX()
{
UnsignedSignatureProperties unsignedSignatureProperties;
bool retVal;
retVal = true;
unsignedSignatureProperties = this.XadesObject.QualifyingProperties.UnsignedProperties.UnsignedSignatureProperties;
if (((unsignedSignatureProperties.CertificateValues != null) && (unsignedSignatureProperties.CertificateValues.HasChanged()))
|| ((unsignedSignatureProperties.RevocationValues != null) && (unsignedSignatureProperties.RevocationValues.HasChanged())))
{
if ((unsignedSignatureProperties.SigAndRefsTimeStampCollection.Count == 0) && (unsignedSignatureProperties.RefsOnlyTimeStampCollection.Count == 0))
{
throw new CryptographicException("XAdES-XL signature should also contain a XAdES-X element");
}
}
return retVal;
}
///
/// Check if CertificateValues match CertificateRefs
///
/// If the function returns true the check was OK
public virtual bool CheckCertificateValuesMatchCertificateRefs()
{
SHA1Managed sha1Managed;
UnsignedSignatureProperties unsignedSignatureProperties;
ArrayList certDigests;
byte[] certDigest;
int index;
bool retVal;
retVal = true;
unsignedSignatureProperties = this.XadesObject.QualifyingProperties.UnsignedProperties.UnsignedSignatureProperties;
if ((unsignedSignatureProperties.CompleteCertificateRefs != null) && (unsignedSignatureProperties.CompleteCertificateRefs.CertRefs != null) &&
(unsignedSignatureProperties.CertificateValues != null))
{
certDigests = new ArrayList();
foreach (Cert cert in unsignedSignatureProperties.CompleteCertificateRefs.CertRefs.CertCollection)
{
certDigests.Add(Convert.ToBase64String(cert.CertDigest.DigestValue));
}
certDigests.Sort();
foreach (EncapsulatedX509Certificate encapsulatedX509Certificate in unsignedSignatureProperties.CertificateValues.EncapsulatedX509CertificateCollection)
{
sha1Managed = new SHA1Managed();
certDigest = sha1Managed.ComputeHash(encapsulatedX509Certificate.PkiData);
index = certDigests.BinarySearch(Convert.ToBase64String(certDigest));
if (index >= 0)
{
certDigests.RemoveAt(index);
}
}
if (certDigests.Count != 0)
{
throw new CryptographicException("Not all CertificateRefs correspond to CertificateValues");
}
}
return retVal;
}
///
/// Check if RevocationValues match RevocationRefs
///
/// If the function returns true the check was OK
public virtual bool CheckRevocationValuesMatchRevocationRefs()
{
SHA1Managed sha1Managed;
UnsignedSignatureProperties unsignedSignatureProperties;
ArrayList crlDigests;
byte[] crlDigest;
int index;
bool retVal;
retVal = true;
unsignedSignatureProperties = this.XadesObject.QualifyingProperties.UnsignedProperties.UnsignedSignatureProperties;
if ((unsignedSignatureProperties.CompleteRevocationRefs != null) && (unsignedSignatureProperties.CompleteRevocationRefs.CRLRefs != null) &&
(unsignedSignatureProperties.RevocationValues != null))
{
crlDigests = new ArrayList();
foreach (CRLRef crlRef in unsignedSignatureProperties.CompleteRevocationRefs.CRLRefs.CRLRefCollection)
{
crlDigests.Add(Convert.ToBase64String(crlRef.CertDigest.DigestValue));
}
crlDigests.Sort();
foreach (CRLValue crlValue in unsignedSignatureProperties.RevocationValues.CRLValues.CRLValueCollection)
{
sha1Managed = new SHA1Managed();
crlDigest = sha1Managed.ComputeHash(crlValue.PkiData);
index = crlDigests.BinarySearch(Convert.ToBase64String(crlDigest));
if (index >= 0)
{
crlDigests.RemoveAt(index);
}
}
if (crlDigests.Count != 0)
{
throw new CryptographicException("Not all RevocationRefs correspond to RevocationValues");
}
}
return retVal;
}
#endregion
#endregion
#region Fix to add a namespace prefix for all XmlDsig nodes
private void SetPrefix(String prefix, XmlNode node)
{
if (node.NamespaceURI == SignedXml.XmlDsigNamespaceUrl)
{
node.Prefix = prefix;
}
foreach (XmlNode child in node.ChildNodes)
{
SetPrefix(prefix, child);
}
return;
}
///
/// Copy of System.Security.Cryptography.Xml.SignedXml.ComputeSignature() which will end up calling
/// our own GetC14NDigest with a namespace prefix for all XmlDsig nodes
///
public new void ComputeSignature()
{
AsymmetricAlgorithm signingKey = this.SigningKey;
if (signingKey == null)
{
throw new CryptographicException("Cryptography_Xml_LoadKeyFailed");
}
if (this.SignedInfo.SignatureMethod == null)
{
if (!(signingKey is DSA))
{
if (!(signingKey is RSA))
{
throw new CryptographicException("Cryptography_Xml_CreatedKeyFailed");
}
if (this.SignedInfo.SignatureMethod == null)
{
this.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
}
}
else
{
this.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
}
}
HashAlgorithm hash;
var description = GetSignedInfoHash(out hash);
//
this.m_signature.SignatureValue = description.CreateFormatter(signingKey).CreateSignature(hash);
}
private HashAlgorithm signedInfoHash = null;
///
/// Calculates standalone SignedInfo hash
///
///
///
///
public SignatureDescription GetSignedInfoHash(out HashAlgorithm hash)
{
SignatureDescription description;
if (signedInfoHash != null)
{
description = CryptoConfig.CreateFromName(this.SignedInfo.SignatureMethod) as SignatureDescription;
hash = signedInfoHash;
return description;
}
this.BuildDigestedReferences();
description =
CryptoConfig.CreateFromName(this.SignedInfo.SignatureMethod) as SignatureDescription;
if (description == null)
{
throw new CryptographicException("Cryptography_Xml_SignatureDescriptionNotCreated");
}
hash = description.CreateDigest();
if (hash == null)
{
throw new CryptographicException("Cryptography_Xml_CreateHashAlgorithmFailed");
}
this.GetC14NDigest(hash, "ds");
this.signedInfoHash = hash;
return description;
}
///
/// Copy of System.Security.Cryptography.Xml.SignedXml.BuildDigestedReferences() which will add a "ds"
/// namespace prefix to all XmlDsig nodes
///
private void BuildDigestedReferences()
{
ArrayList references = this.SignedInfo.References;
// TODO: Проверить комментарий
//this.m_refProcessed = new bool[references.Count];
Type SignedXml_Type = typeof(SignedXml);
FieldInfo SignedXml_m_refProcessed = SignedXml_Type.GetField("m_refProcessed", BindingFlags.NonPublic | BindingFlags.Instance);
SignedXml_m_refProcessed.SetValue(this, new bool[references.Count]);
// TODO: Проверить комментарий
//this.m_refLevelCache = new int[references.Count];
FieldInfo SignedXml_m_refLevelCache = SignedXml_Type.GetField("m_refLevelCache", BindingFlags.NonPublic | BindingFlags.Instance);
SignedXml_m_refLevelCache.SetValue(this, new int[references.Count]);
// TODO: Проверить комментарий
//ReferenceLevelSortOrder comparer = new ReferenceLevelSortOrder();
Assembly System_Security_Assembly = Assembly.Load("System.Security, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
Type ReferenceLevelSortOrder_Type = System_Security_Assembly.GetType("System.Security.Cryptography.Xml.SignedXml+ReferenceLevelSortOrder");
ConstructorInfo ReferenceLevelSortOrder_Constructor = ReferenceLevelSortOrder_Type.GetConstructor(new Type[] { });
Object comparer = ReferenceLevelSortOrder_Constructor.Invoke(null);
// TODO: Проверить комментарий
//comparer.References = references;
PropertyInfo ReferenceLevelSortOrder_References = ReferenceLevelSortOrder_Type.GetProperty("References", BindingFlags.Public | BindingFlags.Instance);
ReferenceLevelSortOrder_References.SetValue(comparer, references, null);
//
ArrayList list2 = new ArrayList();
foreach (Reference reference in references)
{
list2.Add(reference);
}
list2.Sort((IComparer)comparer);
// TODO: Проверить комментарий
//CanonicalXmlNodeList refList = new CanonicalXmlNodeList();
Type CanonicalXmlNodeList_Type = System_Security_Assembly.GetType("System.Security.Cryptography.Xml.CanonicalXmlNodeList");
ConstructorInfo CanonicalXmlNodeList_Constructor = CanonicalXmlNodeList_Type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { }, null);
Object refList = CanonicalXmlNodeList_Constructor.Invoke(null);
MethodInfo CanonicalXmlNodeList_Add = CanonicalXmlNodeList_Type.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance);
foreach (DataObject obj2 in this.m_signature.ObjectList)
{
// TODO: Проверить комментарий
//refList.Add(obj2.GetXml());
XmlElement xml = obj2.GetXml();
SetPrefix("ds", xml);
CanonicalXmlNodeList_Add.Invoke(refList, new object[] { xml });
}
FieldInfo SignedXml_m_containingDocument = SignedXml_Type.GetField("m_containingDocument", BindingFlags.NonPublic | BindingFlags.Instance);
Type Reference_Type = typeof(Reference);
MethodInfo Reference_UpdateHashValue = Reference_Type.GetMethod("UpdateHashValue", BindingFlags.NonPublic | BindingFlags.Instance);
foreach (Reference reference2 in list2)
{
if (reference2.DigestMethod == null)
{
// TODO: Проверить комментарий
//reference2.DigestMethod = "http://www.w3.org/2000/09/xmldsig#sha1";
reference2.DigestMethod = "http://www.w3.org/2001/04/xmldsig-more#gostr3411";
}
// TODO: Проверить комментарий
//reference2.UpdateHashValue(this.m_containingDocument, refList);
object m_containingDocument = SignedXml_m_containingDocument.GetValue(this);
Reference_UpdateHashValue.Invoke(reference2, new object[] { m_containingDocument, refList });
if (reference2.Id != null)
{
// TODO: Проверить комментарий
//refList.Add(reference2.GetXml());
XmlElement xml = reference2.GetXml();
SetPrefix("ds", xml);
CanonicalXmlNodeList_Add.Invoke(refList, new object[] { xml });
}
}
}
///
/// We won't call System.Security.Cryptography.Xml.SignedXml.GetC14NDigest(), as we want to use our own
///
private byte[] GetC14NDigest(HashAlgorithm hash)
{
return null;
}
///
/// Copy of System.Security.Cryptography.Xml.SignedXml.GetC14NDigest() which will add a
/// namespace prefix to all XmlDsig nodes
///
private byte[] GetC14NDigest(HashAlgorithm hash, string prefix)
{
// TODO: Проверить комментарий
//if (!this.bCacheValid || !this.SignedInfo.CacheValid)
//{
Type SignedXml_Type = typeof(SignedXml);
FieldInfo SignedXml_bCacheValid = SignedXml_Type.GetField("bCacheValid", BindingFlags.NonPublic | BindingFlags.Instance);
bool bCacheValid = (bool)SignedXml_bCacheValid.GetValue(this);
Type SignedInfo_Type = typeof(SignedInfo);
PropertyInfo SignedInfo_CacheValid = SignedInfo_Type.GetProperty("CacheValid", BindingFlags.NonPublic | BindingFlags.Instance);
bool CacheValid = (bool)SignedInfo_CacheValid.GetValue(this.SignedInfo, null);
FieldInfo SignedXml__digestedSignedInfo = SignedXml_Type.GetField("_digestedSignedInfo", BindingFlags.NonPublic | BindingFlags.Instance);
if (!bCacheValid || !CacheValid)
{
// TODO: Проверить комментарий
//string securityUrl = (this.m_containingDocument == null) ? null : this.m_containingDocument.BaseURI;
FieldInfo SignedXml_m_containingDocument = SignedXml_Type.GetField("m_containingDocument", BindingFlags.NonPublic | BindingFlags.Instance);
XmlDocument m_containingDocument = (XmlDocument)SignedXml_m_containingDocument.GetValue(this);
string securityUrl = (m_containingDocument == null) ? null : m_containingDocument.BaseURI;
// TODO: Проверить комментарий
//XmlResolver xmlResolver = this.m_bResolverSet ? this.m_xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), securityUrl);
FieldInfo SignedXml_m_bResolverSet = SignedXml_Type.GetField("m_bResolverSet", BindingFlags.NonPublic | BindingFlags.Instance);
bool m_bResolverSet = (bool)SignedXml_m_bResolverSet.GetValue(this);
FieldInfo SignedXml_m_xmlResolver = SignedXml_Type.GetField("m_xmlResolver", BindingFlags.NonPublic | BindingFlags.Instance);
XmlResolver m_xmlResolver = (XmlResolver)SignedXml_m_xmlResolver.GetValue(this);
XmlResolver xmlResolver = m_bResolverSet ? m_xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), securityUrl);
// TODO: Проверить комментарий
//XmlDocument document = Utils.PreProcessElementInput(this.SignedInfo.GetXml(), xmlResolver, securityUrl);
Assembly System_Security_Assembly = Assembly.Load("System.Security, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
Type Utils_Type = System_Security_Assembly.GetType("System.Security.Cryptography.Xml.Utils");
MethodInfo Utils_PreProcessElementInput = Utils_Type.GetMethod("PreProcessElementInput", BindingFlags.NonPublic | BindingFlags.Static);
XmlElement xml = this.SignedInfo.GetXml();
SetPrefix(prefix, xml);
XmlDocument document = (XmlDocument)Utils_PreProcessElementInput.Invoke(null, new object[] { xml, xmlResolver, securityUrl });
// TODO: Проверить комментарий
//CanonicalXmlNodeList namespaces = (this.m_context == null) ? null : Utils.GetPropagatedAttributes(this.m_context);
//FieldInfo SignedXml_m_context = SignedXml_Type.GetField("m_context", BindingFlags.NonPublic | BindingFlags.Instance);
MethodInfo Utils_GetPropagatedAttributes = Utils_Type.GetMethod("GetPropagatedAttributes", BindingFlags.NonPublic | BindingFlags.Static);
var xmlDocumentCloned = new XmlDocument();
xmlDocumentCloned.LoadXml(m_containingDocument.OuterXml);
var signedDataContainer = GetIdElement(xmlDocumentCloned, SignedElementId);
signedDataContainer.InsertBefore(xmlDocumentCloned.ImportNode(document.DocumentElement, true), signedDataContainer.FirstChild);
object namespaces = Utils_GetPropagatedAttributes.Invoke(null, new object[] { signedDataContainer.FirstChild });
// TODO: Проверить комментарий
//object m_context = SignedXml_m_context.GetValue(this);
//object namespaces = (m_context == null) ? null : Utils_GetPropagatedAttributes.Invoke(null, new object[] { m_context });
// TODO: Проверить комментарий
// Utils.AddNamespaces(document.DocumentElement, namespaces);
Type CanonicalXmlNodeList_Type = System_Security_Assembly.GetType("System.Security.Cryptography.Xml.CanonicalXmlNodeList");
MethodInfo Utils_AddNamespaces = Utils_Type.GetMethod("AddNamespaces", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(XmlElement), CanonicalXmlNodeList_Type }, null);
Utils_AddNamespaces.Invoke(null, new object[] { document.DocumentElement, namespaces });
// TODO: Проверить комментарий
//Transform canonicalizationMethodObject = this.SignedInfo.CanonicalizationMethodObject;
System.Security.Cryptography.Xml.Transform canonicalizationMethodObject = this.SignedInfo.CanonicalizationMethodObject;
canonicalizationMethodObject.Resolver = xmlResolver;
// TODO: Проверить комментарий
//canonicalizationMethodObject.BaseURI = securityUrl;
Type Transform_Type = typeof(System.Security.Cryptography.Xml.Transform);
PropertyInfo Transform_BaseURI = Transform_Type.GetProperty("BaseURI", BindingFlags.NonPublic | BindingFlags.Instance);
Transform_BaseURI.SetValue(canonicalizationMethodObject, securityUrl, null);
canonicalizationMethodObject.LoadInput(document);
// TODO: Проверить комментарий
//this._digestedSignedInfo = canonicalizationMethodObject.GetDigestedOutput(hash);
SignedXml__digestedSignedInfo.SetValue(this, canonicalizationMethodObject.GetDigestedOutput(hash));
// TODO: Проверить комментарий
//this.bCacheValid = true;
SignedXml_bCacheValid.SetValue(this, true);
}
// TODO: Проверить комментарий
//return this._digestedSignedInfo;
byte[] _digestedSignedInfo = (byte[])SignedXml__digestedSignedInfo.GetValue(this);
return _digestedSignedInfo;
}
#endregion
#region Private methods
protected XmlElement GetXadesObjectElement(XmlElement signatureElement)
{
XmlElement retVal = null;
XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(signatureElement.OwnerDocument.NameTable); //Create an XmlNamespaceManager to resolve namespace
xmlNamespaceManager.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
xmlNamespaceManager.AddNamespace("xsd", XadesSignedXml.XadesNamespaceUri);
XmlNodeList xmlNodeList = signatureElement.SelectNodes("ds:Object/xsd:QualifyingProperties", xmlNamespaceManager);
if (xmlNodeList.Count > 0)
{
retVal = (XmlElement)xmlNodeList.Item(0).ParentNode;
}
else
{
retVal = null;
}
return retVal;
}
private void SetSignatureStandard(XmlElement signatureElement)
{
if (this.GetXadesObjectElement(signatureElement) != null)
{
this.signatureStandard = KnownSignatureStandard.Xades;
}
else
{
this.signatureStandard = KnownSignatureStandard.XmlDsig;
}
}
private System.Security.Cryptography.Xml.DataObject GetXadesDataObject()
{
System.Security.Cryptography.Xml.DataObject retVal = null;
for (int dataObjectCounter = 0; dataObjectCounter < (this.Signature.ObjectList.Count); dataObjectCounter++)
{
System.Security.Cryptography.Xml.DataObject dataObject = (System.Security.Cryptography.Xml.DataObject)this.Signature.ObjectList[dataObjectCounter];
XmlElement dataObjectXmlElement = dataObject.GetXml();
XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(dataObjectXmlElement.OwnerDocument.NameTable);
xmlNamespaceManager.AddNamespace("xsd", XadesSignedXml.XadesNamespaceUri);
XmlNodeList xmlNodeList = dataObjectXmlElement.SelectNodes("xsd:QualifyingProperties", xmlNamespaceManager);
if (xmlNodeList.Count != 0)
{
retVal = dataObject;
break;
}
}
return retVal;
}
private void SchemaValidationHandler(object sender, ValidationEventArgs validationEventArgs)
{
this.validationErrorOccurred = true;
this.validationErrorDescription += "Validation error:\n";
this.validationErrorDescription += "\tSeverity: " + validationEventArgs.Severity.ToString() + "\n";
this.validationErrorDescription += "\tMessage: " + validationEventArgs.Message + "\n";
}
private void XmlValidationHandler(object sender, ValidationEventArgs validationEventArgs)
{
if (validationEventArgs.Severity != XmlSeverityType.Warning)
{
this.validationErrorOccurred = true;
this.validationErrorDescription += "Validation error:\n";
this.validationErrorDescription += "\tSeverity: " + validationEventArgs.Severity.ToString() + "\n";
this.validationErrorDescription += "\tMessage: " + validationEventArgs.Message + "\n";
}
}
private bool CheckHashDataInfosForTimeStamp(TimeStamp timeStamp)
{
bool retVal = true;
for (int referenceCounter = 0; retVal == true && (referenceCounter < this.SignedInfo.References.Count); referenceCounter++)
{
string referenceId = ((Reference)this.SignedInfo.References[referenceCounter]).Id;
string referenceUri = ((Reference)this.SignedInfo.References[referenceCounter]).Uri;
if (referenceUri != ("#" + this.XadesObject.QualifyingProperties.SignedProperties.Id))
{
bool hashDataInfoFound = false;
for (int hashDataInfoCounter = 0; hashDataInfoFound == false && (hashDataInfoCounter < timeStamp.HashDataInfoCollection.Count); hashDataInfoCounter++)
{
HashDataInfo hashDataInfo = timeStamp.HashDataInfoCollection[hashDataInfoCounter];
hashDataInfoFound = (("#" + referenceId) == hashDataInfo.UriAttribute);
}
retVal = hashDataInfoFound;
}
}
return retVal;
}
private bool CheckHashDataInfosExist(TimeStamp timeStamp)
{
bool retVal = true;
for (int hashDataInfoCounter = 0; retVal == true && (hashDataInfoCounter < timeStamp.HashDataInfoCollection.Count); hashDataInfoCounter++)
{
HashDataInfo hashDataInfo = timeStamp.HashDataInfoCollection[hashDataInfoCounter];
bool referenceFound = false;
string referenceId;
for (int referenceCounter = 0; referenceFound == false && (referenceCounter < this.SignedInfo.References.Count); referenceCounter++)
{
referenceId = ((Reference)this.SignedInfo.References[referenceCounter]).Id;
if (("#" + referenceId) == hashDataInfo.UriAttribute)
{
referenceFound = true;
}
}
retVal = referenceFound;
}
return retVal;
}
private bool CheckObjectReference(ObjectReference objectReference)
{
bool retVal = false;
for (int referenceCounter = 0; retVal == false && (referenceCounter < this.SignedInfo.References.Count); referenceCounter++)
{
string referenceId = ((Reference)this.SignedInfo.References[referenceCounter]).Id;
if (("#" + referenceId) == objectReference.ObjectReferenceUri)
{
retVal = true;
}
}
return retVal;
}
private bool CheckHashDataInfoPointsToSignatureValue(TimeStamp timeStamp)
{
bool retVal = true;
foreach (HashDataInfo hashDataInfo in timeStamp.HashDataInfoCollection)
{
retVal &= (hashDataInfo.UriAttribute == ("#" + this.signatureValueId));
}
return retVal;
}
private bool CheckHashDataInfosOfSigAndRefsTimeStamp(TimeStamp timeStamp)
{
UnsignedSignatureProperties unsignedSignatureProperties;
bool signatureValueHashDataInfoFound = false;
bool allSignatureTimeStampHashDataInfosFound = false;
bool completeCertificateRefsHashDataInfoFound = false;
bool completeRevocationRefsHashDataInfoFound = false;
ArrayList signatureTimeStampIds = new ArrayList();
bool retVal = true;
unsignedSignatureProperties = this.XadesObject.QualifyingProperties.UnsignedProperties.UnsignedSignatureProperties;
foreach (TimeStamp signatureTimeStamp in unsignedSignatureProperties.SignatureTimeStampCollection)
{
signatureTimeStampIds.Add("#" + signatureTimeStamp.EncapsulatedTimeStamp.Id);
}
signatureTimeStampIds.Sort();
foreach (HashDataInfo hashDataInfo in timeStamp.HashDataInfoCollection)
{
if (hashDataInfo.UriAttribute == "#" + this.signatureValueId)
{
signatureValueHashDataInfoFound = true;
}
int signatureTimeStampIdIndex = signatureTimeStampIds.BinarySearch(hashDataInfo.UriAttribute);
if (signatureTimeStampIdIndex >= 0)
{
signatureTimeStampIds.RemoveAt(signatureTimeStampIdIndex);
}
if (hashDataInfo.UriAttribute == "#" + unsignedSignatureProperties.CompleteCertificateRefs.Id)
{
completeCertificateRefsHashDataInfoFound = true;
}
if (hashDataInfo.UriAttribute == "#" + unsignedSignatureProperties.CompleteRevocationRefs.Id)
{
completeRevocationRefsHashDataInfoFound = true;
}
}
if (signatureTimeStampIds.Count == 0)
{
allSignatureTimeStampHashDataInfosFound = true;
}
retVal = signatureValueHashDataInfoFound && allSignatureTimeStampHashDataInfosFound && completeCertificateRefsHashDataInfoFound && completeRevocationRefsHashDataInfoFound;
return retVal;
}
private bool CheckHashDataInfosOfRefsOnlyTimeStamp(TimeStamp timeStamp)
{
UnsignedSignatureProperties unsignedSignatureProperties;
bool completeCertificateRefsHashDataInfoFound;
bool completeRevocationRefsHashDataInfoFound;
bool retVal;
completeCertificateRefsHashDataInfoFound = false;
completeRevocationRefsHashDataInfoFound = false;
retVal = true;
unsignedSignatureProperties = this.XadesObject.QualifyingProperties.UnsignedProperties.UnsignedSignatureProperties;
foreach (HashDataInfo hashDataInfo in timeStamp.HashDataInfoCollection)
{
if (hashDataInfo.UriAttribute == "#" + unsignedSignatureProperties.CompleteCertificateRefs.Id)
{
completeCertificateRefsHashDataInfoFound = true;
}
if (hashDataInfo.UriAttribute == "#" + unsignedSignatureProperties.CompleteRevocationRefs.Id)
{
completeRevocationRefsHashDataInfoFound = true;
}
}
retVal = completeCertificateRefsHashDataInfoFound && completeRevocationRefsHashDataInfoFound;
return retVal;
}
private bool CheckHashDataInfosOfArchiveTimeStamp(TimeStamp timeStamp)
{
UnsignedSignatureProperties unsignedSignatureProperties;
SignedProperties signedProperties;
bool allReferenceHashDataInfosFound = false;
bool signedInfoHashDataInfoFound = false;
bool signedPropertiesHashDataInfoFound = false;
bool signatureValueHashDataInfoFound = false;
bool allSignatureTimeStampHashDataInfosFound = false;
bool completeCertificateRefsHashDataInfoFound = false;
bool completeRevocationRefsHashDataInfoFound = false;
bool certificatesValuesHashDataInfoFound = false;
bool revocationValuesHashDataInfoFound = false;
bool allSigAndRefsTimeStampHashDataInfosFound = false;
bool allRefsOnlyTimeStampHashDataInfosFound = false;
bool allArchiveTimeStampHashDataInfosFound = false;
bool allOlderArchiveTimeStampsFound = false;
ArrayList referenceIds = new ArrayList();
ArrayList signatureTimeStampIds = new ArrayList();
ArrayList sigAndRefsTimeStampIds = new ArrayList();
ArrayList refsOnlyTimeStampIds = new ArrayList();
ArrayList archiveTimeStampIds = new ArrayList();
bool retVal = true;
unsignedSignatureProperties = this.XadesObject.QualifyingProperties.UnsignedProperties.UnsignedSignatureProperties;
signedProperties = this.XadesObject.QualifyingProperties.SignedProperties;
foreach (Reference reference in this.Signature.SignedInfo.References)
{
if (reference.Uri != "#" + signedProperties.Id)
{
referenceIds.Add(reference.Uri);
}
}
referenceIds.Sort();
foreach (TimeStamp signatureTimeStamp in unsignedSignatureProperties.SignatureTimeStampCollection)
{
signatureTimeStampIds.Add("#" + signatureTimeStamp.EncapsulatedTimeStamp.Id);
}
signatureTimeStampIds.Sort();
foreach (TimeStamp sigAndRefsTimeStamp in unsignedSignatureProperties.SigAndRefsTimeStampCollection)
{
sigAndRefsTimeStampIds.Add("#" + sigAndRefsTimeStamp.EncapsulatedTimeStamp.Id);
}
sigAndRefsTimeStampIds.Sort();
foreach (TimeStamp refsOnlyTimeStamp in unsignedSignatureProperties.RefsOnlyTimeStampCollection)
{
refsOnlyTimeStampIds.Add("#" + refsOnlyTimeStamp.EncapsulatedTimeStamp.Id);
}
refsOnlyTimeStampIds.Sort();
allOlderArchiveTimeStampsFound = false;
for (int archiveTimeStampCounter = 0; !allOlderArchiveTimeStampsFound && (archiveTimeStampCounter < unsignedSignatureProperties.ArchiveTimeStampCollection.Count); archiveTimeStampCounter++)
{
TimeStamp archiveTimeStamp = unsignedSignatureProperties.ArchiveTimeStampCollection[archiveTimeStampCounter];
if (archiveTimeStamp.EncapsulatedTimeStamp.Id == timeStamp.EncapsulatedTimeStamp.Id)
{
allOlderArchiveTimeStampsFound = true;
}
else
{
archiveTimeStampIds.Add("#" + archiveTimeStamp.EncapsulatedTimeStamp.Id);
}
}
archiveTimeStampIds.Sort();
foreach (HashDataInfo hashDataInfo in timeStamp.HashDataInfoCollection)
{
int index = referenceIds.BinarySearch(hashDataInfo.UriAttribute);
if (index >= 0)
{
referenceIds.RemoveAt(index);
}
// TODO: Проверить комментарий
//if (hashDataInfo.UriAttribute == "#" + this.signedInfoIdBuffer)
if (hashDataInfo.UriAttribute == "#")
{
signedInfoHashDataInfoFound = true;
}
if (hashDataInfo.UriAttribute == "#" + signedProperties.Id)
{
signedPropertiesHashDataInfoFound = true;
}
if (hashDataInfo.UriAttribute == "#" + this.signatureValueId)
{
signatureValueHashDataInfoFound = true;
}
index = signatureTimeStampIds.BinarySearch(hashDataInfo.UriAttribute);
if (index >= 0)
{
signatureTimeStampIds.RemoveAt(index);
}
if (hashDataInfo.UriAttribute == "#" + unsignedSignatureProperties.CompleteCertificateRefs.Id)
{
completeCertificateRefsHashDataInfoFound = true;
}
if (hashDataInfo.UriAttribute == "#" + unsignedSignatureProperties.CompleteRevocationRefs.Id)
{
completeRevocationRefsHashDataInfoFound = true;
}
if (hashDataInfo.UriAttribute == "#" + unsignedSignatureProperties.CertificateValues.Id)
{
certificatesValuesHashDataInfoFound = true;
}
if (hashDataInfo.UriAttribute == "#" + unsignedSignatureProperties.RevocationValues.Id)
{
revocationValuesHashDataInfoFound = true;
}
index = sigAndRefsTimeStampIds.BinarySearch(hashDataInfo.UriAttribute);
if (index >= 0)
{
sigAndRefsTimeStampIds.RemoveAt(index);
}
index = refsOnlyTimeStampIds.BinarySearch(hashDataInfo.UriAttribute);
if (index >= 0)
{
refsOnlyTimeStampIds.RemoveAt(index);
}
index = archiveTimeStampIds.BinarySearch(hashDataInfo.UriAttribute);
if (index >= 0)
{
archiveTimeStampIds.RemoveAt(index);
}
}
if (referenceIds.Count == 0)
{
allReferenceHashDataInfosFound = true;
}
if (signatureTimeStampIds.Count == 0)
{
allSignatureTimeStampHashDataInfosFound = true;
}
if (sigAndRefsTimeStampIds.Count == 0)
{
allSigAndRefsTimeStampHashDataInfosFound = true;
}
if (refsOnlyTimeStampIds.Count == 0)
{
allRefsOnlyTimeStampHashDataInfosFound = true;
}
if (archiveTimeStampIds.Count == 0)
{
allArchiveTimeStampHashDataInfosFound = true;
}
retVal = allReferenceHashDataInfosFound && signedInfoHashDataInfoFound && signedPropertiesHashDataInfoFound &&
signatureValueHashDataInfoFound && allSignatureTimeStampHashDataInfosFound && completeCertificateRefsHashDataInfoFound &&
completeRevocationRefsHashDataInfoFound && certificatesValuesHashDataInfoFound && revocationValuesHashDataInfoFound &&
allSigAndRefsTimeStampHashDataInfosFound && allRefsOnlyTimeStampHashDataInfosFound && allArchiveTimeStampHashDataInfosFound;
return retVal;
}
#endregion
public SignedDataObjectProperties SignedDataObjectProperties => SignedProperties.SignedDataObjectProperties;
public SignedProperties SignedProperties => XadesObject.QualifyingProperties.SignedProperties;
public SignedSignatureProperties SignedSignatureProperties => SignedProperties.SignedSignatureProperties;
}
}