"Недійсний файл підпису" при спробі запустити .jar


450

Моя програма java упакована у файл з баночкою та використовує зовнішню бібліотеку банку, замок підстрибуючий . Мій код чудово компілюється, але запуск jar призводить до такої помилки:

Виняток у потоці "main" java.lang.SecurityException: Недійсний дайджест файлу підпису для основних атрибутів Manifest

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


1
ти намагаєшся підписати власну банку? якщо так, то як ви намагаєтесь його підписати?
Cogsy

Ні, принаймні я не думаю, що я є. Xcode може намагатися підписати його самостійно, але, здається, не існує жодної настройки, щоб вимкнути це.

не забудьте перевірити, чи підписані також банки, що містять реалізовані інтерфейси!
gaurav

Відповіді:


47

Перелічене тут рішення може містити вказівник.

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

Нижня лінія :

Напевно, найкраще зберегти офіційну банку такою, якою є, і просто додати її як залежність у файл маніфесту для файлу jar програми.


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

@ user123003 .. як у випадку з Intelli-J
MikeM

13
На жаль, деякі з нас використовують такі речі, як "плагін Maven Shadow", тому в тому числі дослівні копії оригінальної баночки в таких випадках не так просто ...
rogerdpack

безсоромна плагін відповісти на цьому сайті: stackoverflow.com/a/30922181/448779
пн

а що з maven-Assembly-плагін? Це питання вирішується в моєму випадку
jhenya-d

1083

Для тих , хто отримав цю помилку при спробі створити прибери-банку з 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
Я спокусився запустити цілу нову нитку - але оскільки це результат номер 1 в результатах Гуглса, - здавалося, вдало зберегти її тут. Перелічені тут рядки знаходяться у файлі POM, який я використовую - і я все одно отримую помилку безпеки під час запуску програми. Це створює чудово - і, звичайно, працює добре, коли НЕ робити банку Uber - як очікувалося. І хоча це, безумовно, варіант - тримайте їх окремо - це не вирішить питання, якщо ви хочете Uber Jar.
Гевін Бауманіс

7
Це працює для мене, але ... чому ми повинні були ігнорувати файли підписів? Впевнений, маніфест підписів є з якоїсь причини ....
Джеріл Кук

4
Не забудьте зробити "mvn clean" після виконання вище!
codeinjuice

4
@JerylCook Файли підписів є для того, щоб вказати, що вміст цієї банки містить ці файли. Коли ви робите банку uber, ви додаєте в банку ще більше файлів, і тому підпис невірний. Якщо ви дійсно хотіли, можете переписати нову банку, але, звичайно, це буде з вашим підписом, а не старим. Крім того, ви не могли поширити jar uber, а замість цього включити підписаний jar як окремий файл, але потім це перешкоджає насамперед призначенню jar uber.
LadyCailin

139

Для тих, хто використовує градел і намагається створити та використовувати жирову банку, може допомогти наступний синтаксис.

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 / ...
Tomasz Sętkowski

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

Деякі з ваших залежностей, ймовірно, підписані жарфілами. Коли ви об'єднаєте їх у один великий jarfile, відповідні файли підписів все ще є, і вони більше не відповідають "великому комбінованому" jarfile, тому час виконання зупиняється, думаючи, що файл 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 destfile = "build / myjar.jar"> <restrict> <not> <name name = "META-INF / *. SF" /> </not> <archives> <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
Дякую, працювали для мене в Windows. Просто відкрив банку з 7zip, видалив .SF файли. У мене не було жодних файлів .RSA для видалення
candino

3
Нічого собі, чи можу я сказати, що це рішення було дивовижним (і я навчився чомусь дуже потужному!) Це потребує більшої користі.
Dylan_Larkin

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

26

У мене була ця проблема під час використання IntelliJ IDEA 14.01.

Я зміг це виправити:

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

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

Файл JAR з бібліотек Виберіть копію у вихідний каталог та зв’яжіть через маніфест


2
Чи можна помістити залежні банки в цільову банку?
coder.chenzhi

ваші рішення прекрасно працюють !! дуже дякую!
hzitoun

19

Безпека - це вже жорстка тема, але я розчарований, коли найпопулярнішим рішенням є видалення підписів безпеки. СКВ вимагає цих підписів . Тінь Maven вибухає файл 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 в одній виконуваній банці.

ОНОВЛЕННЯ :

Ще один спосіб зробити це (правильний спосіб?) - використовувати підписник 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 розпізнати самопідписаний cert, тому, якщо вам потрібно зберегти серти BouncyCastle, вам доведеться або використовувати плагін jar-in-jar, або отримати cert JCE.


Це, безумовно, правильний спосіб зробити це, навіть якщо це працює інтенсивно. Дякуємо, що детально вказали на застереження із використанням схваленої відповіді. Чи знаєте ви, чи повинен підписати ВСЕ СЕР? Або можна
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

Якщо припустити, що ви створили файл з мурахами, ви можете просто доручити мурашник не залишати решту 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 build дав мені інші помилки, які передали мене на 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

Те, як я налагодив, - це покласти жирову банку в каталог ліжок jmeter. Якщо у вас є проблемні банки в Lib / вн, ця проблема не буде очевидна, а ви отримаєте повідомлення про помилку , як в stackoverflow.com/questions/37624187 / ...
sysuser

1
виключити "META-INF / *. RSA", "META-INF / *. SF", "META-INF / *. DSA" Цього не було, деякі залежні банки викликали проблему
Nirbhay Mishra

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 в новій банку зі старою банку (перед тим, як додати нові бібліотеки). Цілком можливо, що з’являться нові файли. Якщо так, ви можете їх видалити. Це повинно допомагати. З повагою, 999міхал


2

Стратегія полягала б у використанні ANT для спрощення видалення підпису з кожного файлу Jar. Він буде виконувати наступні кроки:

  1. Копіювання файлу MANIFEST.MF у тимчасовий файл
  2. Видалення записів Name та SHA з тимчасового файлу
  3. Створення тимчасового файлу Jar з тимчасовим маніфестом
  4. Видалення тимчасового маніфесту
  5. Заміна оригінального файлу Jar тимчасовим

Ось ANT macrodef виконує цю роботу:

<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: Недійсний дайджест файлів підпису для основних атрибутів Manifest на sun.security.util.SignatureFileVerifier.processImpl (SignatureFileVerifier.java: 314) у sun.security.util.SignatureFileVerifier.process (SignatureFileVerifier.java:268) на java.util.jar.JarVerifier.processEntry (JarVerifier.java:316) at java.util.jar.JarVerifier.update (JarVerifier.java : 228) на java.util.jar.JarFile.initializeVerifier (JarFile.java:383) на java.util.jar.JarFile.getInputStream (JarFile.java:250) на sun.misc.URLClassPath $ JarLoader $ 2.getInputStream (URLClassPath) .java: 977) на sun.misc.Resource.cachedInputStream (Resource.java:77) на sun.misc.Resource.getByteBuffer (Resource.java:160) на java.net.URLClassLoader.defineClass (URLClassLoader.java:154) на java.net.URLClassLoader.access $ 100 (URLClassLoader.java:73) на java.net.URLClassLoader $ 1.run (URLClassLoader.java java.net.URLClassLoader $ 1.run (URLClassLoader.java:362) на java.security.AccessController.doPrivileged (Нативний метод) на java.net.URLClassLoader.findClass (URLClassLoader.java:361) на java.lass.lass. (ClassLoader.java:124) at sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:331) at java.lang.ClassLoader.loadClass (ClassLoader.java:357) at sun.launcher.LauncherHelper.checkAndLoadMandel (Launcher). java: 495)запустити (URLClassLoader.java:368) на java.net.URLClassLoader $ 1.run (URLClassLoader.java:362) у java.security.AccessController.doPrivileged (Native Method) на java.net.URLClassLoader.findClass (URLClassLllad61) ) на java.lang.ClassLoader.loadClass (ClassLoader.java:124) на sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:131) на java.lang.ClassLoader.loadClass (ClassLoader.java:257) на сонце .launcher.LauncherHelper.checkAndLoadMain (LauncherHelper.java:195)запустити (URLClassLoader.java:368) на java.net.URLClassLoader $ 1.run (URLClassLoader.java:362) у java.security.AccessController.doPrivileged (Native Method) на java.net.URLClassLoader.findClass (URLClassLllad61) ) на java.lang.ClassLoader.loadClass (ClassLoader.java:124) на sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:131) на java.lang.ClassLoader.loadClass (ClassLoader.java:257) на сонце .launcher.LauncherHelper.checkAndLoadMain (LauncherHelper.java:195)331) на java.lang.ClassLoader.loadClass (ClassLoader.java:357) at sun.launcher.LauncherHelper.checkAndLoadMain (LauncherHelper.java:295)331) на java.lang.ClassLoader.loadClass (ClassLoader.java:357) at sun.launcher.LauncherHelper.checkAndLoadMain (LauncherHelper.java:295)

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


1

Цілком можливо, що два різних підписанта зіпсують розум Java.

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


1
+1 для посилання. Видалення META-INF * .RSA та META-INF * .SF з банок, з якими я працював, вирішив для мене проблеми. YMMV
KathyA.

1

Якщо ви шукаєте рішення Fat JAR, не розпаковуючи та не підробляючи оригінальні бібліотеки, а спеціальний завантажувач класів JAR, погляньте на мій проект тут .

Відмова: Я не писав код, просто упакував його та опублікував на Maven Central і описував у своєму читанні, як ним користуватися.

Я особисто використовую його для створення керованих JAR-файлів uber, що містять 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 сказав "знайдені не керовані файли пом.". Тим часом папка вже створена. Тож останні зміни не отримали.

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

Дивіться також відповідь Маленької Лисиці. Помилка, яку я отримав, була дуже схожа на його.


-1

У мене була схожа проблема. Причина полягала в тому, що я компілював JDK з іншим JRE, ніж стандартний у вікні Windows.

Використання правильного java.exe вирішило мою проблему.


-2

Якщо ви отримуєте це під час спроби зв'язати файли JAR для проекту прив'язки Xamarin.Android таким чином:

JARTOXML: попередження J2XA006: помилка відсутнього класу була піднята під час відображення com.your.class: Недійсний дайджест файлу підпису для основних атрибутів Manifest

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


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