0

我需要用 XAdES-EPES 封装的 xml 文件签名,RSA-SHA256 使用这个哈希: Quzn98x3PMbSHwbUzaj5f5KOpiH0u8bvmwbbbNkO9Es

我签署了 XML,但它无效,因为我不知道如何输入该哈希。这是我的代码:

public class Firma{

private static final String FOLDER = "C:/ECLIPSE/PRUEBAS_Firma/";
private static final String CERT = "SOLDISP_XXXXX.p12";// "Certificado de
                                                        // dispositivo
private static final String PASS = "xxxxxx";

private static final String DOCUMENT = "C:/ECLIPSE/PRUEBAS_Firma/Ejemplo_TicketBAI_B00000034_B2022_0101_SinFirma.xml";

public static void main(String[] args) throws Exception {
    System.setProperty("org.apache.xml.security.ignoreLineBreaks", "true");

    System.out.println(">>>>>>>>> Firmando XML");
    signEpes();
}

private static void signEpes() throws Exception {
    Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(DOCUMENT));
    Element elem = doc.getDocumentElement();
    DOMHelper.useIdAsXmlId(elem);

    KeyingDataProvider kdp = new FileSystemKeyStoreKeyingDataProvider("pkcs12", FOLDER + CERT,
            new FirstCertificateSelector(), new DirectPasswordProvider(PASS), new DirectPasswordProvider(PASS),
            true);
    // politica
    SignaturePolicyInfoProvider policyInfoProvider = new SignaturePolicyInfoProvider() {
        @Override
        public SignaturePolicyBase getSignaturePolicy() {
            return new SignaturePolicyIdentifierProperty(

                    new ObjectIdentifier(
                            "https://www.batuz.eus/fitxategiak/batuz/ticketbai/sinadura_elektronikoaren_zehaztapenak_especificaciones_de_la_firma_electronica_v1_0.pdf",
                            IdentifierType.URI, ""),
                    new ByteArrayInputStream(
                            "https://www.batuz.eus/fitxategiak/batuz/ticketbai/sinadura_elektronikoaren_zehaztapenak_especificaciones_de_la_firma_electronica_v1_0.pdf"
                                    .getBytes())

            );
        }
    };

    SignerEPES signer = (SignerEPES) new XadesEpesSigningProfile(kdp, policyInfoProvider).newSigner();

    new Enveloped(signer).sign(elem);

    outputDocument(doc, "Factura_firmada.xml");
}

protected static void outputDocument(Document doc, String fileName) throws Exception {
    TransformerFactory tf = TransformerFactory.newInstance();
    File outDir = ensureOutputDir();
    FileOutputStream out = new FileOutputStream(new File(outDir, fileName));
    tf.newTransformer().transform(new DOMSource(doc), new StreamResult(out));
    out.close();
}

private static File ensureOutputDir() {
    File dir = new File(toPlatformSpecificFilePath(FOLDER));
    dir.mkdir();
    return dir;
}

}

拜托,谁能帮帮我???提前致谢

4

1 回答 1

0

必须从源策略页面 Stream 计算散列。下面的代码做你想做的,改变你需要适应你的场景的任何东西。您可以在创建时更改代码

SignaturePolicyInfoProvider

SignaturePolicyInfoProvider policyInfoProvider = new SignaturePolicyInfoProvider() {
                @Override
                public SignaturePolicyBase getSignaturePolicy() {
                    try {
                        //PolicyDocumentStream o PolicyDocumentData calculado a partir del contenido de la URL
                        URL url = new URL("https://www.batuz.eus/fitxategiak/batuz/ticketbai/sinadura_elektronikoaren_zehaztapenak_especificaciones_de_la_firma_electronica_v1_0.pdf");
                        if ("https".equals(url.getProtocol())) {
                            HttpsURLConnection.setDefaultSSLSocketFactory(getTrustAllClientSecureContext("TLS").getSocketFactory());
                            HttpsURLConnection.setDefaultHostnameVerifier(new TrustAllHostnameVerifier());
                        }
                        URLConnection urlConn = url.openConnection();
                        urlConn.setConnectTimeout(5000);
                        urlConn.setReadTimeout(60000);
                        //Dummy "User-Agent"
                        urlConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0");
                        return new SignaturePolicyIdentifierProperty(new ObjectIdentifier("https://www.batuz.eus/fitxategiak/batuz/ticketbai/sinadura_elektronikoaren_zehaztapenak_especificaciones_de_la_firma_electronica_v1_0.pdf", IdentifierType.URI), new BufferedInputStream(urlConn.getInputStream()))
                                .withLocationUrl("https://www.batuz.eus/fitxategiak/batuz/ticketbai/sinadura_elektronikoaren_zehaztapenak_especificaciones_de_la_firma_electronica_v1_0.pdf");
                    } catch (Exception ex) {
                        System.out.println("ERROR: SignaturePolicyInfoProvider...");
                        ex.printStackTrace();
                    }
                    return null;
                }
            };

此外,我还为您提供了用于 https 通信的辅助代码。

public SSLContext getTrustAllClientSecureContext(String secureSocketProtocol) {
        SSLContext context = null;
        if (secureSocketProtocol == null) {
            secureSocketProtocol = "TLS";
        }
        try {
            context = SSLContext.getInstance(secureSocketProtocol);
            context.init(null, new TrustManager[]{new TrustAllTrustManager()}, null);
        } catch (Exception e) {
            System.out.println("ERROR: " + e.getMessage());
        }
        return context;
    }

public class TrustAllTrustManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {

    }

    @Override
    public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {

    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
}

public class TrustAllHostnameVerifier implements HostnameVerifier {

    @Override
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }

}

当然,在生产中必须避免连接到 URL 的“允许所有证书”操作,而是最好将相应的证书添加到您的证书存储中。

于 2021-11-05T10:16:30.613 回答