public static (byte[] digest, Uri identifier) Digest(OpcPart part, HashAlgorithmName algorithmName) { using (var hashAlgorithm = HashAlgorithmTranslator.TranslateFromNameToxmlDSigUri(algorithmName, out var identifier)) { using (var partStream = part.Open()) { var digest = hashAlgorithm.ComputeHash(partStream); return(digest, identifier); } } }
public static (byte[] digest, Uri identifier) Digest(OpcPart part, HashAlgorithmName algorithmName) { var info = new HashAlgorithmInfo(algorithmName); using (var hashAlgorithm = info.Create()) { using (var partStream = part.Open()) { var digest = hashAlgorithm.ComputeHash(partStream); return(digest, info.XmlDSigIdentifier); } } }
private static void PublishSignature(XmlDocument document, OpcPart signatureFile) { using (var copySignatureStream = signatureFile.Open()) { copySignatureStream.SetLength(0L); using (var xmlWriter = new XmlTextWriter(copySignatureStream, System.Text.Encoding.UTF8)) { //The .NET implementation of OPC used by Visual Studio does not tollerate "white space" nodes. xmlWriter.Formatting = Formatting.None; document.Save(xmlWriter); } } }
/// <summary> /// Removes an existing part from the package, and its relationships. /// </summary> /// <param name="part">The part to remove from the package. Use <see cref="GetPart(Uri)"/> to obtain the part to remove.</param> /// <remarks>This does not validate or clean up other references to this part.</remarks> public void RemovePart(OpcPart part) { var relationshipUri = part.Relationships.DocumentUri; var relationshipPath = relationshipUri.ToPackagePath(); var relationshipEntry = Archive.GetEntry(relationshipPath); relationshipEntry?.Delete(); _partTracker.Remove(relationshipPath); var path = part.Uri.ToPackagePath(); part.Entry.Delete(); _partTracker.Remove(path); }
/// <summary> /// Gets a part by URI. /// </summary> /// <param name="partUri">A relative URI to the part.</param> /// <returns>An instance of <see cref="OpcPart"/>, or null if the part cannot be found.</returns> public OpcPart GetPart(Uri partUri) { var path = partUri.ToPackagePath(); if (!_partTracker.TryGetValue(path, out OpcPart part)) { var entry = Archive.GetEntry(path); if (entry == null) { return(null); } part = new OpcPart(this, entry.FullName, entry, _mode); _partTracker.Add(path, part); } return(part); }
/// <summary> /// Gets all package-wide parts. /// </summary> /// <returns>An enumerable source of parts.</returns> public IEnumerable <OpcPart> GetParts() { foreach (var entry in Archive.Entries) { if (entry.FullName.Equals(CONTENT_TYPES_XML, StringComparison.OrdinalIgnoreCase)) { continue; } if (!_partTracker.TryGetValue(entry.FullName, out OpcPart part)) { part = new OpcPart(this, entry.FullName, entry, _mode); _partTracker.Add(entry.FullName, part); } yield return(part); } }
/// <summary> /// Creates a new part. /// </summary> /// <param name="partUri">A relative URI where the part will exist in the package.</param> /// <param name="mimeType">The Content Type of the part. If the content type is not registered in the <see cref="ContentTypes"/>, it will automatically be added.</param> /// <returns>An instance of the part just created.</returns> public OpcPart CreatePart(Uri partUri, string mimeType) { var path = partUri.ToPackagePath(); if (Archive.GetEntry(path) != null) { throw new InvalidOperationException("The part already exists."); } var extension = Path.GetExtension(path).TrimStart('.'); if (!ContentTypes.Any(ct => string.Equals(extension, ct.Extension, StringComparison.OrdinalIgnoreCase))) { ContentTypes.Add(new OpcContentType(extension, mimeType.ToLower(), OpcContentTypeMode.Default)); } var zipEntry = Archive.CreateEntry(path, CompressionLevel.NoCompression); var part = new OpcPart(this, zipEntry.FullName, zipEntry, _mode); _partTracker.Add(zipEntry.FullName, part); return(part); }
private static void ApplyTimestamp(XDocument originalSignatureDocument, OpcPart signaturePart, byte[] timestampSignature) { XNamespace xmlDSigNamespace = OpcKnownUris.XmlDSig.AbsoluteUri; XNamespace xmlSignatureNamespace = OpcKnownUris.XmlDigitalSignature.AbsoluteUri; var document = new XDocument(originalSignatureDocument); var signature = new XElement(xmlDSigNamespace + "Object", new XElement(xmlSignatureNamespace + "TimeStamp", new XAttribute("Id", "idSignatureTimestamp"), new XElement(xmlSignatureNamespace + "Comment", ""), new XElement(xmlSignatureNamespace + "EncodedTime", Convert.ToBase64String(timestampSignature)) ) ); document.Element(xmlDSigNamespace + "Signature").Add(signature); using (var copySignatureStream = signaturePart.Open()) { using (var xmlWriter = new XmlTextWriter(copySignatureStream, System.Text.Encoding.UTF8)) { //The .NET implementation of OPC used by Visual Studio does not tollerate "white space" nodes. xmlWriter.Formatting = Formatting.None; document.Save(xmlWriter); } } }
private static (XDocument document, byte[] signature) GetSignatureToTimestamp(OpcPart signaturePart) { XNamespace xmlDSigNamespace = OpcKnownUris.XmlDSig.AbsoluteUri; using (var signatureStream = signaturePart.Open()) { var doc = XDocument.Load(signatureStream); var signature = doc.Element(xmlDSigNamespace + "Signature")?.Element(xmlDSigNamespace + "SignatureValue")?.Value?.Trim(); return(doc, Convert.FromBase64String(signature)); } }
internal OpcPackageTimestampBuilder(OpcPart part) { _part = part; Timeout = TimeSpan.FromSeconds(30); }
/// <summary> /// Dequeues a part from the signature builder. This file will not be part of the signature. /// </summary> /// <param name="part">The part to dequeue.</param> /// <returns>True if the file was dequeued, otherwise false.</returns> public bool DequeuePart(OpcPart part) => _enqueuedParts.Remove(part);
/// <summary> /// Enqueues a part that will be part of the package signature. /// </summary> /// <param name="part">The part to enqueue.</param> public void EnqueuePart(OpcPart part) => _enqueuedParts.Add(part);
internal OpcSignature(OpcPart signaturePart) { _detached = false; _signaturePart = signaturePart; }