2011-04-07 18 views
6

मैं प्रोग्रामेटिक रूप से सत्यापित करने की कोशिश कर रहा हूं कि एक जार फ़ाइल स्पष्ट रूप से छेड़छाड़ नहीं की गई है। मेरे पास 2 उपयोग के मामले हैं जिन्हें मैं रोकना चाहता हूं। 1) मौजूदा कक्षाओं के संशोधनों 2) जारजार हस्ताक्षर सत्यापित करना

में नए वर्गों के जोड़ों ने मैंने jarsigner का उपयोग कर जार पर हस्ताक्षर किए। जब मैं उपरोक्त मामलों में से किसी एक को jarsigner के साथ सत्यापित करता हूं तो यह काम करता है जैसे मैं उम्मीद करता हूं।

जब मैं How to verify a jar signed with jarsigner programmatically या How to verify signature on self signed jar? तथापि में प्रोग्राम के रूप में नमूने का उपयोग करने की कोशिश, मैं उस बात के लिए कोई भी SecurityExceptions ... या किसी भी अपवाद नहीं मिलता है।

यकीन नहीं है कि मैं क्या कर रहा हूं क्योंकि उन स्निपेट अन्य लोगों के लिए काम करना प्रतीत होता है। कोई विचार? यह जेडीके 1.6 बीटीडब्ल्यू है।

संपादित करें: के रूप में नीचे का अनुरोध किया, कोड का एक नमूना ... अपने स्वयं के संशोधित जार :)

JarFile myJar; 

    try 
    { 
     //Insert the full path to the jar here  
     String libPath = "" 
     stature = new JarFile(libPath,true); 

     //Don't really need this right now but was using it to inspect the SHA1 hashes 

     InputStream is = myJar.getInputStream(myJar.getEntry("META-INF/MANIFEST.MF")); 
     Manifest man = myJar.getManifest();    
     is.close(); 

     verifyJar(myJar); 

    } 
    catch (IOException ioe) 
    { 
     throw new Exception("Cannot load jar file", ioe); 
    } 


private void verifyJar(JarFile jar) throws Exception 
{ 
    Enumeration<java.util.jar.JarEntry> entries = jar.entries(); 
    while (entries.hasMoreElements()) 
    { 
     java.util.jar.JarEntry entry = entries.nextElement(); 

     try 
     { 
      jar.getInputStream(entry); 

      //Also tried actually creating a variable from the stream in case it was discarding it before verification 
      //InputStream is = jar.getInputStream(entry); 
      //is.close(); 
     } 
      catch (SecurityException se) 
      { 
       /* Incorrect signature */      
       throw new Exception("Signature verification failed", se); 
      } 
      catch (IOException ioe) 
      { 
       throw new Exception("Cannot load jar file entry", ioe); 
      } 
    } 
} 

+0

आपने परीक्षण के तहत जेएआर के साथ कैसे छेड़छाड़ की? – trashgod

+0

मैंने इसे 7zip में खोला। मैंने इसमें कुछ क्लास फाइलों के साथ एक नई पैकेज निर्देशिका जोड़ा और पुन: संकलित संस्करणों के साथ मौजूदा क्लास फाइलों में से कुछ को संशोधित किया। – Amasuriel

+0

यदि 'jarsigner' बदलते JAR को अस्वीकार करता है, लेकिन आपका कोड इसे स्वीकार करता है, तो एक [sscce] (http://sscce.org/) समस्या को हल करने में मदद कर सकता है। – trashgod

उत्तर

1

मुझे पता चला कि यह मेरे साथ क्यों हो रहा था ... यह एक बेवकूफ गलती थी।

मेरे पास मेरे छेड़छाड़ किए गए जार थे, लेकिन मेरे पास भी सभी कक्षाएं संकलित थीं क्योंकि यह मेरा देव env था। तो क्लासलोडर ने जार वर्गों पर संकलित कक्षाएं उठाईं। संकलित कक्षाओं के लिए कोई अभिव्यक्ति नहीं है, इसलिए कोई सुरक्षा त्रुटियां उत्पन्न नहीं हुईं।

एक बार जब मैंने अपनी संकलित कक्षाओं को हटा दिया तो मुझे अपेक्षित सुरक्षा अपवाद मिल गए।

7

आपूर्ति नीचे दिए गए उदाहरण का उपयोग करना, मैं अपेक्षित परिणाम एक ठीक प्रकार से हस्ताक्षरित जार के लिए प्राप्त (true) और एक परिवर्तित JAR (false)। परीक्षण के प्रभाव को ट्रिगर करने का एक आसान तरीका META-INF/MANIFEST.MF में सूचीबद्ध एक पाचन को बदलना है।

ध्यान दें कि यह दृष्टिकोण मेनिफेस्ट में सूचीबद्ध प्रविष्टियों को अनदेखा करता है। jarsigner -verify रिपोर्ट का उपयोग करके, "इस जार में हस्ताक्षरित प्रविष्टियां हैं जो अखंडता-जांच नहीं हुई हैं।" पूरी तरह से स्ट्रीम पढ़ने के बाद, entry.getCodeSigners() का उपयोग यह निर्धारित करने के लिए किया जा सकता है कि किसी प्रविष्टि में कोई हस्ताक्षरकर्ता है या नहीं।

import java.io.IOException; 
import java.io.InputStream; 
import java.util.Enumeration; 
import java.util.jar.JarEntry; 
import java.util.jar.JarFile; 

/** @see http://stackoverflow.com/questions/5587656 */ 
public class Verify { 

    public static void main(String[] args) throws IOException { 
     System.out.println(verify(new JarFile(args[0]))); 
    } 

    private static boolean verify(JarFile jar) throws IOException { 
     Enumeration<JarEntry> entries = jar.entries(); 
     while (entries.hasMoreElements()) { 
      JarEntry entry = entries.nextElement(); 
      try { 
       byte[] buffer = new byte[8192]; 
       InputStream is = jar.getInputStream(entry); 
       while ((is.read(buffer, 0, buffer.length)) != -1) { 
        // We just read. This will throw a SecurityException 
        // if a signature/digest check fails. 
       } 
      } catch (SecurityException se) { 
       return false; 
      } 
     } 
     return true; 
    } 
} 

नोट: JDK 8 के लिए, केवल इनपुट स्ट्रीम प्राप्त करने के लिए अपने लिए पर्याप्त नहीं। jarsigner में, स्ट्रीम भी पढ़ी जानी चाहिए। उपरोक्त कोड में, इनपुट स्ट्रीम प्राप्त करने के बाद jar signersource से अनुकूलित एक लूप जोड़ा गया है।

+0

हम्म। आपका नमूना मेरे लिए लगभग समान है, फिर भी आपको सुरक्षा अपवाद मिलते हैं और मैं नहीं करता हूं। आप किस सटीक जेडीके का उपयोग कर रहे हैं? – Amasuriel

+0

संस्करण अप्रासंगिक है। 'सुरक्षा अपवाद' केवल तभी फेंक दिया जाता है जब कोई प्रविष्टि गलत तरीके से हस्ताक्षरित हो। आप इसे 'मेटा-आईएनएफ/ एसएफ' के साथ छेड़छाड़ करके भी ट्रिगर कर सकते हैं। – trashgod

+0

मैं इसे उत्तर के रूप में चिह्नित करने जा रहा हूं क्योंकि स्पष्ट रूप से यह ज्यादातर लोगों के लिए काम करता है। जब मुझे मौका मिलता है तो मैं इसे एक सरल उदाहरण के साथ आज़माने जा रहा हूं ... अगर मुझे पता चलता है कि यह मेरे लिए क्यों काम नहीं करता है लेकिन इसे ठीक करने का तरीका नहीं है तो मुझे लगता है कि मैं एक नया प्रश्न खोलूंगा। – Amasuriel

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