Pergunta

eu estou tentando Assine digitalmente um documento XML usando java. Eu tenho uma implementação trabalhando com algumas referências que encontrei que usam várias implementações no javax.xml.crypto.dsig pacote.

No entanto, minha implementação atual é como muitos do exemplos Eu olhei - é um pouco detalhado e envolve usar nada menos que 23 classes de API diferentes do java.xml.crypto.dsig, javax.xml.transform, e java.security pacotes, entre outros. Parece que eu entrei fábrica de fábrica terra, e levei várias horas apenas para descobrir o que estava acontecendo.

Minha pergunta é, Há uma maneira mais fácil de fazer isso? Se eu tenho arquivos de chave pública/privada e quero adicionar um <Signature/> Para um documento XML, existe uma biblioteca por aí que me permite chamar algo como:

OutputStream signFile(InputStream xmlFile, File privateKey)

... Sem toda a loucura XMLSignatureFactory/CanonicalizationMethod/DomsignContext?

Não sou muito versado em criptografia, e a API fornecida por Java parece bastante assustadora para desenvolvedores como eu tentando me familiarizar com a assinatura digital. Se tudo isso for necessário ou atualmente não há API mais amigável por aí, tudo bem e estou disposto a aceitar isso como uma resposta. Eu só gostaria de saber se estou desnecessariamente tomando o caminho difícil aqui.

Foi útil?

Solução

Eu olhei para todas as opções para assinar arquivos XML e decidi seguir uma abordagem não padrão. Os padrões eram muito detalhados. Além disso, não precisava de compatibilidade com os padrões-eu só precisava de assinaturas em um bloco de XML.

Provavelmente, a maneira mais fácil de "assinar" um bloco de XML é usar o GPG com uma assinatura isolada.

Outras dicas

Olhe para Segurança do Apache XML. Para usar o pacote para gerar e verificar uma assinatura, consulte as amostras em src_samples/org/apache/xml/security/samples/signature/.

Edifício do Apache Santuario CreateSignature Por exemplo, a coisa mais curta que eu poderia inventar é essa. Sem o main() e está acompanhando output(), são 20 linhas

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top