ResourceResolverException при подписании XML

Я отчаянно пытаюсь подписать XML-документ сертификатом X509. Мне нужно подписать несколько элементов в моем документе, поэтому я даю список ссылок на свой SignedInfo.

Проблема, с которой я сталкиваюсь, возникает в самой подписи. Я получаю исключение, в котором говорится, что он не может разрешить элемент с указанным идентификатором.

При поиске решения я наткнулся на этот билет (это ошибка OpenJDK 1.7): https://bugs.openjdk.java.net/browse/JDK-8017171

Я использую Oracle JDK 1.8 и все еще имею проблему.

Код :

XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);

Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(unsignedXml));

List<Reference> refs = new ArrayList<Reference>();
refs.add(fac.newReference(
        "#TS",
        fac.newDigestMethod("http://www.w3.org/2000/09/xmldsig#sha1", null),
        Collections.singletonList(fac.newTransform("http://www.w3.org/2001/10/xml-exc-c14n#",(TransformParameterSpec) null)),
        null, null));

SignedInfo si = fac.newSignedInfo(
        fac.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE,
                (C14NMethodParameterSpec) null),
        fac.newSignatureMethod("http://www.w3.org/2000/09/xmldsig#rsa-sha1", null),
        refs);

FileInputStream input = new FileInputStream(keystoreFile);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(input, password.toCharArray());
Key key = ks.getKey(alias, password.toCharArray());
if (key instanceof PrivateKey) {
    Certificate cert = ks.getCertificate(alias);
    PublicKey publicKey = cert.getPublicKey();
    keyPair = new KeyPair(publicKey, (PrivateKey) key);
}

KeyInfoFactory kif = fac.getKeyInfoFactory();
KeyValue kv = kif.newKeyValue(keyPair.getPublic());
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));

DOMSignContext dsc = new DOMSignContext(keyPair.getPrivate(), doc.getDocumentElement());

XMLSignature signature = fac.newXMLSignature(si, ki);

signature.sign(dsc);

OutputStream out = new FileOutputStream(signedXml);

Исключение :

Exception in thread "main" javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
    at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:431)
    at org.jcp.xml.dsig.internal.dom.DOMReference.digest(DOMReference.java:359)
    at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.digestReference(DOMXMLSignature.java:496)
    at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:379)
    at testsig.testsig.Signature.sign(Signature.java:131)
    at testsig.testsig.App.main(App.java:32)
Caused by: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
    at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:134)
    at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:425)
    ... 5 more
Caused by: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
    at com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment.engineResolveURI(ResolverFragment.java:89)
    at com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver.resolve(ResourceResolver.java:313)
    at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:126)
    ... 6 more
javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
    at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:134)
    at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:425)
    at org.jcp.xml.dsig.internal.dom.DOMReference.digest(DOMReference.java:359)
    at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.digestReference(DOMXMLSignature.java:496)
    at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:379)
    at testsig.testsig.Signature.sign(Signature.java:131)
    at testsig.testsig.App.main(App.java:32)
Caused by: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
    at com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment.engineResolveURI(ResolverFragment.java:89)
    at com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver.resolve(ResourceResolver.java:313)
    at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:126)
    ... 6 more

Моя проблема может быть решена хотя бы одним ответом на следующие вопросы: Есть ли обходной путь? Есть ли другой способ подписи файлов XML?

С уважением

Вы можете проверить это stackoverflow.com/questions/12528667/xml-digital-signature-j‌​ava

Sambit 04.06.2019 20:43

@Sambit Tanks за ваш комментарий. К сожалению, эта помощь, поскольку тема немного отличается.

Nicolas G. Duvivier 04.06.2019 23:24
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
375
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В итоге я нашел больше обходного пути, чем решения. Идея состоит в том, чтобы получить нужный мне элемент с помощью XMLHelper, используя DOM, получив идентификатор Attr от элемента. Затем я добавляю атрибут с помощью setIdAttributeNode() в свой элемент. При таком манипулировании элементом исключение не возникает при добавлении новой ссылки в XMLSignatureFactory.

NodeList list = doc.getElementsByTagName("wsu:Timestamp");
    Node node = list.item(0);
    Element tempEl = XMLHelper.getChildElementsByTagName(doc.getDocumentElement(), "Header").get(0);
    Element securityElement = XMLHelper.getChildElementsByTagName(tempEl, "Security").get(0);

    tempEl = XMLHelper.getChildElementsByTagName(securityElement, "Assertion").get(0);
    Attr attr = (Attr)tempEl.getAttributes().getNamedItem("AssertionID");
    tempEl.setIdAttributeNode(attr, true);
    String ref = "#" + attr.getValue();

    List<Reference> refs = new ArrayList<Reference>();
    refs.add(fac.newReference(
            ref,
            fac.newDigestMethod("http://www.w3.org/2000/09/xmldsig#sha1", null),
            Collections.singletonList(fac.newTransform("http://www.w3.org/2001/10/xml-exc-c14n#",(TransformParameterSpec) null)),
            null,
            null));

На мой взгляд, это не идеальное решение, так как оно слишком сильно связано с DOM XML. Но я полагаю, что это было единственное решение, которое я смог найти, чтобы заставить его работать и обойти известную ошибку в JDK.

Другие вопросы по теме