string C14N (string xml)
		{
			XmlDsigExcC14NTransform t = new XmlDsigExcC14NTransform ();
			XmlDocument doc = new XmlDocument ();
			doc.LoadXml (xml);
			t.LoadInput (doc);
			return new StreamReader (t.GetOutput () as Stream).ReadToEnd ();
		}
        /// <summary>
        ///     Выполнить каноникализацию XML-узла
        /// </summary>
        /// <param name="node">
        ///     Узел
        /// </param>
        /// <returns>
        ///     Каноникализированный XM-текст
        /// </returns>
        public static string Canonicalize(this XmlNode node)
        {
            var transform = new XmlDsigExcC14NTransform();
            var document = new XmlDocument();

            document.LoadXml(node.OuterXml);
            transform.LoadInput(document);

            using (var stream = (Stream) transform.GetOutput())
            using (var reader = new StreamReader(stream))
            {
                return reader.ReadToEnd();
            }
        }
Exemple #3
0
        private SignatureVerificationResult VerifyAuthenticodeExpectedHash(XmlElement licenseNode)
        {
            XmlElement element = licenseNode.SelectSingleNode("r:grant/as:ManifestInformation", this.m_namespaceManager) as XmlElement;

            if (element == null)
            {
                return(SignatureVerificationResult.BadSignatureFormat);
            }
            string attribute = element.GetAttribute("Hash");

            if (string.IsNullOrEmpty(attribute))
            {
                return(SignatureVerificationResult.BadSignatureFormat);
            }
            byte[]      lhs      = BackwardHexToBytes(attribute);
            XmlDocument document = new XmlDocument {
                PreserveWhitespace = true
            };
            XmlReaderSettings settings = new XmlReaderSettings {
                DtdProcessing = DtdProcessing.Parse
            };

            using (TextReader reader = new StringReader(this.m_manifestXml.OuterXml))
            {
                using (XmlReader reader2 = XmlReader.Create(reader, settings, this.m_manifestXml.BaseURI))
                {
                    document.Load(reader2);
                }
            }
            XmlElement oldChild = document.SelectSingleNode("//asm:assembly/ds:Signature", this.m_namespaceManager) as XmlElement;

            oldChild.ParentNode.RemoveChild(oldChild);
            XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform();

            transform.LoadInput(document);
            byte[] rhs = null;
            using (SHA1CryptoServiceProvider provider = new SHA1CryptoServiceProvider())
            {
                rhs = provider.ComputeHash(transform.GetOutput() as MemoryStream);
            }
            if (!CompareBytes(lhs, rhs))
            {
                return(SignatureVerificationResult.BadDigest);
            }
            return(SignatureVerificationResult.Valid);
        }
Exemple #4
0
		public void DigestValue_LF ()
		{
			XmlDocument doc = CreateSomeXml ("\n");
			XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform ();
			transform.LoadInput (doc);
			Stream s = (Stream) transform.GetOutput ();
			string output = Stream2String (s);
			Assert.AreEqual ("<person>\n  <birthplace>Brussels</birthplace>\n</person>", output, "#1");

			s.Position = 0;

			HashAlgorithm hash = HashAlgorithm.Create ("System.Security.Cryptography.SHA1CryptoServiceProvider");
			byte[] digest = hash.ComputeHash (s);
			Assert.AreEqual ("e3dsi1xK8FAx1vsug7J203JbEAU=", Convert.ToBase64String (digest), "#2");

			X509Certificate2 cert = new X509Certificate2 (_pkcs12, "mono");
			SignedXml signedXml = new SignedXml (doc);
			signedXml.SigningKey = cert.PrivateKey;
			signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;

			Reference reference = new Reference ();
			reference.Uri = "";

			XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform ();
			reference.AddTransform (env);
			signedXml.AddReference (reference);

			KeyInfo keyInfo = new KeyInfo ();
			KeyInfoX509Data x509KeyInfo = new KeyInfoX509Data ();
			x509KeyInfo.AddCertificate (new X509Certificate2 (_cert));
			x509KeyInfo.AddCertificate (cert);
			keyInfo.AddClause (x509KeyInfo);
			signedXml.KeyInfo = keyInfo;

			signedXml.ComputeSignature ();

			digest = reference.DigestValue;
			Assert.AreEqual ("e3dsi1xK8FAx1vsug7J203JbEAU=", Convert.ToBase64String (digest), "#3");

			Assert.AreEqual ("<SignedInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\">" 
				+ "<CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" />"
				+ "<SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\" />"
				+ "<Reference URI=\"\">"
				+ "<Transforms>"
				+ "<Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\" />"
				+ "</Transforms>"
				+ "<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" />"
				+ "<DigestValue>e3dsi1xK8FAx1vsug7J203JbEAU=</DigestValue>"
				+ "</Reference>"
				+ "</SignedInfo>", signedXml.SignedInfo.GetXml ().OuterXml, "#4");
		}
        private SignatureVerificationResult VerifyAuthenticodeExpectedHash(XmlElement licenseNode)
        {
            Debug.Assert(licenseNode != null, "licenseNode != null");

            // Get the expected hash value from the signature
            XmlElement manifestInformation = licenseNode.SelectSingleNode("r:grant/as:ManifestInformation",
                                                                          m_namespaceManager) as XmlElement;

            if (manifestInformation == null)
            {
                return(SignatureVerificationResult.BadSignatureFormat);
            }

            string expectedHashString = manifestInformation.GetAttribute("Hash");

            if (String.IsNullOrEmpty(expectedHashString))
            {
                return(SignatureVerificationResult.BadSignatureFormat);
            }

            // The expected hash value is stored in backward order, so we cannot use a standard hex to bytes
            // routine to decode it.
            byte[] expectedHash = BackwardHexToBytes(expectedHashString);

            // Make a normalized copy of the manifest without the strong name signature attached
            XmlDocument normalizedManifest = new XmlDocument();

            normalizedManifest.PreserveWhitespace = true;

            XmlReaderSettings normalizationSettings = new XmlReaderSettings();

            normalizationSettings.DtdProcessing = DtdProcessing.Parse;

            using (TextReader manifestReader = new StringReader(m_manifestXml.OuterXml))
                using (XmlReader xmlReader = XmlReader.Create(manifestReader, normalizationSettings, m_manifestXml.BaseURI)) {
                    normalizedManifest.Load(xmlReader);
                }

            XmlElement signatureNode = normalizedManifest.SelectSingleNode("//asm:assembly/ds:Signature",
                                                                           m_namespaceManager) as XmlElement;

            Debug.Assert(signatureNode != null, "signatureNode != null");

            signatureNode.ParentNode.RemoveChild(signatureNode);

            // calculate the hash value of the manifest
            XmlDsigExcC14NTransform canonicalizedXml = new XmlDsigExcC14NTransform();

            canonicalizedXml.LoadInput(normalizedManifest);

            byte[] actualHash = null;
            using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) {
                actualHash = sha1.ComputeHash(canonicalizedXml.GetOutput() as MemoryStream);
            }

            if (!CompareBytes(expectedHash, actualHash))
            {
                return(SignatureVerificationResult.BadDigest);
            }

            return(SignatureVerificationResult.Valid);
        }
Exemple #6
0
        private static byte[] ComputeHashFromManifest(XmlDocument manifestDom, bool oldFormat)
        {
            if (oldFormat)
            {
                XmlDsigExcC14NTransform exc = new XmlDsigExcC14NTransform();
                exc.LoadInput(manifestDom);
                using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
                {
                    byte[] hash = sha1.ComputeHash(exc.GetOutput() as MemoryStream);
                    if (hash == null)
                    {
                        throw new CryptographicException(Win32.TRUST_E_BAD_DIGEST);
                    }

                    return hash;
                }
            }
            else
            {
                // Since the DOM given to us is not guaranteed to be normalized,
                // we need to normalize it ourselves. Also, we always preserve
                // white space as Fusion XML engine always preserve white space.
                XmlDocument normalizedDom = new XmlDocument();
                normalizedDom.PreserveWhitespace = true;

                // Normalize the document
                using (TextReader stringReader = new StringReader(manifestDom.OuterXml))
                {
                    XmlReaderSettings settings = new XmlReaderSettings();
                    settings.DtdProcessing = DtdProcessing.Parse;
                    XmlReader reader = XmlReader.Create(stringReader, settings, manifestDom.BaseURI);
                    normalizedDom.Load(reader);
                }

                XmlDsigExcC14NTransform exc = new XmlDsigExcC14NTransform();
                exc.LoadInput(normalizedDom);
                using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
                {
                    byte[] hash = sha1.ComputeHash(exc.GetOutput() as MemoryStream);
                    if (hash == null)
                    {
                        throw new CryptographicException(Win32.TRUST_E_BAD_DIGEST);
                    }

                    return hash;
                }
            }
        }
		public void PropagatedNamespaces ()
		{
			XmlDocument doc = new XmlDocument ();
			doc.AppendChild (doc.CreateElement ("foo", "urn:foo"));
			doc.DocumentElement.AppendChild (doc.CreateElement ("bar", "urn:bar"));
			Assert.AreEqual (String.Empty, doc.DocumentElement.GetAttribute ("xmlns:f"), "#1");
			XmlDsigExcC14NTransform t = new XmlDsigExcC14NTransform ();
			t.LoadInput (doc);
			t.PropagatedNamespaces.Add ("f", "urn:foo");
			t.PropagatedNamespaces.Add ("b", "urn:bar");
			Stream s = t.GetOutput () as Stream;
			Assert.AreEqual (new StreamReader (s, Encoding.UTF8).ReadToEnd (), "<f:foo xmlns:f=\"urn:foo\"><b:bar xmlns:b=\"urn:bar\"></b:bar></f:foo>");
			Assert.AreEqual ("urn:foo", doc.DocumentElement.GetAttribute ("xmlns:f"), "#2");
		}
Exemple #8
0
        public byte[] ComputeHashValueOfElementList(XmlElement signatureXmlElement, ArrayList elementXpaths)
        {
            XmlDocument xmlDocument;
            XmlNamespaceManager xmlNamespaceManager;
            XmlNodeList searchXmlNodeList;
            XmlElement composedXmlElement;
            XmlDsigExcC14NTransform xmlTransform;

            Stream canonicalizedStream;
            //SHA1 sha1Managed;
            byte[] retVal;

            xmlDocument = signatureXmlElement.OwnerDocument;
            composedXmlElement = xmlDocument.CreateElement("ComposedElement", SignedXml.XmlDsigNamespaceUrl);
            xmlNamespaceManager = new XmlNamespaceManager(xmlDocument.NameTable);
            xmlNamespaceManager.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
            xmlNamespaceManager.AddNamespace("xsd", XadesSignedXml.XadesNamespaceUri);
            foreach (string elementXpath in elementXpaths)
            {
                searchXmlNodeList = signatureXmlElement.SelectNodes(elementXpath, xmlNamespaceManager);
                if (searchXmlNodeList.Count == 0)
                {
                    throw new CryptographicException("Element " + elementXpath + " not found while calculating hash");
                }
                foreach (XmlNode xmlNode in searchXmlNodeList)
                {
                    //jbonilla Id attr deprecated
                    //if (((XmlElement)xmlNode).HasAttribute("Id"))
                    //{
                    //    elementIdValues.Add(((XmlElement)xmlNode).Attributes["Id"].Value);
                    //    composedXmlElement.AppendChild(xmlNode);
                    //}
                    //else
                    //{
                    //    throw new CryptographicException("Id attribute missing on " + xmlNode.LocalName + " element");
                    //}
                    composedXmlElement.AppendChild(xmlNode);
                }
            }

            //Initialise the stream to read the node list
            MemoryStream nodeStream = new MemoryStream();
            XmlWriter xw = XmlWriter.Create(nodeStream);
            composedXmlElement.ChildNodes[0].WriteTo(xw);
            xw.Flush();
            nodeStream.Position = 0;

            //modificado
            xmlTransform = new XmlDsigExcC14NTransform();
            xmlTransform.LoadInput(nodeStream);

            canonicalizedStream = (Stream)xmlTransform.GetOutput(typeof(Stream));

            //sha1Managed = new SHA1Managed();
            //retVal = sha1Managed.ComputeHash(canonicalizedStream);
            IDigest digest = this.tspSource.GetMessageDigest();
            byte[] canonicalizedBytes = Streams.ReadAll(canonicalizedStream);
            digest.BlockUpdate(canonicalizedBytes, 0, canonicalizedBytes.Length);
            retVal = DigestUtilities.DoFinal(digest);

            canonicalizedStream.Close();

            return retVal;
        }
		public void SimpleNamespacePrefixes ()
		{
			string input = "<a:Action xmlns:a='urn:foo'>http://tempuri.org/IFoo/Echo</a:Action>";
			string expected = @"<a:Action xmlns:a=""urn:foo"">http://tempuri.org/IFoo/Echo</a:Action>";

			XmlDocument doc = new XmlDocument ();
			doc.LoadXml (input);
			XmlDsigExcC14NTransform t = new XmlDsigExcC14NTransform ();
			t.LoadInput (doc);
			Stream s = t.GetOutput () as Stream;
			Assert.AreEqual (new StreamReader (s, Encoding.UTF8).ReadToEnd (), expected);
		}
Exemple #10
0
        private static void SignXmlSec1(EnvConfig envConfig, string templateName, string outputName, AppId appId)
        {
            Program.LogAction("signing with xmlsec1: [{0}] => [{1}]", templateName, outputName);

            // load manifest input xml
            var docTemplate = new XmlDocument();
            docTemplate.Load(templateName);
            var nsmgr = CreateDefaultXmlNsmgr(docTemplate);

            // insert publisher identity
            var pfx = UnlockPfx(File.ReadAllBytes(envConfig.ClickOnce.KeyFile));
            var cert = pfx.Certificates.Cast<X509Certificate>().Single();
            var publisherName = cert.SubjectName;
            // as described on http://msdn.microsoft.com/en-us/library/dd996956.aspx
            var issuerKeyHash = FormatKey(_sha1.ComputeHash(cert.PublicKey));

            var publisherIdentity = docTemplate.CreateElement("publisherIdentity", ASMv2_NS);
            SetOrReplaceAttribute(publisherIdentity, "name", null, publisherName);
            SetOrReplaceAttribute(publisherIdentity, "issuerKeyHash", null, issuerKeyHash);

            docTemplate.ChildNodes.OfType<XmlElement>().Last().AppendChild(publisherIdentity);

            var fusionTemplateName = templateName + ".fusion";
            docTemplate.Save(fusionTemplateName);

            //
            // Calculate ManifestInformation Hash
            // ==================================
            // The Fusion XML engine is always preserving whitespace, therefore we need to
            // use a specially configured XmlDocument to normalize and sign the Manifest.
            //
            byte[] hash;
            {
                var fusionDoc = new XmlDocument();
                fusionDoc.PreserveWhitespace = true;
                fusionDoc.Load(fusionTemplateName);

                var transform = new XmlDsigExcC14NTransform();
                transform.LoadInput(fusionDoc);
                hash = _sha1.ComputeHash((MemoryStream)transform.GetOutput());
            }

            // Load SignatureBlock into DOM
            var signatureTemplate = LoadXmlFromResource("PrepareEnv.Templates.SignatureBlock.xml");
            foreach (XmlNode sigNode in signatureTemplate.DocumentElement.ChildNodes)
            {
                var newChild = docTemplate.ImportNode(sigNode, deep: true);
                docTemplate.DocumentElement.AppendChild(newChild);
                foreach (XmlNode assemblyId in newChild.SelectNodes("//as:assemblyIdentity", nsmgr))
                {
                    // authenticode assemblyIdentity looks like asmv1:assemblyIdentity
                    FillAppId(envConfig, assemblyId, appId);
                }
            }

            // Set ManifestInformation Hash
            var manifestInfo = docTemplate.SelectSingleNode("//as:ManifestInformation", nsmgr);
            SetOrReplaceAttribute(manifestInfo, "Hash", null, FormatKey(hash));

            // Set AuthenticodePublisher's SubjectName
            var subjectName = docTemplate.SelectSingleNode("//as:AuthenticodePublisher/as:X509SubjectName", nsmgr);
            subjectName.InnerText = publisherName;

            // Sign everything
            Program.LogDetail("saving to xmlsec1 template: [{0}]", templateName + ".xmlsec1");
            docTemplate.Save(templateName + ".xmlsec1");

            var pw = _passphrase == null ? string.Empty : string.Format("--pwd \"{0}\"", _passphrase);

            // resign manifest RelData
            var relDataArgs = string.Format("--sign {0} {1} {2} --node-xpath \"//*[local-name()='RelData']\" --enabled-key-data rsa,x509 --output \"{3}.reldata\" \"{4}.xmlsec1\"",
                                            pw,
                                            envConfig.ClickOnce.KeyFile.EndsWith("pfx") ? "--pkcs12" : "--privkey-pem",
                                            envConfig.ClickOnce.KeyFile,
                                            outputName,
                                            templateName);
            Program.LogDetail("signing reldata to [{0}.reldata]", outputName);
            var proc = Process.Start(new ProcessStartInfo("xmlsec1", relDataArgs) { UseShellExecute = false });
            proc.WaitForExit();
            if (proc.ExitCode != 0)
            {
                throw new InvalidOperationException(string.Format("xmlsec1 complained about {0}", relDataArgs));
            }

            // resign complete manifest
            var finalArgs = string.Format("--sign {0} {1} {2} --enabled-key-data rsa,x509 --output \"{3}\" \"{3}.reldata\"",
                                          pw,
                                          envConfig.ClickOnce.KeyFile.EndsWith("pfx") ? "--pkcs12" : "--privkey-pem",
                                          envConfig.ClickOnce.KeyFile,
                                          outputName);
            Program.LogDetail("signing final to : [{0}]", outputName);
            proc = Process.Start(new ProcessStartInfo("xmlsec1", finalArgs) { UseShellExecute = false });
            proc.WaitForExit();
            if (proc.ExitCode != 0)
            {
                throw new InvalidOperationException(string.Format("xmlsec1 complained about {0}", finalArgs));
            }
        }
		void AppendNegotiationMessageXml (XmlReader reader, TlsServerSessionInfo tlsInfo)
		{
			XmlDsigExcC14NTransform t = new XmlDsigExcC14NTransform ();
			XmlDocument doc = new XmlDocument ();
			doc.PreserveWhitespace = true;
			reader.MoveToContent ();
			doc.AppendChild (doc.ReadNode (reader));
			t.LoadInput (doc);
			MemoryStream stream = (MemoryStream) t.GetOutput ();
			byte [] bytes = stream.ToArray ();
			tlsInfo.Messages.Write (bytes, 0, bytes.Length);
		}
        /// <summary>
        ///     Verify the hash of the manifest without any signature attached is what the Authenticode
        ///     signature expects it to be
        /// </summary>
        private SignatureVerificationResult VerifyAuthenticodeExpectedHash(XmlElement licenseNode) {
            Debug.Assert(licenseNode != null, "licenseNode != null");

            // Get the expected hash value from the signature
            XmlElement manifestInformation = licenseNode.SelectSingleNode("r:grant/as:ManifestInformation",
                                                                          m_namespaceManager) as XmlElement;
            if (manifestInformation == null)
                return SignatureVerificationResult.BadSignatureFormat;

            string expectedHashString = manifestInformation.GetAttribute("Hash");
            if (String.IsNullOrEmpty(expectedHashString)) {
                return SignatureVerificationResult.BadSignatureFormat;
            }

            // The expected hash value is stored in backward order, so we cannot use a standard hex to bytes
            // routine to decode it.
            byte[] expectedHash = BackwardHexToBytes(expectedHashString);

            // Make a normalized copy of the manifest without the strong name signature attached
            XmlDocument normalizedManifest = new XmlDocument();
            normalizedManifest.PreserveWhitespace = true;

            XmlReaderSettings normalizationSettings = new XmlReaderSettings();
            normalizationSettings.DtdProcessing = DtdProcessing.Parse;

            using (TextReader manifestReader = new StringReader(m_manifestXml.OuterXml))
            using (XmlReader xmlReader = XmlReader.Create(manifestReader, normalizationSettings, m_manifestXml.BaseURI)) {
                normalizedManifest.Load(xmlReader);
            }

            XmlElement signatureNode = normalizedManifest.SelectSingleNode("//asm:assembly/ds:Signature",
                                                                           m_namespaceManager) as XmlElement;
            Debug.Assert(signatureNode != null, "signatureNode != null");

            signatureNode.ParentNode.RemoveChild(signatureNode);

            // calculate the hash value of the manifest
            XmlDsigExcC14NTransform canonicalizedXml = new XmlDsigExcC14NTransform();
            canonicalizedXml.LoadInput(normalizedManifest);

            byte[] actualHash = null;
            using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) {
                actualHash = sha1.ComputeHash(canonicalizedXml.GetOutput() as MemoryStream);
            }

            if (!CompareBytes(expectedHash, actualHash)) {
                return SignatureVerificationResult.BadDigest;
            }

            return SignatureVerificationResult.Valid;
        }
 private static byte[] ComputeHashFromManifest(XmlDocument manifestDom, bool oldFormat)
 {
     if (oldFormat)
     {
         XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform();
         transform.LoadInput(manifestDom);
         using (SHA1CryptoServiceProvider provider = new SHA1CryptoServiceProvider())
         {
             byte[] buffer = provider.ComputeHash(transform.GetOutput() as MemoryStream);
             if (buffer == null)
             {
                 throw new CryptographicException(-2146869232);
             }
             return buffer;
         }
     }
     XmlDocument document = new XmlDocument {
         PreserveWhitespace = true
     };
     using (TextReader reader = new StringReader(manifestDom.OuterXml))
     {
         XmlReaderSettings settings = new XmlReaderSettings {
             DtdProcessing = DtdProcessing.Parse
         };
         XmlReader reader2 = XmlReader.Create(reader, settings, manifestDom.BaseURI);
         document.Load(reader2);
     }
     XmlDsigExcC14NTransform transform2 = new XmlDsigExcC14NTransform();
     transform2.LoadInput(document);
     using (SHA1CryptoServiceProvider provider2 = new SHA1CryptoServiceProvider())
     {
         byte[] buffer2 = provider2.ComputeHash(transform2.GetOutput() as MemoryStream);
         if (buffer2 == null)
         {
             throw new CryptographicException(-2146869232);
         }
         return buffer2;
     }
 }
 private SignatureVerificationResult VerifyAuthenticodeExpectedHash(XmlElement licenseNode)
 {
     XmlElement element = licenseNode.SelectSingleNode("r:grant/as:ManifestInformation", this.m_namespaceManager) as XmlElement;
     if (element == null)
     {
         return SignatureVerificationResult.BadSignatureFormat;
     }
     string attribute = element.GetAttribute("Hash");
     if (string.IsNullOrEmpty(attribute))
     {
         return SignatureVerificationResult.BadSignatureFormat;
     }
     byte[] lhs = BackwardHexToBytes(attribute);
     XmlDocument document = new XmlDocument {
         PreserveWhitespace = true
     };
     XmlReaderSettings settings = new XmlReaderSettings {
         DtdProcessing = DtdProcessing.Parse
     };
     using (TextReader reader = new StringReader(this.m_manifestXml.OuterXml))
     {
         using (XmlReader reader2 = XmlReader.Create(reader, settings, this.m_manifestXml.BaseURI))
         {
             document.Load(reader2);
         }
     }
     XmlElement oldChild = document.SelectSingleNode("//asm:assembly/ds:Signature", this.m_namespaceManager) as XmlElement;
     oldChild.ParentNode.RemoveChild(oldChild);
     XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform();
     transform.LoadInput(document);
     byte[] rhs = null;
     using (SHA1CryptoServiceProvider provider = new SHA1CryptoServiceProvider())
     {
         rhs = provider.ComputeHash(transform.GetOutput() as MemoryStream);
     }
     if (!CompareBytes(lhs, rhs))
     {
         return SignatureVerificationResult.BadDigest;
     }
     return SignatureVerificationResult.Valid;
 }