Java 无法使用Apache Santuario 1.4.6验证XML签名
我正在寻找一些帮助来解决我在使用ApacheSantuarioJava库版本1.4.6验证XML签名时遇到的问题。我有一个客户机/服务器解决方案,客户机在将文档发送到服务器之前对DOM文档进行签名。本人在文件上签字如下: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
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");