Pregunta

Estoy intentando firmar digitalmente un documento XML utilizando Java. Tengo una aplicación que trabaja con algunas referencias que he encontrado que utilizan diversas implementaciones en el paquete javax.xml.crypto.dsig .

Sin embargo, mi implementación actual es como muchos de la ejemplos he mirado - que es bastante detallado y no implica el uso de menos de 23 clases de API diferentes de los paquetes java.xml.crypto.dsig, javax.xml.transform y java.security, entre otros. Se siente como que he entrado en la tierra fábrica fábrica fábrica , y se tomó me varias horas sólo para averiguar lo que estaba pasando.

Mi pregunta es, ¿hay una manera más fácil de hacer esto? Si tengo los archivos de clave pública / privada y quiero añadir un <Signature/> a un documento XML, hay una biblioteca a cabo hay que simplemente me permite llamar algo como:

OutputStream signFile(InputStream xmlFile, File privateKey)

... sin todo el XMLSignatureFactory / CanonicalizationMethod / DOMSignContext locura?

No soy muy versado en la criptografía, y la API proporcionada en Java parece bastante desalentador para los desarrolladores como yo tratando de familiarizarse con la firma digital. Si todo esto es necesario o no hay actualmente ninguna API más amigable hacia fuera allí, que está muy bien y estoy dispuesto a aceptar eso como una respuesta. Sólo me gustaría saber si estoy tomando el camino innecesariamente difícil aquí.

¿Fue útil?

Solución

Miré a todas las opciones para la firma de los archivos XML y decidí ir con un enfoque no estándar. Las normas eran demasiado prolijo. Además, no tenía necesidad de compatibilidad con los estándares --- I sólo firmas necesarias en un bloque de XML.

Probablemente la forma más fácil de "firmar" un bloque de XML es utilizar GPG con una firma separada.

Otros consejos

Tener vistazo a Apache Seguridad XML . Para utilizar el paquete para generar y verificar una firma, pago y envío las muestras en src_samples/org/apache/xml/security/samples/signature/ .

Edificio del ejemplo CreateSignature Apache Santuario, la cosa más corto que podría llegar a es la siguiente. Sin la main() y su output() acompaña, que es 20 líneas

import java.io.*;
import java.security.Key;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.io.IOUtils;
import org.apache.xml.security.Init;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.transforms.Transforms;
import org.apache.xml.security.utils.Constants;
import org.apache.xml.security.utils.ElementProxy;
import org.w3c.dom.Document;

public class CreateSignature {

    private static final String PRIVATE_KEY_ALIAS = "test-alias";
    private static final String PRIVATE_KEY_PASS = "test";
    private static final String KEY_STORE_PASS = "test";
    private static final String KEY_STORE_TYPE = "JKS";

    public static void main(String... unused) throws Exception {
        final InputStream fileInputStream = new FileInputStream("test.xml");
        try {
            output(signFile(fileInputStream, new File("keystore.jks")), "signed-test.xml");
        }
        finally {
            IOUtils.closeQuietly(fileInputStream);
        }
    }

    public static ByteArrayOutputStream signFile(InputStream xmlFile, File privateKeyFile) throws Exception {
        final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlFile);
        Init.init();
        ElementProxy.setDefaultPrefix(Constants.SignatureSpecNS, "");
        final KeyStore keyStore = loadKeyStore(privateKeyFile);
        final XMLSignature sig = new XMLSignature(doc, null, XMLSignature.ALGO_ID_SIGNATURE_RSA);
        final Transforms transforms = new Transforms(doc);
        transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
        sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1);
        final Key privateKey = keyStore.getKey(PRIVATE_KEY_ALIAS, PRIVATE_KEY_PASS.toCharArray());
        final X509Certificate cert = (X509Certificate)keyStore.getCertificate(PRIVATE_KEY_ALIAS);
        sig.addKeyInfo(cert);
        sig.addKeyInfo(cert.getPublicKey());
        sig.sign(privateKey);
        doc.getDocumentElement().appendChild(sig.getElement());
        final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        outputStream.write(Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS).canonicalizeSubtree(doc));
        return outputStream;
    }

    private static KeyStore loadKeyStore(File privateKeyFile) throws Exception {
        final InputStream fileInputStream = new FileInputStream(privateKeyFile);
        try {
            final KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
            keyStore.load(fileInputStream, KEY_STORE_PASS.toCharArray());
            return keyStore;
        }
        finally {
            IOUtils.closeQuietly(fileInputStream);
        }
    }

    private static void output(ByteArrayOutputStream signedOutputStream, String fileName) throws IOException {
        final OutputStream fileOutputStream = new FileOutputStream(fileName);
        try {
            fileOutputStream.write(signedOutputStream.toByteArray());
            fileOutputStream.flush();
        }
        finally {
            IOUtils.closeQuietly(fileOutputStream);
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top