我有一个签名的XML文档,我可以验证签名,我感兴趣的是获取某些工作字段:
<?xml version="1.0" encoding="UTF-8"?>
<inicio>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#1500-Fri Jan 30 19:11:38 BOT 2015">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>YOzKDc7CB3QvedYMF2ZBB6omlsg=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
DLZKHySIMKwFuB1wc8cR7w/UbLhYyZtul/ndFch1GCeiKrmohyNOGO82Hbcm+rFEWxK1yMx2sKtM
KnuPTTCnIiZaYCLax5UJUe27AVqzpHZOc7+UKBmQoOOi3gYfAuyCZX5xBv0lrFNuigoNv6b0Z00B
u5Eu5e2zf01zceUqig40Y3yWUpEVRl+nbEUmVEBT+8fFwcigIQhqMbwFftGO8mcu55VKbGmMZS7c
pwzfq+PsTrnDDHbZ9cme/8p3lWo8TGTEDTcQ2HZoSI5VAPR2/fGDGKtS5PEG0Vbb0WFdVZ+PKuOA
hXqiP947xi6PP6Qv1bCbUqwsNLwTfuTjNR9lGg==
</ds:SignatureValue>
<ds:KeyInfo>
<ds:KeyName>50</ds:KeyName>
</ds:KeyInfo>
<ds:Object Id="1500-Fri Jan 30 19:11:38 BOT 2015">
<DATOS>
<num_orden>49</num_orden>
<cod_alfanumerico>HJYafrtr3456ABDFG</cod_alfanumerico>
<cod_pais>BO</cod_pais>
</DATOS></ds:Object>
</ds:Signature>
<Otros>TAG que no debe estar firmado</Otros>
</inicio>
我试图获取标签内的字段&lt; DATOS&gt;和此标记中包含的节点,但没有成功。 在java中,我可以验证签名,但是我无法访问XML标记以找到我需要使用的DOM和JDOM。
try{
if (doc == null){
doc = createFromString(IOUtils.toString(in));
LOG.info("Documento creado\n{}", documentToString(doc));
}
LOG.info("documento a verificar\n{}", documentToString(doc));
URL url = getClass().getResource("/repositorio.jks");
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(url.openStream(), claveRepositorio.toCharArray());
Certificate cer = ks.getCertificate("pruebas.certificado");
Map<String, Certificate> pubring = new HashMap<String, Certificate>();
pubring.put("50", cer);
pubring.put("09", cer);
NodeList signatures = doc.getElementsByTagNameNS(Constants.SignatureSpecNS, "Signature");
if (signatures.getLength() < 1) {
LOG.error("This message does not contain any signature");
return;
}
signatures.getLength());
for (int i = 0; i < signatures.getLength(); i++) {
Element sigElement = (Element) signatures.item(i);
OutputStream out = new WriterOutputStream();
XMLUtils.ElementToStream(sigElement, out);
LOG.info("Part of the signature to verify\n{}", out);
XMLSignature signature = new XMLSignature(sigElement, "");
String keyName = signature.getKeyInfo().itemKeyName(0).getKeyName();
Certificate certificado = pubring.get(keyName);
if (certificado == null) {
String msg = "I do not have the public certificate signer...";
LOG.error(msg);
fail(msg);
return;
}
PublicKey pk = certificado.getPublicKey();
X509Certificate x509 = X509Certificate.getInstance(cer.getEncoded());
Date notBefore = x509.getNotBefore();
Date notAfter = x509.getNotAfter();
LOG.debug("certificate '{}' valid from '{}' to '{}'",
new Object[] { keyName, sdf.format(notBefore), sdf.format(notAfter) });
try {
x509.checkValidity();
} catch (CertificateNotYetValidException e) {
String msg = "Participant Certificate '" + keyName + "' not valid";
LOG.error(msg, e);
fail(msg);
return;
} catch (CertificateExpiredException e) {
String msg = "Participant Certificate '" + keyName + "' has expired";
LOG.error(msg, e);
fail(msg);
return;
}
valid &= signature.checkSignatureValue(pk);
}
if (valid) {
LOG.info("Digital signature validates!!");
return;
} else {
String msg = "Digital Signature INVALID!!";
LOG.info(msg);
fail(msg);
}
} catch (Exception e) {
LOG.error(e.getMessage(), e);
fail("Failed to verify the signature");
} finally {
IOUtils.closeQuietly(in);
}
LOG.error("The message contains an invalid signature");
非常感谢任何帮助。
非常感谢提前。
答案 0 :(得分:0)
我只添加了一些代码来修改for循环签名元素的语句,请参阅DATOS被引用的部分。
for (int i = 0; i < signatures.getLength(); i++) {
Element sigElement = (Element) signatures.item(i);
if(sigElement.tagName.equals("Object"))
{
Element datos = sigElement.getElementsByTagName("DATOS")[0];
Element num_ordenElm = datos.getElementsByTagName("num_orden")[0];
Element cod_alfanumericoElm = datos.getElementsByTagName("cod_alfanumerico")[0];
Element cod_paisElm = datos.getElementsByTagName("cod_pais")[0];
String num_ordenElm = num_ordenElm.textContent;
String cod_alfanumerico cod_alfanumericoElm.textContent;
String cod_paisElm = cod_paisElm.textContent;
}
OutputStream out = new WriterOutputStream();
XMLUtils.ElementToStream(sigElement, out);
LOG.info("Part of the signature to verify\n{}", out);
XMLSignature signature = new XMLSignature(sigElement, "");
String keyName = signature.getKeyInfo().itemKeyName(0).getKeyName();
Certificate certificado = pubring.get(keyName);
if (certificado == null) {
String msg = "I do not have the public certificate signer...";
LOG.error(msg);
fail(msg);
return;
}
答案 1 :(得分:0)
将问题分为两部分,第一个有效签名,第二个读取值需要: 下面显示了用于读取xml的代码:
DocumentBuilder db =DocumentBuilderFactory.newInstance().newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(XMLRecord));
Document doc = db.parse(is);
NodeList nodes = doc.getElementsByTagName("ds:Signature");
String num_orden=null;
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
NodeList nume = element.getElementsByTagName("num_orden");
Element line = (Element) nume.item(0);
num_orden =element.getElementsByTagName("num_orden").item(0).getTextContent();
System.out.println("Nume: " + getCharacterDataFromElement(line));
NodeList codi = element.getElementsByTagName("cod_alfanumerico");
line = (Element) codi.item(0);
System.out.println("cod_alfanumerico: " + getCharacterDataFromElement(line));
NodeList pais = element.getElementsByTagName("cod_pais");
line = (Element) pais.item(0);
System.out.println("Pais: " + getCharacterDataFromElement(line));
}System.out.println(" El numero de cuenta es "+num_orden);
public static String getCharacterDataFromElement(Element e) {
Node child = e.getFirstChild();
if (child instanceof CharacterData) {
CharacterData cd = (CharacterData) child;
return cd.getData();
}
return "";
}