«Неверный файл подписи» при попытке запустить .jar


451

Моя java-программа упакована в jar-файл и использует внешнюю jar-библиотеку bouncy castle . Мой код компилируется нормально, но запуск jar приводит к следующей ошибке:

Исключение в потоке "main" java.lang.SecurityException: неверный дайджест файла подписи для основных атрибутов манифеста

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


1
ты пытаешься подписать свою банку? если да, то как вы пытаетесь подписать его?
Cogsy

Нет, по крайней мере, я так не думаю. XCode может пытаться подписать его самостоятельно, но, похоже, нет никаких настроек для его отключения.

не забудьте проверить, подписаны ли банки, содержащие реализованные интерфейсы!
Гаурав

Ответы:


47

Решение, перечисленное здесь, может предоставить указатель.

Неверный дайджест файла подписи для основных атрибутов манифеста

Нижняя граница :

Вероятно, лучше оставить официальный jar как есть и просто добавить его в качестве зависимости в файле манифеста для вашего jar-файла приложения.


3
Как бы я отразил это в файле манифеста? Я никогда не редактировал один раньше. Я использую Xcode, и общепринятым условием является размещение внешних библиотек jar для включения в каталог myproject / lib, что я и делаю.

@ user123003 .. как и в случае с Intelli-J
MikeM

13
К сожалению, некоторые из нас используют такие вещи, как «плагин maven shade», поэтому в таких случаях не так просто включить дословные копии оригинальной банки ...
rogerdpack

бесстыдный плагин для ответа на этом сайте: stackoverflow.com/a/30922181/448779
foo

как насчет maven-Assembly-плагин? Это решит эту проблему в моем случае
jhenya-d

1085

Для тех, кто получил эту ошибку при попытке создать Uber-JAR с maven-shade-plugin, решение состоит в том, чтобы исключить файлы подписи манифеста, добавив следующие строки в конфигурацию плагина:

<configuration>
    <filters>
        <filter>
            <artifact>*:*</artifact>
            <excludes>
                <exclude>META-INF/*.SF</exclude>
                <exclude>META-INF/*.DSA</exclude>
                <exclude>META-INF/*.RSA</exclude>
            </excludes>
        </filter>
    </filters>
    <!-- Additional configuration. -->
</configuration>

9
Я использовал этот метод для своего uber-jar, и он отлично работал. Полный пример POM по адресу maven.apache.org/plugins/maven-shade-plugin/examples/… , демонстрирующий этот метод фильтрации включаемых файлов.
М. Дадли

4
У меня был соблазн начать совершенно новую тему - но, поскольку это первое место в результатах поиска в Google, казалось, что оно пригодится здесь. Строки, перечисленные здесь, находятся в файле POM, который я использую - и я все еще получаю ошибку безопасности при запуске приложения. Он прекрасно работает - и, конечно, работает нормально, когда НЕ делает банку Uber - как и ожидалось. И хотя это, безусловно, вариант - держите их отдельно - это не решит проблему, если вам нужен Uber Jar.
Гэвин Бауманис

7
Это работает для меня, но ... почему мы должны были игнорировать файлы подписи? Я уверен, что подпись в манифесте есть по какой-то причине ...
Джерил Кук

4
Обязательно сделайте "mvn clean" после выполнения выше!
codeinjuice

4
@JerylCook Файлы подписи находятся там, чтобы указать, что содержимое этого файла содержит эти файлы. Когда вы делаете Uber JAR, вы добавляете в него еще несколько файлов, и, таким образом, подпись неверна. Если бы вы действительно хотели, вы можете заново подписать новую банку, но, конечно, это будет с вашей подписью, а не со старой. Кроме того, вы не можете распространять Uber JAR, но вместо этого включить JAR с подписью в виде отдельного файла, но это в первую очередь наносит ущерб цели Uber JAR.
LadyCailin

139

Для тех, кто использует gradle и пытается создать и использовать толстый jar, следующий синтаксис может помочь.

jar {
    doFirst {
        from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } 
    }
    exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA' 
}

1
Это в основном исключает все файлы с расширениями .RSA, .SF или .DSA в каталоге META-INF.
Кит П

9
Подписание файла JAR добавляет эти файлы в META-INF, но когда они включены, подписи больше не согласуются с содержимым JAR. Таким образом, удаление их позволяет избежать несоответствия подписи.
Питер Н. Штайнмец

1
Существует аналогичный вопрос, касающийся использования толстой банки в gradle - stackoverflow.com/questions/4871656/…
Томаш Сэтковски

3
Это не сработало для меня. Я должен был поставить excludeсвою fatJarзадачу, которая имела эту configurations.compile.collectкоманду. См. Stackoverflow.com/a/31426413/103412
Торстен

1
Это решает также ошибкуError: Could not find or load main class App Caused by: java.lang.ClassNotFoundException: App
vonox7

57

Некоторые из ваших зависимостей, вероятно, являются подписанными jarfiles. Когда вы объединяете их в один большой jar-файл, соответствующие файлы сигнатур по-прежнему присутствуют и больше не соответствуют «большому объединенному» jar-файлу, поэтому среда выполнения останавливается, думая, что файл jar был подделан (что ... разговаривать).

Вы можете решить эту проблему, удалив файлы сигнатур из ваших зависимостей jarfile. К сожалению, это невозможно сделать за один шаг в муравье .

Тем не менее, я смог получить эту работу с Ant в два этапа, без особого именования каждой зависимости jarfile, используя:

<target name="jar" depends="compile" description="Create one big jarfile.">
    <jar jarfile="${output.dir}/deps.jar">
        <zipgroupfileset dir="jars">
            <include name="**/*.jar" />
        </zipgroupfileset>
    </jar>
    <sleep seconds="1" />
    <jar jarfile="${output.dir}/myjar.jar" basedir="${classes.dir}">
        <zipfileset src="${output.dir}/deps.jar" excludes="META-INF/*.SF" />
        <manifest>
            <attribute name="Main-Class" value="com.mycompany.MyMain" />
        </manifest>
    </jar>
</target>

Предполагается, что спящий элемент предотвращает ошибки в файлах с датами изменения в будущем .

Другие варианты, которые я нашел в связанных темах, не работали для меня.


Это можно сделать за один шаг, используя другой способ указания ваших jar-файлов: <jar destfile = "build / myjar.jar"> <restrict> <not> <name name = "META-INF / *. SF" /> </ not> <архивы> <zips> <fileset dir = "jarfolder" включает в себя = " * / .jar" /> </ zips> </ archives> </ restrict> </ jar>
DieterDP

57

Пожалуйста, используйте следующую команду

zip -d yourjar.jar 'META-INF/*.SF' 'META-INF/*.RSA' 'META-INF/*SF'

4
Спасибо, у меня была эта проблема с intellij 14, и ваше решение работает для меня!
Мохамад Коуи Могадам

5
Спасибо, у меня работало в винде. Просто открыл банку с 7zip, удалил .SF файлы. У меня не было файлов .RSA для удаления
Candino

3
Ничего себе, могу ли я просто сказать, что это решение было удивительным (и я узнал кое-что очень мощное по пути!) Это требует большего голосования.
Dylan_Larkin

Я согласен с комментарием @Dylan_Larkin, это то, что решил это для меня.
Фелипе Вальдес,

26

У меня была эта проблема при использовании IntelliJ IDEA 14.01.

Я смог это исправить:

Файл-> Структура проекта-> Добавить новый (Артефакты) -> jar-> Из модулей с зависимостями в окне Создать Jar из модуля:

Выберите свой основной класс

Файл JAR из библиотек. Выберите копию в выходной каталог и ссылку через манифест.


2
Можно ли поместить зависимые банки в целевой сосуд?
coder.chenzhi

ваши решения работают отлично !! огромное спасибо!
Хзитоун

19

Безопасность - это уже сложная тема, но я разочарован тем, что самым популярным решением является удаление сигнатур безопасности. JCE требует эти подписи . Maven shade использует файл Jar BouncyCastle, который помещает подписи в META-INF, но подписи BouncyCastle недопустимы для нового uber-jar (только для jar BC), и именно это вызывает ошибку недопустимой подписи в этом потоке ,

Да, исключение или удаление подписей в соответствии с предложением @ruhsuzbaykus действительно исключает исходную ошибку, но может также привести к новым, загадочным ошибкам:

java.security.NoSuchAlgorithmException: PBEWithSHA256And256BitAES-CBC-BC SecretKeyFactory not available

Явно указав, где найти алгоритм, вот так:

SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC","BC");

Я смог получить другую ошибку:

java.security.NoSuchProviderException: JCE cannot authenticate the provider BC

JCE не может аутентифицировать провайдера, потому что мы удалили криптографические подписи , следуя предложению в другом месте в этой же теме .

Решением, которое я нашел, был плагин исполняемого упаковщика, который использует подход jar-in-jar для сохранения подписи BouncyCastle в одном исполняемом jar.

ОБНОВЛЕНИЕ :

Еще один способ сделать это (правильный путь?) - использовать подписчик Maven Jar . Это позволяет вам продолжать использовать тени Maven без ошибок безопасности. ОДНАКО, у вас должен быть сертификат подписи кода (Oracle предлагает поискать «Сертификат подписи кода Java»). Конфигурация POM выглядит следующим образом:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.1.0</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <filters>
                    <filter>
                        <artifact>org.bouncycastle:*</artifact>
                        <excludes>
                            <exclude>META-INF/*.SF</exclude>
                            <exclude>META-INF/*.DSA</exclude>
                            <exclude>META-INF/*.RSA</exclude>
                        </excludes>
                    </filter>
                </filters>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <mainClass>your.class.here</mainClass>
                    </transformer>
                </transformers>
                <shadedArtifactAttached>true</shadedArtifactAttached>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jarsigner-plugin</artifactId>
    <version>1.4</version>
    <executions>
        <execution>
            <id>sign</id>
            <goals>
                <goal>sign</goal>
            </goals>
        </execution>
        <execution>
            <id>verify</id>
            <goals>
                <goal>verify</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <keystore>/path/to/myKeystore</keystore>
        <alias>myfirstkey</alias>
        <storepass>111111</storepass>
        <keypass>111111</keypass>
    </configuration>
</plugin>

Нет, у JCE нет способа распознать самоподписанный сертификат, поэтому, если вам нужно сохранить сертификаты BouncyCastle, вы должны либо использовать плагин jar-in-jar, либо получить сертификат JCE.


Это определенно правильный способ сделать это, даже если это интенсивная работа. Спасибо за подробное указание на предостережения с использованием утвержденного ответа. Знаете ли вы, если сертификат JCE должен быть подписан Sun? Или может
WiteCastle

1
Есть третьи лица, которые могут выдавать сертификаты подписи кода. Выполните поиск «Сертификат подписи кода Java», чтобы увидеть параметры.
MattW

Вы, сэр, сделали мой день!
Socona

Помог мне. Есть некоторые файлы в этой библиотеке, что я не использую, так что кроме них мне помочь с жиром банку файл
Saidolim

14

Я столкнулся с той же проблемой, после ссылки где-то это работало, как показано ниже:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.2.1</version>
    <configuration>
        <createDependencyReducedPom>false</createDependencyReducedPom>
    </configuration>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <filters>
                    <filter>
                        <artifact>*:*</artifact>
                        <excludes>
                            <exclude>META-INF/*.SF</exclude>
                            <exclude>META-INF/*.DSA</exclude>
                            <exclude>META-INF/*.RSA</exclude>
                        </excludes>
                    </filter>
                </filters>
            </configuration>
        </execution>
    </executions>
</plugin>

1
Это решило мою проблему быстро! Для полноты, это должно идти в maven-shade-pluginтеге.
Кузеко

1
@Kuzeko Обновил ответ с вашим предложением. Спасибо
m.nguyencntt

8

Предполагая, что вы создаете свой jar-файл с помощью ant, вы можете просто дать команду ant пропустить директорию META-INF. Это упрощенная версия моей цели:

<jar destfile="app.jar" basedir="${classes.dir}">
    <zipfileset excludes="META-INF/**/*" src="${lib.dir}/bcprov-jdk16-145.jar"></zipfileset>
    <manifest>
        <attribute name="Main-Class" value="app.Main"/>
    </manifest>
</jar>

где я должен добавить эти строки?
Addi.Star

4

Я недавно начал использовать IntelliJ в своих проектах. Тем не менее, некоторые из моих коллег все еще используют Eclipse в тех же проектах. Сегодня я получил ту же ошибку после выполнения jar-файла, созданного моим IntelliJ. Хотя все решения, о которых здесь говорится, говорят об одном и том же, ни одно из них не сработало для меня легко (возможно, из-за того, что я не использую ANT, сборка maven вызвала у меня другие ошибки, которые привели меня к http://cwiki.apache.org/ confluence / display / MAVEN / MojoExecutionException , а также я не мог понять, что такое подписанные банки самостоятельно!)

Наконец это помогло мне

zip -d demoSampler.jar 'META-INF/*.SF' 'META-INF/*.RSA' 'META-INF/*SF'

Угадай, что было удалено из моего фляги ?!

deleting: META-INF/ECLIPSE_.SF 
deleting: META-INF/ECLIPSE_.RSA

Кажется, что проблема была связана с некоторыми файлами, относящимися к затмению.


4

У меня была такая же проблема gradleпри создании толстого Jar, обновление build.gradleфайла с помощью строки исключения исправило проблему.

jar {
    from {
        configurations.compile.collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
    exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
    manifest {
        attributes 'Main-Class': 'com.test.Main'
    }
}

1
Я отлаживал в течение нескольких дней, это решило мою проблему с флягой.
sysuser

Способ, который я отлаживал, - это поместить жирный jar в директорию jmeter lib. Если у вас есть проблемный jar в lib / ext, эта проблема не будет очевидной, скорее вы получите ошибку, подобную той, что в stackoverflow.com/questions/37624187/…
sysuser

1
исключить 'META-INF / *. RSA', 'META-INF / *. SF', 'META-INF / *. DSA'. Это отсутствовало, причиной был какой-то зависимый сосуд
Нирбхай Мишра

3

Если вы используете gradle, вот полная задача farJar:

version = '1.0'
//create a single Jar with all dependencies
task fatJar(type: Jar) {
    manifest {
        attributes 'Implementation-Title': 'Gradle Jar File Example',  
            'Implementation-Version': version,
            'Main-Class': 'com.example.main'
    }
    baseName = project.name + '-all'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA' 
    with jar
}

2

Сравните папку META-INF в новом jar со старым jar (до добавления новых библиотек). Возможно, что появятся новые файлы. Если да, вы можете удалить их. Это должно помочь. С уважением, 999michal


2

Стратегия будет заключаться в использовании ANT для упрощения удаления подписи из каждого файла Jar. Было бы выполнить следующие шаги:

  1. Копирование MANIFEST.MF во временный файл
  2. Удаление имени и записей SHA из временного файла
  3. Создание временного файла Jar с временным манифестом
  4. Удаление временного манифеста
  5. Замена исходного файла Jar на временный

Вот макрос ANT, выполняющий эту работу:

<macrodef name="unsignjar" description="To unsign a specific Jar file">
    <attribute name="jarfile" 
        description="The jar file to unsign" />
    <sequential>
<!-- Copying to the temporary manifest file -->
        <copy toFile="@{jarFile}_MANIFEST.tmp">
            <resources>
                <zipentry zipfile="@{jarFile}" name="META-INF/MANIFEST.MF"/>
            </resources>
        </copy>
<!-- Removing the Name and SHA entries from the temporary file -->
        <replaceregexp file="@{jarFile}_MANIFEST.tmp" match="\nName:(.+?)\nSH" replace="SH" flags="gis" byline="false"/>
        <replaceregexp file="@{jarFile}_MANIFEST.tmp" match="SHA(.*)" replace="" flags="gis" byline="false"/>
<!-- Creating a temporary Jar file with the temporary manifest -->
        <jar jarfile="@{jarFile}.tmp"
            manifest="@{jarFile}_MANIFEST.tmp">
            <zipfileset src="@{jarFile}">
                <include name="**"/>
                <exclude name="META-INF/*.SF"/>
                <exclude name="META-INF/*.DSA"/>
                <exclude name="META-INF/*.RSA"/>
            </zipfileset>
        </jar>
<!-- Removing the temporary manifest -->
        <delete file="@{jarFile}_MANIFEST.tmp" />
<!-- Swapping the original Jar file with the temporary one -->
        <move file="@{jarFile}.tmp"
              tofile="@{jarFile}"
              overwrite="true" />
</sequential>

`

Затем определение можно назвать так в задаче ANT:

<target name="unsignJar">
    <unsignjar jarFile="org.test.myjartounsign.jar" />
</target>

2

Ошибка: произошла ошибка JNI, пожалуйста, проверьте вашу установку и попробуйте снова. Исключение в потоке "main" java.lang.SecurityException: неверный дайджест файла подписи для основных атрибутов манифеста в sun.security.util.SignatureFileVerifier.processImpl (SignatureFileVerifier.java: 314) в sun.security.util.SignatureFileVerifier.process (SignatureFileVerifier.java:268) в java.util.jar.JarVerifier.processEntry (JarVerifier.java:316) в java.util.jar.JarVerifier.update (JarVerifier : 228) в java.util.jar.JarFile.initializeVerifier (JarFile.java:383) в java.util.jar.JarFile.getInputStream (JarFile.java:450) в sun.misc.URLClassPath $ JarLoader $ 2.getInputStath (UR .java: 977) в sun.misc.Resource.cachedInputStream (Resource.java:77) в sun.misc.Resource.getByteBuffer (Resource.java:160) на java.net.URLClassLoader.defineClass (URLClassLoader.java:454) на java.net.URLClassLoader.access $ 100 (URLClassLoader.java:73) на java.net.URLClassLoader $ 1.run (URLClassLoader.java:368) на java.net.URLClassLoader $ 1.run (URLClassLoader.java:362) в java.security.AccessController.doPrivileged (собственный метод) в java.net.URLClassLoader.findClass (URLClassLoader.java:361) в java.lang.ClassLader (ClassLoader.java:424) в sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:331) в java.lang.ClassLoader.loadClass (ClassLoader.java:357) в sun.launcher.LauncherHelper.checkAndLoadHper Laine. Java: 495)запустить (URLClassLoader.java:368) в java.net.URLClassLoader $ 1.run (URLClassLoader.java:362) в java.security.AccessController.doPrivileged (собственный метод) в java.net.URLClassLoader.findClass (URLClassLoader.java.java:36) ) в java.lang.ClassLoader.loadClass (ClassLoader.java:424) в sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:331) в java.lang.ClassLoader.loadClass (ClassLoader.java:357) в ВС .launcher.LauncherHelper.checkAndLoadMain (LauncherHelper.java:495)запустить (URLClassLoader.java:368) в java.net.URLClassLoader $ 1.run (URLClassLoader.java:362) в java.security.AccessController.doPrivileged (собственный метод) в java.net.URLClassLoader.findClass (URLClassLoader.java.java:36) ) в java.lang.ClassLoader.loadClass (ClassLoader.java:424) в sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:331) в java.lang.ClassLoader.loadClass (ClassLoader.java:357) в ВС .launcher.LauncherHelper.checkAndLoadMain (LauncherHelper.java:495)331) в java.lang.ClassLoader.loadClass (ClassLoader.java:357) в sun.launcher.LauncherHelper.checkAndLoadMain (LauncherHelper.java:495)331) в java.lang.ClassLoader.loadClass (ClassLoader.java:357) в sun.launcher.LauncherHelper.checkAndLoadMain (LauncherHelper.java:495)

Что мне помогло (IntelliJ IDEA 2016.3): Файл -> Структура проекта -> Артефакты -> Добавить JAR -> Выбрать основной класс -> Выбрать "скопировать в выходной каталог и связать через манифест" -> ОК -> Применить -> Построить - > Построить артефакты ... -> Построить


1

Вполне возможно, что два разных подписчика испортили разум Java.

Попробуйте удалить папку META-INF из jar, добавить манифест и снова подписать JAR, это мне помогло: http://jehy.ru/articles/2013/12/13/invalid-signature-file-digest-for-manifest-main- атрибуты /


1
+1 за ссылку. Удаление META-INF * .RSA и META-INF * .SF из банок, с которыми я работал, решило проблемы для меня. YMMV
Катя.

1

Если вы ищете решение Fat JAR без распаковки или изменения оригинальных библиотек, но со специальным загрузчиком классов JAR, взгляните на мой проект здесь .

Отказ от ответственности: я не писал код, просто упаковал его и опубликовал в Maven Central и описал в своей статье о том, как его использовать.

Я лично использую его для создания исполняемых UAR JAR-файлов, содержащих зависимости BouncyCastle. Может быть, это тоже полезно для вас.


0

Для тех, у кого проблемы с принятым решением, есть другой способ исключить ресурс из затененной банки с помощью DontIncludeResourceTransformer:

https://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html#DontIncludeResourceTransformer

          <transformers>
            <transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
                <resource>BC1024KE.DSA</resource>
            </transformer>
          </transformers>

От Shade 3.0 этот преобразователь принимает список ресурсов. Перед этим вам просто нужно использовать несколько трансформаторов, каждый с одним ресурсом.


0

Это случилось со мной в Intellij, когда я нажал «Добавить как проект Maven» в нижней строке, когда Intellij сказал «Обнаружены неуправляемые файлы pom». Между тем, папка уже была создана. Так что он не получил последние изменения.

Удаление папки и запуск программы решили проблему для меня. папка была затем воссоздана.

Смотрите также ответ Little Fox. Ошибка, которую я получил, была очень похожа на его.


-1

У меня была аналогичная проблема. Причина была в том, что я компилировал с использованием JDK с JRE, отличным от стандартного в моем окне Windows.

Использование правильного java.exe решило мою проблему.


-2

Если вы получаете это при попытке связать файлы JAR для проекта привязок Xamarin.Android, например:

JARTOXML: предупреждение J2XA006: ошибка отсутствующего класса возникла при отражении com.your.class: неверный дайджест файла подписи для основных атрибутов манифеста

Просто откройте файлы JAR с помощью Winzip и удалите каталоги meta-inf. Перестроить - работа выполнена


1
Это ужасная техника. Абсолютно Ужасно. Внесите исправления локально, не вносите изменения во входящие банки
sinisterrook
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.