Y at-il un moyen plus facile de signer un document XML en Java?
-
20-09-2019 - |
Question
Je suis en train de signer numériquement un document XML utilisant Java. J'ai une mise en œuvre de travailler avec quelques références que j'ai trouvé qui utilisent différentes implémentations dans le package javax.xml.crypto.dsig
.
Cependant, mon implémentation actuelle est comme du Exemples J'ai regardé - il est plutôt bavard et implique l'utilisation de pas moins de 23 différentes classes de l'API des Ma question est, est-il un moyen plus facile de le faire? Si j'ai des fichiers de clé publique / privée et je veux ajouter un ... sans tous les XMLSignatureFactory / CanonicalizationMethod / DOMSignContext folie? Je ne suis pas très bien versé dans la cryptographie, et l'API Java fourni semble assez intimidant pour les développeurs comme moi-même en essayant de se familiariser avec la signature numérique. Si tout cela est nécessaire ou il n'y a actuellement pas d'API conviviale là-bas, c'est bien et je suis prêt à accepter cela comme une réponse. Je voudrais savoir si je prends la route inutilement difficile ici. java.xml.crypto.dsig
, javax.xml.transform
et forfaits java.security
, entre autres. Il se sent comme je suis entré dans la terre de l'usine d'usine d'usine de
<Signature/>
à un document XML, est-il une bibliothèque sur là que me permet d'appeler quelque chose comme: OutputStream signFile(InputStream xmlFile, File privateKey)
La solution
Je regardais toutes les options pour la signature des fichiers XML et décidé d'aller avec une approche non standard. Les normes étaient trop bavard. De plus, je ne l'ai pas besoin d'une compatibilité avec les normes --- Je seulement les signatures nécessaires sur un bloc de XML.
Probablement la meilleure façon de « signer » un bloc de XML est d'utiliser GPG avec une signature détachée.
Autres conseils
Apache XML de sécurité. Pour utiliser le package pour générer et vérifier une signature, la caisse dans les échantillons src_samples/org/apache/xml/security/samples/signature/
.
Bâtiment de l'exemple Apache Santuario de CreateSignature
, la chose la plus courte je pourrais venir avec c'est. Sans le main()
et son output()
qui l'accompagne, il est 20 lignes
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);
}
}
}