2010-01-12 8 views
17

मैं जावा का उपयोग कर digitally sign an XML document करने का प्रयास कर रहा हूं। मुझे कुछ संदर्भों के साथ काम करने का कार्यान्वयन मिला है जो मैंने पाया है कि javax.xml.crypto.dsig पैकेज में विभिन्न कार्यान्वयन का उपयोग करें।जावा में किसी XML दस्तावेज़ पर हस्ताक्षर करने का कोई आसान तरीका है?

हालांकि, मेरे वर्तमान कार्यान्वयन examples मैं देखा है की many तरह है - यह बल्कि वर्बोज़ है और java.xml.crypto.dsig, javax.xml.transform, और java.security संकुल से कम से कम 23 विभिन्न एपीआई वर्गों का उपयोग करना, दूसरों के बीच में शामिल है। ऐसा लगता है कि मैंने factory factory factory भूमि दर्ज की है, और यह पता लगाने के लिए कि मुझे क्या चल रहा था, मुझे कई घंटे लग गए।

मेरा प्रश्न है, क्या ऐसा करने का कोई आसान तरीका है? मैं सार्वजनिक/निजी कुंजी फ़ाइलें मिल गया है और मैं एक XML दस्तावेज़ के लिए एक <Signature/> जोड़ना चाहते हैं, वहाँ एक पुस्तकालय सिर्फ मेरे जैसे कुछ फोन की सुविधा देता है:

OutputStream signFile(InputStream xmlFile, File privateKey) 

... के सभी बिना XMLSignatureFactory/CanonicalizationMethod/DOMSignContext पागलपन?

मैं क्रिप्टोग्राफ़ी में बहुत अच्छी तरह से ज्ञात नहीं हूं, और जावा-प्रदत्त एपीआई डिजिटल डेवलपमेंट से परिचित होने की कोशिश कर रहे डेवलपर्स के लिए मुश्किल है। यदि यह सब आवश्यक है या वर्तमान में कोई मित्रवत एपीआई नहीं है, तो यह ठीक है और मैं इसे उत्तर के रूप में स्वीकार करने के लिए तैयार हूं। मैं सिर्फ यह जानना चाहूंगा कि मैं अनावश्यक रूप से हार्ड रोड ले रहा हूं या नहीं।

+0

एक वैकल्पिक समाधान के रूप में, मैं एक एक लाइनर प्रणाली कॉल करेंगे और http://www.aleksey.com/xmlsec/ का उपयोग हस्ताक्षर करने के लिए कर रहा था है एक्सएमएल। मैं इसे उत्तर के रूप में पोस्ट नहीं कर रहा हूं क्योंकि यह प्रश्न की सीमाओं के भीतर नहीं है (यानी "जावा में")। –

उत्तर

3

मैंने एक्सएमएल फाइलों पर हस्ताक्षर करने के लिए सभी विकल्पों को देखा और एक गैर मानक दृष्टिकोण के साथ जाने का फैसला किया। मानक भी सभी verbose थे। इसके अलावा, मुझे मानकों के साथ संगतता की आवश्यकता नहीं थी --- मुझे एक्सएमएल के ब्लॉक पर हस्ताक्षर की आवश्यकता थी।

शायद एक्सएमएल के ब्लॉक को "साइन" करने का सबसे आसान तरीका एक अलग हस्ताक्षर के साथ जीपीजी का उपयोग करना है।

+0

अच्छा विचार, शायद अब तक का सबसे सरल प्रदान किया गया है। यह javax.xml.crypto या अपाचे के सैंटुआरियो की सभी कॉन्फ़िगरेशन की पेशकश नहीं करता है, लेकिन यह वास्तव में उन अन्य लोगों को इतना जटिल बनाता है। –

+0

धन्यवाद। एक प्रणाली जो ऐसा करती है, यह दृष्टिकोण एक्सएमएल ब्लॉक लेता है, आरएसए पब्लिक की और ओपनएसएसएल का उपयोग करके हस्ताक्षर की गणना करता है, और उसके बाद पाठ फ़ाइल में एक्सएमएल ब्लॉक के अंत में हस्ताक्षर को एम्बेड करता है। आप मेरे afsign.cpp प्रोग्राम में कोड पा सकते हैं जो AFFLIB का हिस्सा है, जिसे http://afflib.org/ – vy32

+0

से डाउनलोड किया जा सकता है क्योंकि यह एक आसान समाधान है क्योंकि इसे स्वीकार करना। पास्कल का समाधान भी उचित है, हालांकि इसे अभी भी उचित मात्रा में कोड की आवश्यकता है। –

10

Apache XML Security पर देखें। हस्ताक्षर उत्पन्न करने और सत्यापित करने के लिए पैकेज का उपयोग करने के लिए, src_samples/org/apache/xml/security/samples/signature/ में नमूने चेकआउट करें।

+0

धन्यवाद, पास्कल। वास्तव में उन उदाहरणों को काम करने के लिए कुछ परेशानी हो रही थी, अर्थात् "java.io.IOException: अवैध कीस्टोर प्रारूप", हालांकि मैं अपना खुद का keystore.pks बनाने और इसे काम करने में सक्षम था। – Kirby

+0

लिंक अब मान्य नहीं है –

8

अपाचे सैंटुआरियो 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); 
     } 
    } 
} 
+0

आपके प्रस्ताव का प्रयास कर रहा था, हालांकि मैं Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS से Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS तक C14N अलगो को बदलने में असमर्थ हूं। यहां तक ​​कि जब मैं कोड में इसे बदलता हूं तो आउटपुट एक्सएमएल हस्ताक्षर अभी भी CanonicalizationMethod को के रूप में दिखाता है। क्या कोई विचार है कि यहां क्या गलत हो सकता है? – mithrandir

संबंधित मुद्दे

 संबंधित मुद्दे