代码之家  ›  专栏  ›  技术社区  ›  Rob Hruska MegalomanINA

在Java中有一种更容易的方式签署XML文档吗?

  •  18
  • Rob Hruska MegalomanINA  · 技术社区  · 15 年前

    我在努力 digitally sign an XML document 使用Java。我有一个实现,它使用一些引用,我发现这些引用在 javax.xml.crypto.dsig 包裹。

    但是,我当前的实现是 many examples 我已经看过了-它相当冗长,涉及使用不少于23个不同的API类 java.xml.crypto.dsig , javax.xml.transform java.security 包裹等。感觉好像我进入了 factory factory factory 着陆,我花了几个小时才弄清楚到底发生了什么。

    我的问题是, 有更简单的方法吗? 如果我有公钥/私钥文件,我想添加一个 <Signature/> 对于XML文档,是否有一个库可以让我调用如下内容:

    OutputStream signFile(InputStream xmlFile, File privateKey)
    

    …没有所有的xmlsignaturefactory/canonicalizationmethod/domsigncontext疯狂?

    我不太精通密码学,而Java提供的API对于我这样的开发者来说,似乎很难理解数字签名。如果所有这些都是必需的,或者目前还没有更友好的API,那就好了,我愿意接受这一点作为答案。我只想知道我是不是在不必要地走这条艰难的路。

    3 回复  |  直到 12 年前
        1
  •  3
  •   vy32    15 年前

    我研究了签署XML文件的所有选项,并决定采用非标准方法。标准太冗长了。另外,我不需要与标准兼容——我只需要在一块XML上签名。

    对XML块进行“签名”最简单的方法可能是使用带有分离签名的GPG。

        2
  •  10
  •   Rob Hruska MegalomanINA    14 年前

    看看 Apache XML Security . 要使用包生成和验证签名,请签出 src_samples/org/apache/xml/security/samples/signature/ .

        3
  •  10
  •   Kirby    12 年前

    从阿帕奇-桑塔里奥建筑 CreateSignature 我能想到的最短的事情就是这个。没有 main() 及其伴随物 output() 是20行

    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);
            }
        }
    }