我的Java程序打包在jar文件中,并使用外部jar库bouncy castle。我的代码可以正常编译,但是运行jar会导致以下错误:
线程“主”中的异常java.lang.SecurityException:清单主要属性的无效签名文件摘要
我在Google上搜索了一个多小时,一直在寻找解释,却发现价值不大。如果有人以前曾见过此错误并可以提供帮助,我将有义务。
我的Java程序打包在jar文件中,并使用外部jar库bouncy castle。我的代码可以正常编译,但是运行jar会导致以下错误:
线程“主”中的异常java.lang.SecurityException:清单主要属性的无效签名文件摘要
我在Google上搜索了一个多小时,一直在寻找解释,却发现价值不大。如果有人以前曾见过此错误并可以提供帮助,我将有义务。
Answers:
对于那些谁得到了试图创建一个当这个错误尤伯杯罐子用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>
对于使用gradle并尝试创建和使用胖子的人,以下语法可能会有所帮助。
jar {
doFirst {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
}
exclude
我的fatJar
任务,其中有这样的configurations.compile.collect
命令。请参阅stackoverflow.com/a/31426413/103412
Error: Could not find or load main class App Caused by: java.lang.ClassNotFoundException: App
您的某些依赖项可能是签名的jarfile。当您将它们全部组合到一个大的jar文件中时,相应的签名文件仍然存在,并且不再与“大组合的” jar文件匹配,因此运行时会暂停,以为jar文件已被篡改(它...已经被篡改了)。说话)。
您可以通过从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元素来防止将来具有修改日期的文件出错。
我在链接线程中发现的其他变体对我不起作用。
请使用以下命令
zip -d yourjar.jar 'META-INF/*.SF' 'META-INF/*.RSA' 'META-INF/*SF'
使用IntelliJ IDEA 14.01时出现此问题。
我可以通过以下方式修复它:
File-> Project Structure-> Add new(Artifacts)-> jar-> From Modules并具有从模块窗口中创建Jar的相关性:
选择你的主班
库中的JAR文件选择复制到输出目录并通过清单链接
安全性已经是一个艰巨的话题,但是令我失望的是,最受欢迎的解决方案是删除安全性签名。JCE需要这些签名。Maven阴影会爆炸BouncyCastle jar文件,该文件会将签名放入META-INF中,但是BouncyCastle签名对于新的uber-jar无效(仅对于BC jar),这就是导致此线程中的Invalid签名错误的原因。
是的,按照@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证书。
在引用某处后,我遇到了同样的问题,它的工作方式如下所示:
<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>
maven-shade-plugin
标记中。
假设您使用ant构建jar文件,则只需指示ant忽略META-INF目录即可。这是我的ant目标的简化版本:
<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>
我最近开始在项目中使用IntelliJ。但是,我的一些同事仍然在同一项目上使用Eclipse。今天,执行我的IntelliJ创建的jar文件后,我遇到了同样的错误。尽管这里的所有解决方案都在谈论几乎同一件事,但它们都不适合我(可能是因为我不使用ANT,Maven构建给我带来了其他错误,这些错误将我引到http://cwiki.apache.org/ confluence / display / MAVEN / MojoExecutionException,而且我自己也搞不清楚已签名的罐子是什么!)
最后,这对我有帮助
zip -d demoSampler.jar 'META-INF/*.SF' 'META-INF/*.RSA' 'META-INF/*SF'
猜猜从我的jar文件中删除了什么?
deleting: META-INF/ECLIPSE_.SF
deleting: META-INF/ECLIPSE_.RSA
似乎该问题与某些与日食有关的文件有关。
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'
}
}
如果您使用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
}
一种策略是使用ANT简化从每个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>
错误:发生了JNI错误,请检查安装情况,然后重试。线程“主”中的异常java.lang.SecurityException:sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:中清单主要属性的无效签名文件摘要: 314)在java.util.jar.JarVerifier.processEntry(JarVerifier.java:316)在sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:268)在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)at java.net.URLClassLoader.defineClass(URLClassLoader.java:454)at java.net.URLClassLoader.access $ 100(URLClassLoader.java:73)at java.net.URLClassLoader $ 1.run(URLClassLoader.java:368)at java.net.URLClassLoader.findClass(URLClassLoader.java:361)上的java.net.URLClassLoader.findClass(URLClassLoader.java:361)上的java.net.URLClassLoader $ 1.run(URLClassLoader.java:362) (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)在java.net.URLClassLoader处运行(URLClassLoader.java:368)$1。在java.net.URLClassLoader.findClass(URLClassLoader.java:361处的java.security.AccessController.doPrivileged(本机方法)处运行(URLClassLoader.java:362) )的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)在java.net.URLClassLoader处运行(URLClassLoader.java:368)$1。在java.net.URLClassLoader.findClass(URLClassLoader.java:361处的java.security.AccessController.doPrivileged(本机方法)处运行(URLClassLoader.java:362) )的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),位于sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)的java.lang.ClassLoader.loadClass(ClassLoader.java:357)331),位于sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)的java.lang.ClassLoader.loadClass(ClassLoader.java:357)
是什么帮助了我(IntelliJ IDEA 2016.3):文件->项目结构->工件->添加JAR->选择主类->选择“复制到输出目录并通过清单链接”->确定->应用->构建- >构建工件...->构建
两个不同的签名者可能会使Java思维混乱。
尝试从jar中删除META-INF文件夹,添加清单并再次签名JAR,它对我有帮助:http : //jehy.ru/articles/2013/12/13/invalid-signature-file-digest-for-manifest-main-属性/
对于那些对接受的解决方案有疑问的人,还有另一种方法是使用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文件夹然后被重新创建。
参见小狐狸的答案。我收到的错误与他的错误非常相似。
如果在尝试为Xamarin.Android绑定项目绑定JAR文件时遇到这种情况,请执行以下操作:
JARTOXML:警告J2XA006:反映com.your.class时,引发缺少类错误:清单主要属性的无效签名文件摘要
只需使用Winzip打开JAR文件并删除meta-inf目录。重建-工作完成