“无效的签名文件”;当试图运行.jar

我的java程序被打包在一个jar文件中,并使用了一个外部jar库bouncy castle。我的代码编译良好,但运行jar会导致以下错误:

java.lang.SecurityException: Manifest主属性的签名文件摘要无效

我在谷歌上搜索了一个多小时,想要找到一个解释,但几乎没有什么价值。如果有人看到这个错误之前,可以提供一些帮助,我将不胜感激。

281966 次浏览

这里列出的解决方案可能提供一个指针。

无效的Manifest主属性签名文件摘要

底线:

可能最好把官方的罐子保存为 只是将其作为依赖项添加到您的manifest文件中

. jar文件
比较新jar和旧jar中的META-INF文件夹(在添加新库之前)。有可能会有新的文件。如果是,可以删除。这应该会有所帮助。 问候, 999米甲< / p >

我也遇到过类似的问题。原因是我使用的JDK的JRE与Windows系统中的默认JRE不同。

使用正确的java.exe解决了我的问题。

假设您使用ant构建jar文件,您可以指示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>

对于那些试图用maven-shade-plugin创建阴影uber-jar时得到此错误的人,解决方案是通过在插件配置中添加以下行来排除清单签名文件:

<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>

有些依赖项可能是带符号的jarfile。当您将它们组合到一个大的jarfile中时,相应的签名文件仍然存在,并且不再匹配“大的组合”。jar文件,因此运行时停止认为jar文件已被篡改(它…可以这么说)。

假设您正在使用ant,可以通过从jarfile依赖项中删除签名文件来解决这个问题。不幸的是,在ant中不可能一步到位

但是,我能够在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>

sleep元素应该防止关于将来修改日期的文件的错误

我在链接线程中发现的其他变化并不适合我。

对于那些使用gradle并试图创建和使用fat jar的人来说,下面的语法可能会有所帮助。

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

有可能是两个不同的签名者搞砸了java思维。

尝试从jar中删除META-INF文件夹,再次添加清单和签名jar,它帮助了我:http://jehy.ru/articles/2013/12/13/invalid-signature-file-digest-for-manifest-main-attributes/

如果您在尝试为Xamarin绑定JAR文件时遇到这种情况。Android绑定项目如下:

J2XA006:在反映清单主属性的com.your.class:无效签名文件摘要时引发了缺少类错误

只需使用Winzip打开JAR文件并删除meta-inf目录。重建-工作完成

我在使用IntelliJ IDEA 14.01时遇到了这个问题。

我可以通过以下方法修复它:

文件->项目结构->添加新的(工件)->jar->从模块与依赖创建jar从模块窗口:

选择你的主要类

JAR文件从库 选择复制到输出目录并通过manifest

链接

请使用以下命令

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

一种策略包括使用ANT来简化从每个Jar文件中删除签名。它将采取下列步骤:

  1. 复制舱单。MF在临时文件中
  2. 从临时文件中删除的名字
  3. 用临时清单创建一个临时Jar文件
  4. 移除临时舱单
  5. 将原始Jar文件与临时Jar文件交换

下面是一个蚂蚁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>

错误:发生了JNI错误,请检查您的安装,然后再试一次 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) java.util.jar.JarVerifier.update (JarVerifier.java: 228) java.util.jar.JarFile.initializeVerifier (JarFile.java: 383) java.util.jar.JarFile.getInputStream (JarFile.java: 450) 在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: 454) java.net.URLClassLoader.access 100美元(URLClassLoader.java: 73) 在java.net.URLClassLoader 1.美元运行(URLClassLoader.java: 368) 在java.net.URLClassLoader 1.美元运行(URLClassLoader.java: 362) 在java.security.AccessController。doPrivileged(本地方法) java.net.URLClassLoader.findClass (URLClassLoader.java: 361) java.lang.ClassLoader.loadClass (ClassLoader.java: 424) sun.misc.Launcher AppClassLoader.loadClass美元(Launcher.java: 331) java.lang.ClassLoader.loadClass (ClassLoader.java: 357) sun.launcher.LauncherHelper.checkAndLoadMain (LauncherHelper.java: 495) < / p >

什么帮助了我(IntelliJ IDEA 2016.3): 文件->项目结构-> Artifacts ->添加JAR ->选择主类->选择“通过manifest复制到输出目录和链接”->确定->应用->构建->构建Artifacts…——> < / p >

安全性已经是一个棘手的话题,但我很失望地看到最流行的解决方案是删除安全性签名。JCE需要这些签名。Maven阴影爆炸将签名放入META-INF的BouncyCastle jar文件,但BouncyCastle签名对新的super -jar(仅对BC jar)和这就是在这个线程中导致无效签名错误的原因无效。

是的,排除或删除@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 shade而不会出现安全错误。但是,你必须有一个代码签名证书(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证书。

如果你正在使用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
}

我最近开始在我的项目中使用IntelliJ。然而,我的一些同事仍然在相同的项目中使用Eclipse。今天,在执行IntelliJ创建的jar文件后,我得到了完全相同的错误。虽然这里所有的解决方案都在谈论几乎相同的事情,但没有一个解决方案对我来说很容易(可能是因为我不使用ANT, maven构建给了我其他的错误,这些错误将我引用到http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException,而且我自己也无法弄清楚有符号的jar是什么!)

最后,帮助了我

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

猜猜我的jar文件里删除了什么!

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

这个问题似乎与一些与eclipse相关的文件有关。

如果你正在寻找一个不解包或篡改原始库的Fat JAR解决方案,而是使用一个特殊的JAR类加载器,请查看我的项目

免责声明:代码不是我写的,只是打包并发布在Maven Central上,并在我的阅读中描述如何使用它。

我个人使用它来创建包含BouncyCastle依赖的可运行的优jar。也许它对你也有用。

我有同样的问题在gradle创建一个胖罐;用排除行更新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'
}
}

我也遇到过同样的问题,经过参考,它的工作原理如下:

<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>

对于那些对已接受的解决方案有问题的人,有另一种方法可以使用dontincleresourcetransformer从阴影jar中排除资源:

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开始,这个转换器接受一个资源列表。在此之前,您只需要使用多个转换器,每个转换器具有一个资源。

这发生在我在Intellij中,当我点击“添加为Maven项目”底线时,Intellij说“发现非托管pom文件”。同时,out文件夹已经生成。所以它最近没有变化。

删除文件夹和运行程序解决了我的问题。然后重新创建Out文件夹。

看看小狐狸的回答吧。我收到的错误和他的非常相似。

你可以使用影子来生成一个jar。

Shadow是一个Gradle插件,用于将项目的依赖类和资源组合到一个输出Jar中。组合罐通常被称为fat-jar或super - Jar。

  1. < p >修改build.gradle

    plugins {
    ...
    // ① Add the shadow plugin
    id "com.github.johnrengelman.shadow" version "5.2.0"
    }
    
    
    ...
    // ② Config the shadow jar, its name is baseName-1.0-classifier.jar
    shadowJar {
    archiveBaseName.set('baseName')
    archiveClassifier.set('classifier')
    archiveVersion.set('1.0')
    manifest {
    attributes 'Main-Class': 'Main'
    }
    }
    
    
    // ③ Disable the default jar task
    jar.enabled = false
    // ④ Execute the shadowJar task when compiling
    build.dependsOn(shadowJar)
    
  2. 执行gradle build命令,生成jar文件:

    • & lt;项目Directory> /构建/ libs / basename classifier.jar——1.0

对于使用kotlin脚本(kts)作为构建脚本的人:

task("fatJar", type = Jar::class) {
baseName = "${project.name}-fat"
manifest {
attributes["Implementation-Title"] = "Watcher Jar File"
attributes["Implementation-Version"] = version
attributes["Main-Class"] = "MainKt"
}
from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) }) {
exclude(listOf("META-INF/*.RSA", "META-INF/*.SF", "META-INF/*.DSA"))
}
with(tasks.jar.get() as CopySpec)