Проверка Подписи Jar

Я пытаюсь программно проверить, что файл jar не был явно изменен. У меня есть 2 варианта использования, которые я хочу предотвратить. 1) изменения существующих классов 2) добавление новых классов в jar

Я подписал банку с помощью jarsigner. Когда я проверяю любой из вышеперечисленных случаев с jarsigner, он работает так, как я ожидал.

когда я пытаюсь сделать это программно, используя образцы в Как проверить банку, подписанную с jarsigner программно или Как проверить подпись на подпись собственной банке? тем не менее, я не получаю никаких SecurityExceptions...и вообще никаких исключений.

Не уверен, что я делаю неправильно, так как эти фрагменты, казалось, работали для других людей. Есть идеи? Это JDK 1.6 кстати.

изменить: Как указано ниже, образец кода...поставьте свой собственный модифицированный jar :)

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

2 ответов


используя приведенный ниже пример, я получил ожидаемый результат для правильно подписанного JAR (true) и измененная банка (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 signer источник был добавлен после получения входного потока.


Я понял, почему это происходит со мной...это была глупая ошибка.

У меня была моя подделанная подписанная банка, но у меня также были все те же классы, скомпилированные, так как это был мой dev env. Чтобы classloader взял скомпилированные классы по классам банку. Манифеста для скомпилированных классов нет, поэтому ошибки безопасности не создавались.

Как только я удалил скомпилированные классы, я получил ожидаемые исключения безопасности.