"Archivo de firma no válido" al intentar ejecutar un .jar


450

Mi programa java está empaquetado en un archivo jar y hace uso de una biblioteca jar externa, castillo hinchable . Mi código se compila bien, pero ejecutar el jar provoca el siguiente error:

Excepción en el subproceso "main" java.lang.SecurityException: resumen de archivo de firma no válido para los atributos principales del manifiesto

Busqué en Google durante más de una hora buscando una explicación y encontré muy poco valor. Si alguien ha visto este error antes y podría ofrecer alguna ayuda, estaría obligado.


1
¿Estás tratando de firmar tu propio frasco? Si es así, ¿cómo intenta firmarlo?
Cogsy

No, al menos no creo que lo sea. Xcode puede estar intentando firmarlo por sí solo, pero no parece haber ninguna configuración para desactivarlo.

¡no olvide verificar si los frascos que contienen interfaces implementadas también están firmados!
Gaurav

Respuestas:


47

La solución que se enumera aquí podría proporcionar un puntero.

Resumen de archivo de firma no válido para los atributos principales del manifiesto

Línea de fondo :

Probablemente sea mejor mantener el jar oficial como está y simplemente agregarlo como una dependencia en el archivo de manifiesto para el archivo jar de su aplicación.


3
¿Cómo reflejaría esto en el archivo de manifiesto? Nunca he editado uno antes. Estoy usando Xcode, y la convención común es poner bibliotecas jar externas en el directorio myproject / lib para su inclusión, que es lo que estoy haciendo.

@ user123003 .. como es el caso con Intelli-J
MikeM

13
Desafortunadamente, algunos de nosotros usamos cosas como "plug-in sombra maven" por lo que incluir copias literales del frasco original, no es tan fácil en esos casos ...
rogerdpack

enchufe descarado para responder en este sitio: stackoverflow.com/a/30922181/448779
foo

¿Qué pasa con Maven-Assembly-Plugin? Resuelve este problema en mi caso
jhenya-d

1083

Para aquellos que obtuvieron este error al intentar crear un uber-jar con maven-shade-plugin, la solución es excluir los archivos de firma de manifiesto agregando las siguientes líneas a la configuración del complemento:

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

99
Usé este método para mi uber-jar, y funcionó muy bien. Hay un ejemplo completo de POM en maven.apache.org/plugins/maven-shade-plugin/examples/… que muestra este método filtrando los archivos incluidos.
M. Dudley

44
Estuve tentado de comenzar un hilo completamente nuevo, pero como este es el número 1 en los resultados de Google, parecía apto para mantenerlo aquí. Las líneas enumeradas aquí están en el archivo POM que estoy usando, y todavía recibo el error de seguridad cuando ejecuto la aplicación. Se construye bien, y, por supuesto, funciona bien cuando NO está haciendo un jar Uber, como se esperaba. Y aunque esa es ciertamente una opción, mantenerlos separados, no resuelve el problema si quieres un Uber Jar.
Gavin Baumanis

77
Esto funciona para mí, pero ... ¿por qué tuvimos que ignorar los archivos de firma? Estoy seguro de que el manifiesto de firma está ahí por una razón ...
Jeryl Cook

44
¡Asegúrate de hacer "mvn clean" después de hacer lo anterior!
codeinjuice

44
@JerylCook Los archivos de firma están ahí para indicar que el contenido de este jar tiene estos archivos. Cuando haces un jar súper, estás agregando un montón más de archivos al jar y, por lo tanto, la firma no es correcta. Si realmente quisieras, podrías volver a firmar el nuevo frasco, pero por supuesto sería con tu firma, no con la anterior. Alternativamente, no puede distribuir el uber jar, sino que en su lugar incluye el jar firmado como un archivo separado, pero eso en primer lugar anula el propósito de un uber jar.
LadyCailin

139

Para aquellos que usan gradle e intentan crear y usar un tarro gordo, la siguiente sintaxis podría ayudar.

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

1
Esto básicamente excluye todos los archivos con extensiones de .RSA, .SF o .DSA dentro del directorio META-INF.
Keith P

99
Firmar un archivo jar agrega estos archivos en META-INF, pero cuando se incluyen, las firmas ya no están de acuerdo con el contenido del jar. Por lo tanto, eliminarlos evita el desajuste de la firma.
Peter N. Steinmetz

1
Hay una pregunta similar estrictamente sobre el uso de jarra de grasa en gradle - stackoverflow.com/questions/4871656/…
Tomasz Sętkowski

3
Esto no funcionó para mí. Tuve que poner excludea mi fatJartarea, que tenía ese configurations.compile.collectcomando. Ver stackoverflow.com/a/31426413/103412
Torsten

1
Esto también resuelve el errorError: Could not find or load main class App Caused by: java.lang.ClassNotFoundException: App
vonox7

57

Es probable que algunas de sus dependencias sean archivos jar firmados. Cuando los combina todos en un gran archivo jar, los archivos de firma correspondientes todavía están presentes, y ya no coinciden con el archivo jar "grande combinado", por lo que el tiempo de ejecución se detiene pensando que el archivo jar ha sido manipulado (lo cual ... hablar).

Puede resolver el problema eliminando los archivos de firma de sus dependencias de archivo jar. Desafortunadamente, no es posible hacer esto en un solo paso en la hormiga .

Sin embargo, pude hacer que esto funcionara con Ant en dos pasos, sin nombrar específicamente cada dependencia de archivo jar, usando:

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

Se supone que el elemento de suspensión previene errores sobre archivos con fechas de modificación en el futuro .

Otras variaciones que encontré en los hilos vinculados no funcionaron para mí.


Es posible hacerlo en un solo paso, utilizando una forma diferente de especificar sus jarras: <jar destfile = "build / myjar.jar"> <restrict> <not> <name name = "META-INF / *. SF" /> </not> <archives> <zips> <fileset dir = "jarfolder" incluye = " * / .jar" /> </zips> </archives> </restrict> </jar>
DieterDP

57

Por favor use el siguiente comando

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

44
¡Gracias, tuve este problema con intellij 14 y su solución funciona para mí!
Mohamad Kouhi Moghadam

55
Gracias, trabajó para mí en Windows. Acabo de abrir el jar con 7zip, eliminé los archivos .SF. No tenía ningún archivo .RSA para eliminar
candino

3
Wow, ¿puedo decir que esta solución fue increíble (y aprendí algo muy poderoso en el camino!) Esto necesita más votos.
Dylan_Larkin

Estoy de acuerdo con el comentario de @Dylan_Larkin, esto es lo que me resolvió.
Felipe Valdés

26

Tuve este problema al usar IntelliJ IDEA 14.01.

Pude arreglarlo:

Archivo-> Estructura del proyecto-> Agregar nuevo (artefactos) -> jar-> Desde módulos con dependencias en la ventana Crear jar desde el módulo:

Selecciona tu clase principal

Archivo JAR de bibliotecas Seleccione copiar en el directorio de salida y enlace mediante manifiesto


2
¿Es posible poner los frascos dependientes en el frasco objetivo?
coder.chenzhi

tus soluciones funcionan bien !! ¡muchas gracias!
hzitoun

19

La seguridad ya es un tema difícil, pero me decepciona ver que la solución más popular es eliminar las firmas de seguridad. JCE requiere estas firmas . Maven Shading explota el archivo jar de BouncyCastle que coloca las firmas en META-INF, pero las firmas BouncyCastle no son válidas para un nuevo jar uber (solo para el jar BC), y eso es lo que causa el error de firma no válido en este hilo .

Sí, excluir o eliminar las firmas según lo sugerido por @ruhsuzbaykus hace que el error original desaparezca, pero también puede conducir a nuevos errores crípticos:

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

Al especificar explícitamente dónde encontrar el algoritmo de esta manera:

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

Pude obtener un error diferente:

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

JCE no puede autenticar al proveedor porque hemos eliminado las firmas criptográficas siguiendo la sugerencia en otra parte de este mismo hilo .

La solución que encontré fue el complemento de empaquetador ejecutable que utiliza un enfoque jar-in-jar para preservar la firma BouncyCastle en un solo jar ejecutable.

ACTUALIZACIÓN :

Otra forma de hacer esto (¿la forma correcta?) Es usar el firmante Maven Jar . Esto le permite seguir usando la sombra Maven sin obtener errores de seguridad. SIN EMBARGO, debe tener un certificado de firma de código (Oracle sugiere buscar el "Certificado de firma de código Java"). La configuración de POM se ve así:

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

No, no hay forma de que JCE reconozca un certificado autofirmado, por lo que si necesita conservar los certificados BouncyCastle, debe usar el complemento jar-in-jar u obtener un certificado JCE.


Esta es definitivamente la forma correcta de hacerlo, incluso si es un trabajo intensivo. Gracias por señalar, en detalle, las advertencias con el uso de la respuesta aprobada. ¿Sabes si el certificado JCE debe ser firmado por Sun? O puede
WiteCastle

1
Hay terceros que pueden emitir certificados de firma de código. Busque "Certificado de firma de código Java" para ver las opciones.
MattW

Usted, señor, me alegró el día!
socona

Ayudado por mi. Hay algunos archivos en esta biblioteca que no uso, así que excepto ellos me ayudan con el archivo fat-jar
Saidolim

14

Me enfrenté al mismo problema, después de hacer referencia en alguna parte, funcionó de la siguiente manera:

<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
¡Esto resolvió mi problema rápidamente! Para completar, esto debería ir en la maven-shade-pluginetiqueta.
Kuzeko

1
@ Kuzeko Actualizó la respuesta con su sugerencia. Gracias
m.nguyencntt

8

Suponiendo que construya su archivo jar con ant, puede indicar a ant que omita el directorio META-INF. Esta es una versión simplificada de mi objetivo 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>

¿Dónde debo agregar estas líneas?
Addi.Star

4

Recientemente comencé a usar IntelliJ en mis proyectos. Sin embargo, algunos de mis colegas todavía usan Eclipse en los mismos proyectos. Hoy, tengo el mismo error después de ejecutar el archivo jar creado por mi IntelliJ. Si bien todas las soluciones aquí hablan de casi lo mismo, ninguna de ellas funcionó para mí fácilmente (posiblemente porque no uso ANT, la construcción de Maven me dio otros errores que me remitieron a http://cwiki.apache.org/ confluence / display / MAVEN / MojoExecutionException , ¡y tampoco pude entender cuáles son los frascos firmados por mí mismo!)

Finalmente esto me ayudó

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

¿Adivina qué se ha eliminado de mi archivo jar?

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

Parece que el problema era relevante para algunos archivos relevantes para eclipse.


4

Tuve el mismo problema gradleal crear un Jar gordo, actualizar el build.gradlearchivo con una línea de exclusión corrigió el problema.

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
Estuve depurando durante días, esto resolvió mi problema con el tarro gordo.
sysuser

La forma en que depuré es poner el jarro gordo en el directorio jmeter lib. Si tiene el jar problemático en lib / ext, este problema no será obvio, sino que obtendrá un error como el de stackoverflow.com/questions/37624187/…
sysuser

1
excluir 'META-INF / *. RSA', 'META-INF / *. SF', 'META-INF / *. DSA' Esto faltaba, algún frasco dependiente estaba causando el problema
Nirbhay Mishra

3

En caso de que estés usando gradle, aquí hay una tarea completa de 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

Compare la carpeta META-INF en el nuevo jar con el viejo jar (antes de agregar nuevas bibliotecas). Es posible que haya nuevos archivos. En caso afirmativo, puede eliminarlos. Debería ayudar. Saludos, 999michal


2

Una estrategia consistiría en usar ANT para simplificar la eliminación de la firma de cada archivo Jar. Continuaría con los siguientes pasos:

  1. Copiar el MANIFEST.MF en un archivo temporal
  2. Eliminar las entradas de Nombre y SHA del archivo temporal
  3. Crear un archivo Jar temporal con el manifiesto temporal
  4. Eliminar el manifiesto temporal
  5. Intercambiando el archivo Jar original con el temporal

Aquí hay una macrodef ANT haciendo el trabajo:

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

``

La definición se puede llamar de esta manera en una tarea ANT:

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

2

Error: se ha producido un error JNI, compruebe su instalación e intente de nuevo Excepción en el subproceso "main" java.lang.SecurityException: resumen de archivo de firma no válido para los atributos principales Manifest en sun.security.util.SignatureFileVerifier.processImpl (SignatureFileVerifier.java: 314) en sun.security.util.SignatureFileVerifier.process (SignatureFileVerifier.java:268) en java.util.jar.JarVerifier.processEntry (JarVerifier.java:316) en java.util.jar.JarVerifier.update (JarVerifier.java : 228) en java.util.jar.JarFile.initializeVerifier (JarFile.java:383) en java.util.jar.JarFile.getInputStream (JarFile.java:450) en sun.misc.URLClassPath $ JarLoader $ 2.getInputStream (URLClassPath .java: 977) en sun.misc.Resource.cachedInputStream (Resource.java:77) en sun.misc.Resource.getByteBuffer (Resource.java:160) en java.net.URLClassLoader.defineClass (URLClassLoader.java:454) en java.net.URLClassLoader.access $ 100 (URLClassLoader.java:73) en java.net.URLClassLoader $ 1.run (URLClassLoader.java:368) en java.net.URLClassLoader $ 1.run (URLClassLoader.java:362) en java.security.AccessController.doPrivileged (Método nativo) en java.net.URLClassLoader.findClass (URLClassLoader.java:361) en java.lang.ClassLoader.loadClass (ClassLoader.java:424) en sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:331) en java.lang.ClassLoader.loadClass (ClassLoader.java:357) en sun.launcher.LauncherHelper.checkAndLoadMain (LauncherHelper. java: 495)ejecutar (URLClassLoader.java:368) en java.net.URLClassLoader $ 1.run (URLClassLoader.java:362) en java.security.AccessController.doPrivileged (Método nativo) en java.net.URLClassLoader.findClass (URLClassLoader.java:361 ) en java.lang.ClassLoader.loadClass (ClassLoader.java:424) en sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:331) en java.lang.ClassLoader.loadClass (ClassLoader.java:357) en sun .launcher.LauncherHelper.checkAndLoadMain (LauncherHelper.java:495)ejecutar (URLClassLoader.java:368) en java.net.URLClassLoader $ 1.run (URLClassLoader.java:362) en java.security.AccessController.doPrivileged (Método nativo) en java.net.URLClassLoader.findClass (URLClassLoader.java:361 ) en java.lang.ClassLoader.loadClass (ClassLoader.java:424) en sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:331) en java.lang.ClassLoader.loadClass (ClassLoader.java:357) en sun .launcher.LauncherHelper.checkAndLoadMain (LauncherHelper.java:495)331) en java.lang.ClassLoader.loadClass (ClassLoader.java:357) en sun.launcher.LauncherHelper.checkAndLoadMain (LauncherHelper.java:495)331) en java.lang.ClassLoader.loadClass (ClassLoader.java:357) en sun.launcher.LauncherHelper.checkAndLoadMain (LauncherHelper.java:495)

Lo que me ayudó (IntelliJ IDEA 2016.3): Archivo -> Estructura del proyecto -> Artefactos -> Agregar JAR -> Seleccionar clase principal -> Elija "copiar al directorio de salida y vincular mediante manifiesto" -> Aceptar -> Aplicar -> Construir - > Construir artefactos ... -> Construir



1

Si está buscando una solución Fat JAR sin desempaquetar o alterar las bibliotecas originales pero con un cargador de clases JAR especial, eche un vistazo a mi proyecto aquí .

Descargo de responsabilidad: no escribí el código, simplemente lo empaqueté y lo publiqué en Maven Central y describí en mi archivo léame cómo usarlo.

Personalmente lo uso para crear JAR uber ejecutables que contienen dependencias BouncyCastle. Quizás también te sea útil.


0

Para aquellos que tienen problemas con la solución aceptada, hay otra forma de excluir recursos del frasco sombreado con 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>

Desde Shade 3.0, este transformador acepta una lista de recursos. Antes de eso, solo necesita usar transformadores múltiples, cada uno con un recurso.


0

Esto me sucedió en Intellij cuando hice clic en "Agregar como proyecto Maven" en la línea de fondo cuando Intellij dijo "se encontraron archivos pom no administrados". Mientras tanto, ya se generó la carpeta. Por lo tanto, no recibió cambios recientes.

Eliminar la carpeta y ejecutar el programa me resolvió el problema. nuestra carpeta fue recreada.

Vea también la respuesta de Little Fox. El error que recibí fue muy similar al suyo.


-1

Tuve un problema similar. La razón fue que estaba compilando usando un JDK con un JRE diferente al predeterminado en mi cuadro de Windows.

Usar el java.exe correcto resolvió mi problema.


-2

Si obtiene esto cuando intenta enlazar archivos JAR para un proyecto de enlaces Xamarin.Android de esta manera:

JARTOXML: advertencia J2XA006: se generó un error de clase faltante al reflejar com.your.class: resumen de archivo de firma no válido para los atributos principales del manifiesto

Simplemente abra los archivos JAR usando Winzip y elimine los directorios meta-inf. Reconstruir - trabajo hecho


1
Esta es una técnica horrible. Absolutamente horrible. Realice las correcciones localmente, no realice cambios en los frascos entrantes
sinisterrook
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.