/// <summary>
        /// Replaces the document's contents with the contents of the given replacement's contents.
        /// </summary>
        /// <param name="document">The destination document</param>
        /// <param name="replacement">The source document</param>
        /// <returns>The original document with replaced contents</returns>
        public static OpenXmlPackage ReplaceWith(this OpenXmlPackage document,
                                                 OpenXmlPackage replacement)
        {
            if (document == null)
            {
                throw new ArgumentNullException("document");
            }
            if (replacement == null)
            {
                throw new ArgumentNullException("replacement");
            }

            // Delete all parts (i.e., the direct relationship targets and their
            // children).
            document.DeleteParts(document.GetPartsOfType <OpenXmlPart>());

            // Add the replacement's parts to the document.
            foreach (var part in replacement.Parts)
            {
                document.AddPart(part.OpenXmlPart, part.RelationshipId);
            }

            // Save and return.
            document.Package.Flush();
            return(document);
        }
        /// <summary>
        /// Signs the given <paramref name="openXmlPackage"/>, using the given
        /// <paramref name="certificate"/>.
        /// </summary>
        /// <param name="openXmlPackage">The <see cref="OpenXmlPackage"/>.</param>
        /// <param name="certificate">The <see cref="X509Certificate2"/>.</param>
        public static void Sign(OpenXmlPackage openXmlPackage, X509Certificate2 certificate)
        {
            if (openXmlPackage == null)
            {
                throw new ArgumentNullException(nameof(openXmlPackage));
            }
            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }

            RSA privateKey = certificate.GetRSAPrivateKey();

            using SHA256 hashAlgorithm = SHA256.Create();

            // Create KeyInfo.
            var keyInfo = new KeyInfo();

            keyInfo.AddClause(new KeyInfoX509Data(certificate));

            // Create a Signature XmlElement.
            var signedXml = new SignedXml {
                SigningKey = privateKey, KeyInfo = keyInfo
            };

            signedXml.Signature.Id = Constants.PackageSignatureId;
            signedXml.SignedInfo.SignatureMethod = Constants.SignatureMethod;
            signedXml.AddReference(CreatePackageObjectReference());
            signedXml.AddObject(CreatePackageObject(openXmlPackage.Package, hashAlgorithm));
            signedXml.ComputeSignature();
            XmlElement signature = signedXml.GetXml();

            // Get or create the DigitalSignatureOriginPart.
            DigitalSignatureOriginPart dsOriginPart =
                openXmlPackage.GetPartsOfType <DigitalSignatureOriginPart>().FirstOrDefault() ??
                openXmlPackage.AddNewPart <DigitalSignatureOriginPart>();

            var xmlSignaturePart = dsOriginPart.AddNewPart <XmlSignaturePart>();

            // Write the Signature XmlElement to the XmlSignaturePart.
            using Stream stream    = xmlSignaturePart.GetStream(FileMode.Create, FileAccess.Write);
            using XmlWriter writer = XmlWriter.Create(stream);
            signature.WriteTo(writer);
        }