0

簡単に言えば、私は文書に問題なく署名できます。しかし、それらを検証すると、毎回 false が返されます。Google と bing の最初の 5 ページまたは 6 ページを調べて解決策を探しましたが、見つかったすべての「修正」は役に立ちません。私はこれに1週間強取り組んでいるので、助けていただければ幸いです。また、これらの証明書の秘密鍵はエクスポートできず、エクスポートできません。それが重要かどうかはわかりません。また、今のところ ValidateCertificate を含めないことを選択しました。CheckSignature() で常に失敗します。ありがとうございました。

証明書を生成するために使用しているものは次のとおりです。

makecert -a SHA256 -n "CN=JEA2.me" -pe -r -len 2048 -sy 24 -sky signature -sv jeame2.pvk jeame2.cer

certmgr /add jeame2.cer /s /r localmachine root

makecert -sk "jea2.me" -iv jeame2.pvk -n "CN=JEA2IIS.me" -eku 1.3.6.1.4.1.311.10.3.12 -pe -sy 24 -ss my -sr localmachine -len 2048 -sky signature -ic Jeame2.cer IIS-ServerCert-Jeame2.cer

ここからローカル マシンに直接インストールします -> 信頼されたルート証明機関

    private static X509Certificate2 CheckXmldsigSignature(XmlDocument document)
    {
        X509Certificate2 certificate = null;

        try
        {
            XmlNodeList nodeList = document.GetElementsByTagName("Signature", Xmldsigns);

            if (nodeList.Count != 1)
            {
                Logger.ErrorFormat("Found {0} signature elements in file", nodeList.Count);
                throw new InvalidOperationException(
                    "The XML document must have a single element with local name: \"Signature\" and namespace URI: " + Xmldsigns);
            }
            else
            {
                Logger.DebugFormat("Found Signature element successfully");
            }

            RSAPKCS1SHA256SignatureDescription.Register();
            var signatureElement = (XmlElement)nodeList[0];
            var signedXml = new SignedXml(document);
            signedXml.LoadXml(signatureElement);

            var keyInfoX509 =
                    (KeyInfoX509Data)
                    (from KeyInfoClause kic in signedXml.KeyInfo where kic is KeyInfoX509Data select kic).Single();

            if (keyInfoX509.Certificates.Count != 1)
            {
                var msg = "The signature must contain information for one certificate.";
                Logger.Error(msg);
                throw new InvalidOperationException(msg);
            }
            else
            {
                Logger.DebugFormat("Extracted X509 certificate data successfully");
            }

            certificate = (X509Certificate2)keyInfoX509.Certificates[0];
            bool validSignature = signedXml.CheckSignature(); //was null parameters. This too does not work.

            if (!validSignature)
            {
                var msg = " SignedXml.CheckSignature returned false.";
                throw new InvalidOperationException(msg);
            }
            else
            {
                Logger.DebugFormat("SignedXml.CheckSignature returned true.");
            }
        }
        catch (Exception ex)
        {
            ScriptPro.Common.Logging.LogEx.LogException(Logger, ex);
            throw;
        }

        return certificate;
    }

   private static Stream SignSHA256Stream(X509Certificate2 certificate, Stream stream)
    {
        if (certificate == null)
        {
            Logger.Error("certificate argument is null");
            throw new ArgumentNullException("certificate");
        }

        if (stream == null)
        {
            Logger.Error("stream argument is null");
            throw new ArgumentNullException("stream");
        }

        RSAPKCS1SHA256SignatureDescription.Register();

        var document = new XmlDocument();
        document.PreserveWhitespace = true; // May not be necessary.
        document.Load(stream);
        XmlNode root = document.DocumentElement;
        XmlNodeList nodeList = document.GetElementsByTagName("Signature", Xmldsigns);

        while (nodeList.Count > 0)
        {
            root.RemoveChild(nodeList[0]);
        }

        Reference reference = new Reference(string.Empty);
        reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
        reference.AddTransform(new XmlDsigExcC14NTransform());
        reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
        CspParameters csp = new CspParameters(24);
        csp.Flags = CspProviderFlags.UseMachineKeyStore;
        csp.KeyContainerName = "XML_DISG_RSA_KEY";
        RSACryptoServiceProvider key = new RSACryptoServiceProvider(csp);
        key.PersistKeyInCsp = false;
        var keyInfo = new KeyInfo();
        keyInfo.AddClause(new KeyInfoX509Data(certificate));
        SignedXml sxml = new SignedXml(document);
        sxml.KeyInfo = keyInfo;
        sxml.SigningKey = key;
        sxml.SignedInfo.SignatureMethod = Xmldsigns256;
        sxml.AddReference(reference);
        sxml.ComputeSignature();

        XmlElement xmlDigitalSignature = sxml.GetXml();

        if (document.DocumentElement == null)
        {
            document.AppendChild(document.ImportNode(xmlDigitalSignature, true));
        }
        else
        {
            document.DocumentElement.AppendChild(document.ImportNode(xmlDigitalSignature, true));
        }

        if (document.FirstChild is XmlDeclaration)
        {
            document.RemoveChild(document.FirstChild);
        }

        MemoryStream outStream = new MemoryStream();
        document.Save(outStream);

        return outStream;
    }
    private static void SignSHA256File(X509Certificate2 certificate, FileInfo file)
    {
        if (certificate == null)
        {
            Logger.Error("certificate argument is null");
            throw new ArgumentNullException("certificate");
        }

        if (file == null)
        {
            Logger.Error("file argument is null");
            throw new ArgumentNullException("file");
        }

        if (!file.Exists)
        {
            Logger.ErrorFormat("File {0} does not exist.", file.Name);
            throw new ArgumentException("File must exist.", "file");
        }

        if (file.IsReadOnly)
        {
            Logger.ErrorFormat("File {0} is read only.", file.Name);
            throw new ArgumentException("File is read only.", "file");
        }

        FileStream stream = file.OpenRead();

        string s = string.Empty;
        using (StreamReader reader = new StreamReader(stream))
        {
            s = reader.ReadToEnd();
        }

        MemoryStream stream2 = new MemoryStream(Encoding.Default.GetBytes(s));
        Stream inStream = SignSHA256Stream(certificate, stream2);

        XmlDocument document = new XmlDocument();
        inStream.Seek(0L, SeekOrigin.Begin);

        document.Load(inStream);

        Logger.InfoFormat("Saving {0}", file.FullName);

        document.Save(file.FullName);
    }

public class RSAPKCS1SHA256SignatureDescription : SignatureDescription
{
    private const int PROV_RSA_AES = 24;

    public RSAPKCS1SHA256SignatureDescription()
    {
        this.KeyAlgorithm = "System.Security.Cryptography.RSACryptoServiceProvider";
        this.DigestAlgorithm = "System.Security.Cryptography.SHA256CryptoServiceProvider"; // use System.Security.Cryptography.SHA256Managed for .NET 4.5
        this.FormatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureFormatter";
        this.DeformatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureDeformatter";
    }

    public static void Register()
    {
        CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
    }

    public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
    {
        var asymmetricSignatureDeformatter = (AsymmetricSignatureDeformatter)CryptoConfig.CreateFromName(DeformatterAlgorithm);
        asymmetricSignatureDeformatter.SetKey(key);
        asymmetricSignatureDeformatter.SetHashAlgorithm("SHA256");
        return asymmetricSignatureDeformatter;
    }

    public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)
    {
        var asymmetricSignatureFormatter = (AsymmetricSignatureFormatter)CryptoConfig.CreateFromName(FormatterAlgorithm);
        asymmetricSignatureFormatter.SetKey(key);
        asymmetricSignatureFormatter.SetHashAlgorithm("SHA256");
        return asymmetricSignatureFormatter;
    }
}
}

ここに私の 2 つの XML ファイルがあります: 1.xml:

<node1>
  <node2>
  </node2>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
      <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
          <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        <DigestValue>3nIr0blku+Nsu3FgibCxfQRGBtSmtZL4JGodmaU8blE=    </DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>O3ihm7QwE/vh9VZ6CtdENAhB9Ve8jceATCgdJuaQkUHpPWxrG01TftUlrw9a/dQGfW48jJMPngwgcfqnbFspmEEGsBe1xoWQd6mdy2wVRBcQSjqdReNNzs0uQz3/1wPPk4Y2UO+fL+CVNzkIcMpne+t80c2eU4cHBa1WyL5qSlc=</SignatureValue>
<KeyInfo>
  <X509Data>
    <X509Certificate>MIICFDCCAX2gAwIBAgIQ2rStbEE1JJhHRLiuA4n/0jANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDEwtKQUxDT1JOLm1lMjAeFw0xNjAzMzAxODE1MDFaFw0zOTEyMzEyMzU5NTlaMBkxFzAVBgNVBAMTDkpBTENPUk5JSVMubWUyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLJEzyRjaHLfK6zrg1Xdx2yO34d5sbd7ajFFVmb3zPKtVGmuJlCBPsDTC84pzHBTywVVApi3U2UwtuCh96rQu5r3nYUT/E46CtexWiFATyh0M9+wD/h3hZj1CQ0YHTEZWznOWWIdbNRAcp99tGSALrwjH2rEJhGHHpVn7otCNmZQIDAQABo2AwXjATBgNVHSUEDDAKBggrBgEFBQcDATBHBgNVHQEEQDA+gBAgVyu7w3c59jEjiSh/vma+oRgwFjEUMBIGA1UEAxMLSkFMQ09STi5tZTKCEFvqkxy0Sd+mSgbqvsCEqKcwDQYJKoZIhvcNAQELBQADgYEAAcM6GlR3UpjIY4TWWuMiSyqiUiAGgg3JetiUXj1EVZ7TZVvyoVA1L/wd8ZHt+nZu1UtJmJ8sU7eu55TMVcX/xu7QoYsp6JtbPp5abLI6rnOCwDfyorrjM4S8Rm2RCO3PhL0NC9i9QBPfNV15FEbFpeqHZGw/xmyGzEv3EWxEESE=</X509Certificate>
      </X509Data>
    </KeyInfo>
  </Signature>
</node1>

2.xml:

<metadata>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
      <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
          <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        <DigestValue>wc+6kgUoF9TE7KL1OQXm0EzAIYZuVVc6w3zOKsIY8yU=    </DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>MDJn2QLG65LChsJOAN9zKmq4Br5JFSncaTMOmmsmL+DY4xcZt7e4VfI6/IehBkBUzDLeUJHWoE9sp7tVmArBiq/ZFm/ScB2/SRAAD+/NS0XxnxTPjvwu0JsmupNFJ364r/k31TYhI6TBmiCBIdZ6/3qV8LNPtS0iVrMkyhFw6L8=</SignatureValue>
    <KeyInfo>
      <X509Data>
        <X509Certificate>MIICFDCCAX2gAwIBAgIQ2rStbEE1JJhHRLiuA4n/0jANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDEwtKQUxDT1JOLm1lMjAeFw0xNjAzMzAxODE1MDFaFw0zOTEyMzEyMzU5NTlaMBkxFzAVBgNVBAMTDkpBTENPUk5JSVMubWUyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLJEzyRjaHLfK6zrg1Xdx2yO34d5sbd7ajFFVmb3zPKtVGmuJlCBPsDTC84pzHBTywVVApi3U2UwtuCh96rQu5r3nYUT/E46CtexWiFATyh0M9+wD/h3hZj1CQ0YHTEZWznOWWIdbNRAcp99tGSALrwjH2rEJhGHHpVn7otCNmZQIDAQABo2AwXjATBgNVHSUEDDAKBggrBgEFBQcDATBHBgNVHQEEQDA+gBAgVyu7w3c59jEjiSh/vma+oRgwFjEUMBIGA1UEAxMLSkFMQ09STi5tZTKCEFvqkxy0Sd+mSgbqvsCEqKcwDQYJKoZIhvcNAQELBQADgYEAAcM6GlR3UpjIY4TWWuMiSyqiUiAGgg3JetiUXj1EVZ7TZVvyoVA1L/wd8ZHt+nZu1UtJmJ8sU7eu55TMVcX/xu7QoYsp6JtbPp5abLI6rnOCwDfyorrjM4S8Rm2RCO3PhL0NC9i9QBPfNV15FEbFpeqHZGw/xmyGzEv3EWxEESE=</X509Certificate>
      </X509Data>
    </KeyInfo>
  </Signature>
</metadata>

public static bool VerifyXmldsigSignature(FileInfo file, bool useSHA256 = false)
    {
        Logger.InfoFormat("Checking Digital Signature and Certificate on {0}", file.FullName);

        bool validCertificate = false;

        if (file == null)
        {
            Logger.Error("file argument is null");
            throw new ArgumentNullException("file");
        }

        if (!file.Exists)
        {
            Logger.ErrorFormat("File {0} does not exist.", file.Name);
            throw new ArgumentException("File must exist.", "file");
        }

        try
        {
            var document = new XmlDocument();
            document.PreserveWhitespace = true;     document.Load(file.FullName);

            DateTime timestamp = DateTime.UtcNow;

            bool respectCertExpiration = HasTimestamp(document);

            if (respectCertExpiration)
            {
                timestamp = CheckXadesTimestamp(document);
            }

            var certificate = CheckXmldsigSignature(document);

            validCertificate = ValidateCertificate(certificate, timestamp, respectCertExpiration);

            Logger.InfoFormat("Digital Signature and Certificate passed verification on {0}", file.FullName);
        }
        catch (Exception ex)
        {
            string message = string.Format("{0} failed signature verification.", file.FullName);
            throw;
        }
4

2 に答える 2

0

アンダース、あなたの提案に感謝します。数週間試してみた後、ようやくコードを検証することができました。ようやく何かが機能するようになったので、皆さんと共有したいと思いました。検証方法は変更されておらず、Xades のものはカスタムであり、私のコードで署名されたファイルを検証する必要はありません。最後に、次の 2 つの URL を出発点として使用しましたが、Google の数十のページも役に立ちました。

https://blogs.msdn.microsoft.com/winsdk/2015/11/14/using-sha256-with-the-signedxml-class/ https://gist.github.com/sneal/f35de432115b840c4c1f#file-rsapkcs1sha256signaturedescription

private static Stream SignSHA256Stream(X509Certificate2 certificate, Stream stream)
    {
        if (certificate == null)
        {
            Logger.Error("certificate argument is null");
            throw new ArgumentNullException("certificate");
        }

        if (stream == null)
        {
            Logger.Error("stream argument is null");
            throw new ArgumentNullException("stream");
        }

        RSAPKCS1SHA256SignatureDescription.Register();

        var document = new XmlDocument();
        document.Load(stream);
        XmlNode root = document.DocumentElement;
        XmlNodeList nodeList = document.GetElementsByTagName("Signature", Xmldsigns);

        // nodeList is actively updated so we delete element [0] until there are none left.
        while (nodeList.Count > 0)
        {
            root.RemoveChild(nodeList[0]);
        }

        Reference reference = new Reference(string.Empty);
        reference.AddTransform(new XmlDsigEnvelopedSignatureTransform()); 
        reference.AddTransform(new XmlDsigExcC14NTransform());
        reference.DigestMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

        var keyInfo = new KeyInfo();
        keyInfo.AddClause(new KeyInfoX509Data(certificate));

        SignedXml sxml = new SignedXml(document);
        sxml.KeyInfo = keyInfo;
        sxml.SigningKey = certificate.PrivateKey;
        sxml.SignedInfo.SignatureMethod = Xmldsigns256;
        sxml.AddReference(reference);
        sxml.SignedInfo.CanonicalizationMethod = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
        sxml.ComputeSignature();

        XmlElement xmlDigitalSignature = sxml.GetXml();

        if (document.DocumentElement == null)
        {
            document.AppendChild(document.ImportNode(xmlDigitalSignature, true));
        }
        else
        {
            document.DocumentElement.AppendChild(document.ImportNode(xmlDigitalSignature, true));
        }

        if (document.FirstChild is XmlDeclaration)
        {
            document.RemoveChild(document.FirstChild);
        }

        MemoryStream outStream = new MemoryStream();
        document.Save(outStream);

        return outStream;
    }
于 2016-04-08T16:00:46.733 に答える