// TimeStamp.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.Security.Cryptography; using System.Xml; namespace Microsoft.Xades { /// /// This class contains timestamp information /// public class TimeStamp { #region Private variables private string tagName; private HashDataInfoCollection hashDataInfoCollection; private EncapsulatedPKIData encapsulatedTimeStamp; private XMLTimeStamp xmlTimeStamp; #endregion #region Public properties /// /// The name of the element when serializing /// public string TagName { get { return this.tagName; } set { this.tagName = value; } } /// /// A collection of hash data infos /// public HashDataInfoCollection HashDataInfoCollection { get { return this.hashDataInfoCollection; } set { this.hashDataInfoCollection = value; } } /// /// The time-stamp generated by a TSA encoded as an ASN.1 data /// object /// public EncapsulatedPKIData EncapsulatedTimeStamp { get { return this.encapsulatedTimeStamp; } set { this.encapsulatedTimeStamp = value; if (this.encapsulatedTimeStamp != null) { this.xmlTimeStamp = null; } } } /// /// The time-stamp generated by a TSA encoded as a generic XML /// timestamp /// public XMLTimeStamp XMLTimeStamp { get { return this.xmlTimeStamp; } set { this.xmlTimeStamp = value; if (this.xmlTimeStamp != null) { this.encapsulatedTimeStamp = null; } } } #endregion #region Constructors /// /// Default constructor /// public TimeStamp() { this.hashDataInfoCollection = new HashDataInfoCollection(); this.encapsulatedTimeStamp = new EncapsulatedPKIData("EncapsulatedTimeStamp"); this.xmlTimeStamp = null; } /// /// Constructor with TagName /// /// Name of the tag when serializing with GetXml public TimeStamp(string tagName) : this() { this.tagName = tagName; } #endregion #region Public methods /// /// Check to see if something has changed in this instance and needs to be serialized /// /// Flag indicating if a member needs serialization public bool HasChanged() { bool retVal = false; if (this.hashDataInfoCollection.Count > 0) { retVal = true; } if (this.encapsulatedTimeStamp != null && this.encapsulatedTimeStamp.HasChanged()) { retVal = true; } if (this.xmlTimeStamp != null && this.xmlTimeStamp.HasChanged()) { retVal = true; } return retVal; } /// /// Load state from an XML element /// /// XML element containing new state public void LoadXml(System.Xml.XmlElement xmlElement) { XmlNamespaceManager xmlNamespaceManager; XmlNodeList xmlNodeList; IEnumerator enumerator; XmlElement iterationXmlElement; HashDataInfo newHashDataInfo; if (xmlElement == null) { throw new ArgumentNullException("xmlElement"); } xmlNamespaceManager = new XmlNamespaceManager(xmlElement.OwnerDocument.NameTable); xmlNamespaceManager.AddNamespace("xsd", XadesSignedXml.XadesNamespaceUri); this.hashDataInfoCollection.Clear(); xmlNodeList = xmlElement.SelectNodes("xsd:HashDataInfo", xmlNamespaceManager); enumerator = xmlNodeList.GetEnumerator(); try { while (enumerator.MoveNext()) { iterationXmlElement = enumerator.Current as XmlElement; if (iterationXmlElement != null) { newHashDataInfo = new HashDataInfo(); newHashDataInfo.LoadXml(iterationXmlElement); this.hashDataInfoCollection.Add(newHashDataInfo); } } } finally { IDisposable disposable = enumerator as IDisposable; if (disposable != null) { disposable.Dispose(); } } xmlNodeList = xmlElement.SelectNodes("xsd:EncapsulatedTimeStamp", xmlNamespaceManager); if (xmlNodeList.Count != 0) { this.encapsulatedTimeStamp = new EncapsulatedPKIData("EncapsulatedTimeStamp"); this.encapsulatedTimeStamp.LoadXml((XmlElement)xmlNodeList.Item(0)); this.xmlTimeStamp = null; } else { xmlNodeList = xmlElement.SelectNodes("xsd:XMLTimeStamp", xmlNamespaceManager); if (xmlNodeList.Count != 0) { this.xmlTimeStamp = new XMLTimeStamp(); this.xmlTimeStamp.LoadXml((XmlElement)xmlNodeList.Item(0)); this.encapsulatedTimeStamp = null; } else { throw new CryptographicException("EncapsulatedTimeStamp or XMLTimeStamp missing"); } } } /// /// Returns the XML representation of the this object /// /// XML element containing the state of this object public XmlElement GetXml() { XmlDocument creationXmlDocument; XmlElement retVal; creationXmlDocument = new XmlDocument(); retVal = creationXmlDocument.CreateElement("xades", this.tagName, XadesSignedXml.XadesNamespaceUri); if (this.hashDataInfoCollection.Count > 0) { foreach (HashDataInfo hashDataInfo in this.hashDataInfoCollection) { if (hashDataInfo.HasChanged()) { retVal.AppendChild(creationXmlDocument.ImportNode(hashDataInfo.GetXml(), true)); } } } else { throw new CryptographicException("HashDataInfoCollection is empty. TimeStamp needs at least one HashDataInfo element"); } if (this.encapsulatedTimeStamp != null && this.encapsulatedTimeStamp.HasChanged()) { retVal.AppendChild(creationXmlDocument.ImportNode(this.encapsulatedTimeStamp.GetXml(), true)); } else { if (this.xmlTimeStamp != null && this.xmlTimeStamp.HasChanged()) { retVal.AppendChild(creationXmlDocument.ImportNode(this.xmlTimeStamp.GetXml(), true)); } else { throw new CryptographicException("EncapsulatedTimeStamp or XMLTimeStamp element missing"); } } return retVal; } #endregion } }