19

Java を使用して XML ドキュメントにデジタル署名しようとしています。javax.xml.crypto.dsigパッケージ内のさまざまな実装を使用することがわかったいくつかの参照で動作する実装があります。

ただし、私の現在の実装は、これまで見てきた多くjava.xml.crypto.dsigと似ています。かなり冗長で、javax.xml.transform、 、java.securityパッケージなどから 23 個以上の異なる API クラスを使用する必要があります。工場工場工場の土地に足を踏み入れたような気分で、何が起こっているのかを理解するだけで数時間かかりました。

私の質問は、これを行う簡単な方法はありますか? 公開鍵/秘密鍵ファイルを持ってい<Signature/>て、XML ドキュメントに追加したい場合、次のようなものを呼び出せるライブラリはありますか?

OutputStream signFile(InputStream xmlFile, File privateKey)

...XMLSignatureFactory/CanonicalizationMethod/DOMSignContext の狂気のすべてなしで?

私は暗号化についてはあまり詳しくありません。Java が提供する API は、デジタル署名に慣れようとしている私のような開発者にとってはかなり難しいようです。これらすべてが必要な場合、または現在、より使いやすい API が存在しない場合は、それで問題ありません。回答として喜んで受け入れます。ここで不必要に困難な道を進んでいるかどうかを知りたいだけです。

4

3 に答える 3

11

Apache XML Securityを見てください。パッケージを使用して署名を生成および検証するには、 のサンプルをチェックアウトしますsrc_samples/org/apache/xml/security/samples/signature/

于 2010-01-12T22:20:04.130 に答える
10

Apache Santuario の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);
        }
    }
}
于 2013-04-09T20:12:49.420 に答える
3

XML ファイルに署名するためのすべてのオプションを検討した結果、非標準のアプローチを採用することにしました。基準はあまりにも冗長でした。また、標準との互換性は必要ありませんでした。XML のブロックに署名が必要だっただけです。

おそらく、XML のブロックに「署名」する最も簡単な方法は、分離された署名で GPG を使用することです。

于 2010-01-13T05:05:07.850 に答える