Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 无法使用Apache Santuario 1.4.6验证XML签名_Java_Xml_Security_Apache - Fatal编程技术网

Java 无法使用Apache Santuario 1.4.6验证XML签名

Java 无法使用Apache Santuario 1.4.6验证XML签名,java,xml,security,apache,Java,Xml,Security,Apache,我正在寻找一些帮助来解决我在使用ApacheSantuarioJava库版本1.4.6验证XML签名时遇到的问题。我有一个客户机/服务器解决方案,客户机在将文档发送到服务器之前对DOM文档进行签名。本人在文件上签字如下: public static void applySignature(X509Certificate cert, PrivateKey privateKey, Document doc) { try { XMLSignature sig = new

我正在寻找一些帮助来解决我在使用ApacheSantuarioJava库版本1.4.6验证XML签名时遇到的问题。我有一个客户机/服务器解决方案,客户机在将文档发送到服务器之前对DOM文档进行签名。本人在文件上签字如下:

public static void applySignature(X509Certificate cert, PrivateKey privateKey, Document doc)
{
    try
    {
        XMLSignature sig = new XMLSignature(doc, 
                                            "", 
                                            XMLSignature.ALGO_ID_SIGNATURE_RSA);

        sig.addResourceResolver(new XmlSignatureResolver());
        doc.getDocumentElement().appendChild(sig.getElement());

        Transforms transforms = new Transforms(doc);
        transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
        transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS);

        sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1);

        sig.addKeyInfo(cert);
        sig.addKeyInfo(cert.getPublicKey());

        sig.sign(privateKey);
    }
    catch (XMLSecurityException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
我核实签字如下:

public static boolean verifySignature(X509Certificate cert, Document doc)
{
    boolean validSignature = false;

    try
    {
        Element nscontext = createDSctx(doc, "ds", Constants.SignatureSpecNS); 

        // Remove any attributes of Signed Info
        Node signInfoNode = XPathAPI.selectSingleNode(doc, "//ds:SignedInfo", nscontext);

        int numAttributes = signInfoNode.getAttributes().getLength();
        if (numAttributes > 0)
        {
            for (int i = 0; i < numAttributes; i++)
            {
                String attrName = signInfoNode.getAttributes().item(0).getNodeName();
                signInfoNode.getAttributes().removeNamedItem(attrName);
            }    
        }

        Element sigElement = 
            (Element) XPathAPI.selectSingleNode(doc, "//ds:Signature", nscontext); 
        XMLSignature signature = new XMLSignature(sigElement, "");

        signature.setFollowNestedManifests(true); 
        signature.addResourceResolver(new XmlSignatureResolver());

        validSignature = signature.checkSignatureValue(cert);

        //  Remove the signature
        sigElement.getParentNode().removeChild(sigElement);            
    }
    catch (XMLSignatureException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    catch (XMLSecurityException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    catch (TransformerException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return validSignature;// validSignature;
}
在服务器端读取dom的代码是:

                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                dbf.setNamespaceAware(true);
                DocumentBuilder db = dbf.newDocumentBuilder();

                m_Logger.debug("Parsing Document");
                Document doc = db.parse(m_SenderInput);
                m_Logger.debug("Received DOM");   
应用签名之前的dom类似于以下内容(在应用签名之前对数据进行加密):


VosyFTcuAkzo6WPPLnnM2Nka+gpyD9r2cNy3fbSX8RjGg5dKktK9SGZAar5t3ci2mU6Nw9Ski2Td
g1WNei+kgns6vFET5Ff8m5/VIO24sBz30DPO5cAwfLax0slTjZWDRu7XXs/ORSK2PrB8B8qaO+me
W5IPLXJKL4LWZFIVCSDG3JJOOTUHR6CSTQUTEJRBLVTDVRY8JB2RNCJPV244ENG7BMK7HWCND
MZ20DUJFX14MTYKAQCVAGUHM9MPISVEIDRKYTXWCKMA2NCUHPXQZJYPTYJTHVJQFAPZ2KLA2NQV
DcMPUvmM+V0Y3kI5NBZq1vlIAg1i5JsZRniB+Q==8UCDr2ZzDvD5JczkPU7UnxRYBdxs6ZgL5s2ksHyn/FZvBVSwYh6o/RNX41FNN6W++zoxSq
A9QCPUS8RFXTW6TrzzeixJYBGZWVHP9NYIB4WBTZF6IR5EJAGKZDGGHUGCVTVKKBMqttpRCYM
7HA2iQzNpGH1tcGegDB8+W3ALDP8QN5Q3PG2UFBK880KXROZXAXKZVNKZFEZYAT0FNZF6J8BTCC
n1lxV02jCWyz1/2Gd/jfo8B2BLXVMZWm0WiM7Z/UK4PFSTQTQJPMB1CD+E+7Oh8TRJzIqC1dyPQVV+
kgdoJbM/2sZka1VCuUzEIEQ1fhH+iUE0ymtuw+djwhfqDAow1pfRJOsak2cXzLoYO7mwqmIHoeaM
hN9IAtI/TfXDHNSL8ledhYT/ZL2gmNSR1Jze6JZPaXgqkmBEGVgqbzLex/5drxOf/DQVcugSnqEw
UHRIKLSJU4JHOZNG4GIDJNPCKLPGJAILX1RGYO9N6PUDMVRNH+TZ1G7EFYDZORZT+yY8Je17NL
ah8mBQb/S5zGD7642aDR4UmVQthD3LTMIG/oxbzMIh/OOcC432SZ+ShAvUD+bU+GDDdcOKzemLPB
EV6QLSTFQONYHLSTQGIMU5Z2NXFPJIKRBCLX09Q5FOYTARVRGIZGJTOFUT4ZFWJMWF66YUIQP0H
gD9O95A+IFMWE8K9KUSAO9Q8ALXRXRQHPTFSYSCYDO2NSKBHSN5CkgSDK4JW5B6ZSOQZXJMZSYT
ZSBO0DHJABZVSSU0HETMRKRNLOABXAJPXSMQZ2HT/wgYnWSMZt839swJyOZhaMuOUfShAP1iVo+
m5xM+zw7SnsAwFozNw==
在applySignature之后以及在verifysignature方法中修改SignedInfo之后,XML是相同的。当我通过套接字发送文档时,问题似乎与SignedInfo引用的项有关;不知何故,验证期间发生的转换是添加46个字节,导致检查失败


不知道这是从哪里来的。有人有什么想法吗?

这些想法与您的错误没有直接关系,但稍后会导致失败:您不应该删除或更改SignedInfo元素中的任何内容。在规范化SignedInfo元素的摘要上计算最终签名值。因此,如果您在验证签名之前更改了任何内容,您肯定会破坏它


至于您的文档摘要无效的原因,可能有多种原因,仅凭猜测很难分析。如果您可以在这里发布未签名的文档,那么我可以告诉您正确的摘要值是多少,至少…

这与您的错误没有直接关系,但稍后会导致失败:您不应该删除或更改SignedInfo元素中的任何内容。在规范化SignedInfo元素的摘要上计算最终签名值。因此,如果您在验证签名之前更改了任何内容,您肯定会破坏它


至于您的文档摘要无效的原因,可能有多种原因,仅凭猜测很难分析。如果您可以在此处发布未签名的文档,那么我可以告诉您正确的摘要值,至少…

问题不在于SignedInfo,而在于KeyInfo节点。KeyInfo节点添加了一个名称空间属性,而在应用原始签名时,该属性并不存在。在检查签名值之前删除KeyInfo属性修复了我看到的问题。

问题不在于SignedInfo,而在于KeyInfo节点。KeyInfo节点添加了一个名称空间属性,而在应用原始签名时,该属性并不存在。在检查签名值之前删除KeyInfo属性修复了我看到的问题。

简短回答:在原始问题中,添加
doc.normalizeDocument()
位于应用签名的开头,因此在添加签名之前

更多信息:

我知道这是一个老问题,但我有一个类似的问题,没有得到任何答案解决。 事实上,我认为其中一个答案是错误的,它说问题在于验证。然而,我相信这是在签署!我希望把我的经验和解决方案放在这里能帮助有类似问题的人

我正在生成一个XML文档,然后对它进行签名。我试着和阿帕奇和桑塔里奥签约。当这不起作用时,我切换到javax.xml.crypto.dsig

这两种方法生成的XML文档在我使用Santuario和外部工具检查时没有正确签名

首先是我尝试生成的签名XML示例:

<signed-envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="somenamespace" xsi:schemaLocation="someshemelocation">
   <object xml:id="object0">
      ...
   </object>
   <signatures>
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
         ...
         <SignedInfo>
            <Reference URI="#object0">
            ...
         </SignedInfo>
      </Signature>
   </signatures>
</signed-envelope>
这是正确的验证方法!这里的一个答案表明它是不正确的,并试图修复它,但事实上这是正确的。这里的问题不在于验证,而在于签名

问题是,Santuario表明在对文档签名时没有添加此名称空间!这让我相信我生成的
文档
对象有问题。 生成我的XML文档时,将命名空间添加到根元素中,如下所示:

rootElement.setAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "xsi:noNamespaceSchemaLocation", "some_namespace");
经过大量搜索,我发现
doc.normalizeDocument()
解决了类似的问题。我试过了,一切都好

我不知道为什么
doc.normalizeDocument()
能让一切正常,但现在我可以用ApacheSantuario和javax.xml.crypto.dsig正确签名了。所以他们都需要这个来正确签名。

简短回答:在原始问题中,添加
doc.normalizeDocument()
位于应用签名的开头,因此在添加签名之前

更多信息:

我知道这是一个老问题,但我有一个类似的问题
<signed-envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="somenamespace" xsi:schemaLocation="someshemelocation">
   <object xml:id="object0">
      ...
   </object>
   <signatures>
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
         ...
         <SignedInfo>
            <Reference URI="#object0">
            ...
         </SignedInfo>
      </Signature>
   </signatures>
</signed-envelope>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
rootElement.setAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "xsi:noNamespaceSchemaLocation", "some_namespace");