Is there an easier way to sign an XML document in Java?

前端 未结 3 1186
囚心锁ツ
囚心锁ツ 2021-02-05 08:09

I\'m trying to digitally sign an XML document using Java. I\'ve got an implementation working with some references I\'ve found that use various implementations in the javax.xml.

相关标签:
3条回答
  • 2021-02-05 09:01

    I looked at all of the options for signing XML files and decided to go with a non-standard approach. The standards were all way too verbose. Also, I didn't need compatibility with the standards---I just needed signatures on a block of XML.

    Probably the easiest way to "sign" a block of XML is to use GPG with a detached signature.

    0 讨论(0)
  • 2021-02-05 09:10

    Have look at Apache XML Security. To use the package to generate and verify a signature, checkout the samples in src_samples/org/apache/xml/security/samples/signature/.

    0 讨论(0)
  • 2021-02-05 09:11

    Building from the Apache Santuario CreateSignature example, the shortest thing I could come up with is this. Without the main() and its accompanying output(), it's 20 lines

    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);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题