Проверка подписи не удалась после форматирования XML с SignatureValue.JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Проверка подписи не удалась после форматирования XML с SignatureValue.

Сообщение Anonymous »

Из теста apache santuario xmlsignature
Я провожу тест: добавляю подпись в XML-файл, затем сохраняю ее как файл, после этого считываю ее из этого файла и проверяю подпись.
См. комментарии в коде.
Обычный XML-файл:

Код: Выделить всё




spade


shovel



Dig PLC, 1 First Ave, Dublin 1, Ireland



Dig PLC, 1 First Ave, Dublin 1, Ireland


Foo B Baz
1234 567890 12345




У меня есть несколько вопросов:
  • Проверьте подпись, используя сертификат в XML. Если это работает, XML-файл интерпретируется автоматически, зачем нам еще нужен сертификат, загруженный из хранилища ключей?
  • Я не могу отформатировать сгенерированный XML, содержащий подпись. Если я изменю какую-то часть XML-файла, это приведет к сбою проверки. Как мне отформатировать XML-файл? Или просто оставить его там?
Основной код Java:

Код: Выделить всё

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.Key;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.xml.security.signature.XMLSignature;
import org.junit.Assert;
import org.w3c.dom.Document;
import org.apache.xml.security.utils.XMLUtils;
import org.w3c.dom.Element;

/**
* This tests using the DOM API of Apache Santuario - XML Security for Java for XML Signature.
*/
public class SignatureDOMTest extends org.junit.Assert {

// Sign + Verify an XML Document using the DOM API
@org.junit.Test
public void testSignatureUsingDOMAPI() throws Exception {

// Read in plaintext document
InputStream sourceDocument =
new FileInputStream(new File("plaintext.xml"));
Document document = XMLUtils.read(sourceDocument, true);

// Set up the Key
KeyStore keyStore = KeyStore.getInstance("jks");
keyStore.load(
this.getClass().getClassLoader().getResource("clientstore.jks").openStream(),
"cspass".toCharArray()
);
Key key = keyStore.getKey("myclientkey", "ckpass".toCharArray());
X509Certificate cert = (X509Certificate)keyStore.getCertificate("myclientkey");

// Sign using DOM
List namesToSign = new ArrayList();
namesToSign.add(new QName("urn:example:po", "PaymentInfo"));

SignatureUtils.signUsingDOM(
document, namesToSign, "http://www.w3.org/2000/09/xmldsig#rsa-sha1", key, cert
);
// Verify using DOM, here it use the cert load from Keystore.
SignatureUtils.verifyUsingDOM(document, namesToSign, cert);

// Those code are my test:
// I write the signed xml to a file, then read from the file.
XMLUtils.outputDOM(document, new FileOutputStream(new File("plaintext_signed.xml")));

// read from the signed file.
Document signedDocument = XMLUtils.read(new FileInputStream(new File("plaintext_signed.xml")), true);

// Verify using DOM
List  namesToSign1 = new ArrayList();
namesToSign1.add(new QName("urn:example:po", "PaymentInfo"));

Element sigElement = SignatureUtils.getSignatureElement(signedDocument);
Assert.assertNotNull(sigElement);

SignatureUtils.findElementsToVerify(signedDocument, namesToSign1);

// try to get cert from the node in the xml.
XMLSignature signature = new XMLSignature(sigElement, "");

X509Certificate cert_in_xml = signature.getKeyInfo().getX509Certificate();

// verify the signature by using the cert in the xml.
// If it works, why do we need a cert loaded from the keystore?
SignatureUtils.verifyUsingDOM(signedDocument, namesToSign1, cert_in_xml);
}
}
Включите функции в SignatureUtils.java для обеспечения целостности:

Код: Выделить всё

import org.apache.xml.security.Init;
import org.apache.xml.security.keys.KeyInfo;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.transforms.Transforms;
import org.junit.Assert;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import javax.xml.namespace.QName;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.security.Key;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.UUID;

/**
* Some utility methods for signing/verifying documents
*/
public final class SignatureUtils {

static {
Init.init();
}

private SignatureUtils() {
// complete
}

/**
* Sign the document using the DOM API of Apache Santuario - XML Security for Java.
* It signs a list of QNames that it finds in the Document via XPath.
*/
public static void signUsingDOM(
Document document,
List namesToSign,
String algorithm,
Key signingKey,
X509Certificate signingCert
) throws Exception {
XMLSignature sig =
new XMLSignature(document, "", algorithm, "http://www.w3.org/2001/10/xml-exc-c14n#");
Element root = document.getDocumentElement();
root.appendChild(sig.getElement());

XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
xpath.setNamespaceContext(new DSNamespaceContext());

for (QName nameToSign : namesToSign) {
String expression = "//*[local-name()='" + nameToSign.getLocalPart() + "']";
NodeList elementsToSign =
(NodeList) xpath.evaluate(expression, document, XPathConstants.NODESET);
for (int i = 0; i < elementsToSign.getLength(); i++) {
Element elementToSign = (Element)elementsToSign.item(i);
Assert.assertNotNull(elementToSign);
String id = UUID.randomUUID().toString();
elementToSign.setAttributeNS(null, "Id", id);
elementToSign.setIdAttributeNS(null, "Id", true);

Transforms transforms = new Transforms(document);
transforms.addTransform("http://www.w3.org/2001/10/xml-exc-c14n#");
sig.addDocument("#" + id, transforms, "http://www.w3.org/2000/09/xmldsig#sha1");
}
}

sig.sign(signingKey);

// Find the Signature Element
Element sigElement = getSignatureElement(document);
Assert.assertNotNull(sigElement);

if (signingCert != null) {
sig.addKeyInfo(signingCert);
}
}

/**
* Verify the document using the DOM API of Apache Santuario - XML Security for Java.
* It finds a list of QNames via XPath and uses the DOM API to mark them as having an
* "Id".
*/
public static void verifyUsingDOM(
Document document,
List  namesToSign,
X509Certificate cert
) throws Exception {
// Find the Signature Element
Element sigElement = getSignatureElement(document);
Assert.assertNotNull(sigElement);

findElementsToVerify(document, namesToSign);

XMLSignature signature = new XMLSignature(sigElement, "");

// Check we have a KeyInfo
KeyInfo ki = signature.getKeyInfo();
Assert.assertNotNull(ki);

// Check the Signature value
Assert.assertTrue(signature.checkSignatureValue(cert));
}

public static void findElementsToVerify(Document document, List namesToSign) throws XPathExpressionException {
XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
xpath.setNamespaceContext(new DSNamespaceContext());

for (QName nameToSign : namesToSign) {
String expression = "//*[local-name()='" + nameToSign.getLocalPart() + "']";
Element signedElement =
(Element) xpath.evaluate(expression, document, XPathConstants.NODE);
Assert.assertNotNull(signedElement);
if (signedElement.hasAttributeNS(null, "Id")) {
signedElement.setIdAttributeNS(null, "Id", true);
}
}
}

public static Element getSignatureElement(Document document) throws XPathExpressionException {
XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
xpath.setNamespaceContext(new DSNamespaceContext());

// Find the Signature Element
String expression = "//dsig:Signature[1]";
Element sigElement =
(Element) xpath.evaluate(expression, document, XPathConstants.NODE);
return sigElement;
}
}
Сгенерированный XML-файл с подписью. Он не очень хорошо отформатирован. Я хотел бы его отформатировать, но затем проверка не удалась.

Код: Выделить всё



spade


shovel



Dig PLC, 1 First Ave, Dublin 1, Ireland



Dig PLC, 1 First Ave, Dublin 1, Ireland


Foo B Baz
1234 567890 12345












ANOpAn94IZWzHAFvQSXI6rK3Hsg=



Tlbljw+A69WQ4oClxMgv64RLunmxX0k92UJdqGkQUo7L35wpVgET1EjtZf7TF6ekaxuICDEISPmq
R7vwrRsmf3/u1v9bANaa0rOtO7nuJgxUs9kVndnMnAPWcIm9Njtl7GUEpt6BLMKwAVkbDjOq5Q0S
R3P9d31ppuYdOt7nnbGvgtYDDVIsQRA50rlZqotWI3odfh27HlJMtIys9YJ/0BuQKI4LaNhdymKQ
haRFe6jaAv3v0MVG9Hg53uaJf8vwKL0tYG73ZO2Wh2Tr0j0EPEJY72akyJdNcAHjHiSzZEw1HwRt
Y9Ns2cnbMLpVEYQzW8oO/TO8uf9UYXfUttFyLQ==




MIIDqjCCAxOgAwIBAgIBHzANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJERTEPMA0GA1UECBMG
QmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUxFTATBgNVBAsTDEFwYWNoZSBX
U1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTE1MDkxMDEzMjEyMloXDTI1MDkwNzEzMjEyMlowUzEL
MAkGA1UEBhMCSUUxETAPBgNVBAgTCExlaW5zdGVyMQ8wDQYDVQQHEwZEdWJsaW4xDzANBgNVBAoT
BkFwYWNoZTEPMA0GA1UEAxMGQ2xpZW50MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
jeP2hF/KOv8Pw/++n9bAa0DxKFzyLvlcAciBgv1E01cCyUwn5X0v8nT9gIdjXBi6Y6PvSCs2GqcA
zo82yzIjlcDmocXt/2vBkezwh6Ow2xoXItzXD+I6KlhpH8gl4xXd35N0z+88m4SEclncm//l3sQH
P6CMG9O4H91A+0DXzTkQHzs2PEg13ONMOVbg5P85ceZ+VTBjd3BkqC0mZDB6Ovo6Xt06tVS/S4rF
R0L9mtyxZ+v/Psd8TYAIk3wlz1e1wm+dobp1YkOPgvv08r8ROVnWC0pRZquCPQUou6r50LseRZWE
o9MGN8kt4sYcLCaJbF3fsTvKYi6InWyczv2JSQIDAQABo4H2MIHzMAkGA1UdEwQCMAAwLAYJYIZI
AYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQsRXQjSEq1
PetSTIekkXnMBtntGTCBmAYDVR0jBIGQMIGNgBRWF+/2a4tZ/iMZaN54wOFNZ33QZqFqpGgwZjEL
MAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ0wCwYDVQQKEwRI
b21lMRUwEwYDVQQLEwxBcGFjaGUgV1NTNEoxDzANBgNVBAMTBldlcm5lcoIJAI3hLAppEXfSMA0G
CSqGSIb3DQEBCwUAA4GBAKZXwqAplMzutyC8jIUzFN/DfQOAuZ8ExLBIUxW51KSzxxL+kfydq4HF
otRC7PZ3bYEkXYN7deUYoq6yFO0AAWvagBbxdzRYDPRCwpKe+4jn8VLGtjkEyLSsMiiaNiOuMx8q
WxvV1sA9KioHvZDFVP+0QqSc1ZytEPOKasdViUU9





Обновление 1:
  • Исходный XML-файл хорошо отформатирован. В настоящее время только узел ds:Signature некорректно отформатирован.
  • При обработке подписи с помощью библиотеки Apache Как мы узнаем, что XML-файл уже отформатирован? Поскольку XML-файл теперь представлен как объекты Java.
  • Обычно содержимое между > и

    Подробнее здесь: https://stackoverflow.com/questions/758 ... alue-on-it
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»