проверка xades4j без KeyInfo - PullRequest
       56

проверка xades4j без KeyInfo

0 голосов
/ 24 сентября 2019

Наша компания использует Etokens для связи с сервером через https.Как проверить файл XML с конвертами, который поставляется без сертификата для подписи в KeyInfo?

<?xml version="1.0" encoding="UTF-8"?>
<EDoc><NextMsg ID="Edoc">2019-09-23T16:20:53</NextMsg><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="xmldsig-5d0f41cd-6e98-488d-9415-28b6329b34d1">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></ds:SignatureMethod>
<ds:Reference Id="xmldsig-5d0f41cd-6e98-488d-9415-28b6329b34d1-ref0" URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></ds:DigestMethod>
<ds:DigestValue>IUdYs162QE1GdUEKUxqppoFmNvrYMLMBGnduWy6v3rc=</ds:DigestValue>
</ds:Reference>
<ds:Reference Type="http://uri.etsi.org/01903#SignedProperties" URI="#xmldsig-5d0f41cd-6e98-488d-9415-28b6329b34d1-signedprops">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></ds:DigestMethod>
<ds:DigestValue>Uw2b3fkLSJPm+yDeYwXQhJHZhWP+vUNBEeS55LcII00=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue Id="xmldsig-5d0f41cd-6e98-488d-9415-28b6329b34d1-sigvalue">
eHOQcdUYRRhQa3DV+P5lWnXR32KXpO08n4QI/SIXvJxbjvz3roGNas53E/1hCui8MG3TkZulx4Fw&#xD;
W3N9qJ3FXciasReaqofrexHtbntyr6O/tzQh2akcJzo3TPH+j4PxozjFUxCxcaJRSqCE0hWdBtuI&#xD;
S8rn+EKpes7ohgtlsVg=
</ds:SignatureValue>
<ds:Object><xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Target="#xmldsig-5d0f41cd-6e98-488d-9415-28b6329b34d1"><xades:SignedProperties xmlns:ns3="http://uri.etsi.org/01903/v1.4.1#" Id="xmldsig-5d0f41cd-6e98-488d-9415-28b6329b34d1-signedprops"><xades:SignedSignatureProperties><xades:SigningTime>2019-09-23T16:20:53+03:00</xades:SigningTime><xades:SigningCertificate><xades:Cert><xades:CertDigest><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod><ds:DigestValue>woG3fsImDUeqxznickzLkpeY9R4=</ds:DigestValue></xades:CertDigest><xades:IssuerSerial><ds:X509IssuerName>cn=LB-LITAS-CA,ou=MSD,o=Lietuvos bankas,l=Vilnius,c=LT</ds:X509IssuerName><ds:X509SerialNumber>105704079740755226136574</ds:X509SerialNumber></xades:IssuerSerial></xades:Cert></xades:SigningCertificate></xades:SignedSignatureProperties></xades:SignedProperties></xades:QualifyingProperties></ds:Object>
</ds:Signature></EDoc>

По умолчанию verify функция ищет KeyInfo

 public static void verifyBes(KeyStore ksaa, String path)
      throws javax.xml.parsers.ParserConfigurationException, org.xml.sax.SAXException,
          java.security.NoSuchAlgorithmException, xades4j.utils.XadesProfileResolutionException,
          xades4j.XAdES4jException, java.io.IOException, java.security.NoSuchProviderException,
          java.security.cert.CertificateException, java.security.cert.CRLException,
          java.security.cert.CertStoreException, java.security.KeyStoreException {

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

    Document doc = dbf.newDocumentBuilder().parse(new File(path));
    Element root = doc.getDocumentElement();

    Element idChild = (Element) root.getFirstChild();
    DOMHelper.useIdAsXmlId(idChild);

    String filename =
        System.getProperty("java.home") + "/lib/security/cacerts".replace('/', File.separatorChar);
    FileInputStream is = new FileInputStream(filename);
    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    String password = "changeit";
    ks.load(is, password.toCharArray());

    X509Certificate validate_cert = null;

    FileSystemDirectoryCertStore fsCertStore = new FileSystemDirectoryCertStore("../certStore");
    Collection<? extends Certificate> allCerts = fsCertStore.getStore().getCertificates(null);
    // search for specific certificate to test agains
    for (Certificate c : allCerts) {
      X509Certificate pool_cert = (X509Certificate) c;
      System.out.println(pool_cert.getSubjectDN().getName());
      if (-1 != pool_cert.getSubjectDN().getName().indexOf("TEST CERTIFICATE"))
        validate_cert = pool_cert;
    }

    CertificateValidationProvider validationProviderMySigs =
        new PKIXCertificateValidationProvider(ks, false, fsCertStore.getStore());
    XadesVerificationProfile instance = new XadesVerificationProfile(validationProviderMySigs);
    XadesVerifier verifier = instance.newVerifier();
    Element sig = (Element) doc.getElementsByTagName("ds:Signature").item(0);
    XAdESVerificationResult r = verifier.verify(sig, null);
  }

xades4j.verification.InvalidKeyInfoDataException: НетX509Data для идентификации конечного сертификата в xades4j.verification.SignatureUtils.processKeyInfo (SignatureUtils.java:79) в xades4j.verification.XadesVerifierImpl.verify (XadesVerifierImpl.java:184) в com.mycompany.app.App.vejj: 993) в com.mycompany.app.App.main (App.java:460)

1 Ответ

1 голос
/ 26 сентября 2019

TL, DR;

В настоящее время нет способа сделать это.

Причины

  • xadesj4j основаны на стандарте XAdES 1.4.1.Согласно этому стандарту свойство SigningCertificate требует, чтобы сертификат подписи был идентифицирован в свойстве, но не указывает, какой элемент соответствует сертификату подписи, если в свойстве имеется более одной ссылки на сертификат.xades4j пытается использовать данные в KeyInfo, чтобы выяснить это.
  • xades4j начинается с выполнения базовой проверки XML-DSIG / криптографии (для которой требуется подписывающий сертификат) и только после проверки каждого соответствующего свойства.Это означает, что свойство SigningCertificate не учитывается при попытке идентифицировать сертификат.Возможно, это может отличаться, особенно если в свойстве есть только одна ссылка на сертификат (проблема, упомянутая в предыдущем пункте, не будет применима).

Идеи

  1. Целью идентификации сертификата подписи является предоставление X509CertSelector до CertificateValidationProvider.validate().Без других изменений, если «пустой» селектор сертификатов был предоставлен, когда KeyInfo отсутствует, это означало бы, что CertificateValidationProvider нужно будет знать, как идентифицировать сертификат подписи.Встроенный PKIXCertificateValidationProvider потерпит неудачу, что не круто.Однако, поскольку этот сценарий в настоящее время не работает, это означает, что изменение не нарушит существующие приложения.
  2. Когда нет KeyInfo, попробуйте поискать свойство SigningCertificate и если оно содержит одну ссылку на сертификат, используйте там издателя / серийный номер для настройки X509CertSelector.Учитывая текущую архитектуру, у этого есть обратная сторона доступа к данным свойств до проверки подписи ядра.

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

...