سؤال

أحاول أن قم بالتوقيع رقميًا على مستند XML باستخدام جافا.لدي تطبيق يعمل مع بعض المراجع التي وجدتها تستخدم تطبيقات مختلفة في javax.xml.crypto.dsig طَرد.

ومع ذلك، فإن تطبيقي الحالي يشبه كثير التابع أمثلة لقد ألقيت نظرة عليه - إنه مطول إلى حد ما ويتضمن استخدام ما لا يقل عن 23 فئة مختلفة من واجهة برمجة التطبيقات (API) من java.xml.crypto.dsig, javax.xml.transform, ، و java.security الحزم، من بين أمور أخرى.يبدو الأمر وكأنني دخلت مصنع مصنع مصنع الأرض، واستغرق الأمر مني عدة ساعات فقط لمعرفة ما يحدث.

سؤالي هو، هل هناك طريقة أسهل لعمل هذا الشيء؟ إذا كان لدي ملفات مفاتيح عامة/خاصة وأريد إضافة ملف <Signature/> إلى مستند XML، هل توجد مكتبة تتيح لي الاتصال بشيء مثل:

OutputStream signFile(InputStream xmlFile, File privateKey)

...بدون كل جنون XMLSignatureFactory/CanonicalizationMethod/DOMSignContext؟

أنا لست على دراية جيدة بالتشفير، ويبدو أن واجهة برمجة التطبيقات (API) التي توفرها Java صعبة للغاية بالنسبة للمطورين مثلي الذين يحاولون التعرف على التوقيع الرقمي.إذا كان كل هذا ضروريًا أو لا توجد حاليًا واجهة برمجة تطبيقات أكثر سهولة، فلا بأس وأنا على استعداد لقبول ذلك كإجابة.أود فقط أن أعرف ما إذا كنت أسلك الطريق الصعب هنا دون داعٍ.

هل كانت مفيدة؟

المحلول

لقد نظرت في جميع الخيارات لتوقيع ملفات XML وقررت اتباع نهج غير قياسي.وكانت المعايير كلها مطولة للغاية.وأيضًا، لم أكن بحاجة إلى التوافق مع المعايير --- كنت بحاجة فقط إلى التوقيعات على كتلة من XML.

ربما تكون أسهل طريقة "لتوقيع" كتلة من XML هي استخدام GPG بتوقيع منفصل.

نصائح أخرى

ألقي نظرة على أباتشي XML الأمن.لاستخدام الحزمة لإنشاء التوقيع والتحقق منه، قم بإلقاء نظرة على العينات الموجودة src_samples/org/apache/xml/security/samples/signature/.

بناء من أباتشي سانتواريو 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);
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top