java - "ملف توقيع غير صالح" عند محاولة تشغيل.jar




executable-jar (13)

تتمثل الإستراتيجية في استخدام ANT لتبسيط إزالة التوقيع من كل ملف جرة. سوف المضي قدما في الخطوات التالية:

  1. نسخ MANIFEST.MF في ملف مؤقت
  2. إزالة إدخالات الاسم والشا من الملف المؤقت
  3. إنشاء ملف Jar مؤقت مع البيان المؤقت
  4. إزالة البيان المؤقت
  5. تبديل ملف Jar الأصلي مع الملف المؤقت

هنا هو ماكرو MDT القيام بهذا العمل:

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

يتم حزم برنامج جافا الخاص بي في ملف جرة ويستفيد من مكتبة جرة الخارجية ، وقلعة نطاط . تتحول التعليمة البرمجية الخاصة بي بشكل جيد ، ولكن تشغيل الجرة يؤدي إلى الخطأ التالي:

استثناء في الموضوع "main" java.lang.SecurityException: ملخص ملف التوقيع غير صالح لخصائص رئيسية تظهر

لقد غوغد لأكثر من ساعة البحث عن تفسير ووجد القليل جدا من القيمة. إذا كان أي شخص قد شاهد هذا الخطأ من قبل ويمكن أن يقدم بعض المساعدة ، فسأكون مضطرًا.


كان لي هذه المشكلة عند استخدام IntelliJ IDEA 14.01.

تمكنت من إصلاحها من خلال:

File-> بنية المشروع-> إضافة جديد (المصنوعات اليدوية) -> jar-> من الوحدات النمطية مع التبعيات على إنشاء جرة من إطار الوحدة النمطية:

اختر الفصل الرئيسي لك

JAR File from Libraries تحديد نسخة إلى دليل الإخراج والارتباط عبر البيان


الأمن بالفعل موضوع صعب ، لكنني أشعر بخيبة أمل لرؤية الحل الأكثر شيوعًا هو حذف توقيعات الأمان. JCE يتطلب هذه التوقيعات . Maven shade ينفجر ملف BouncyCastle jar الذي يضع التوقيعات في META-INF ، لكن التوقيعات BouncyCastle ليست صالحة لجرة جديدة (فقط لجرة 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 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.


بالنسبة لأولئك الذين يستخدمون غراوا ويحاولون إنشاء واستخدام جرة دهنية ، قد يساعد بناء الجملة التالي.

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

من المحتمل أن تكون بعض تبعياتك قد وقعت على jarfiles. عند دمجهم جميعًا في 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>

من المفترض أن يمنع عنصر السكون الأخطاء المتعلقة بالملفات ذات تواريخ التعديل في المستقبل .

اختلافات أخرى وجدت في المواضيع المرتبطة لم تعمل بالنسبة لي.



لأولئك الذين حصلوا على هذا الخطأ عند محاولة إنشاء 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>


إذا كنت تحصل على هذا عند محاولة ربط ملفات JAR لمشروع ربط Xamarin.Android مثل:

JARTOXML: تحذير J2XA006: تم رفع خطأ في الصف في عداد المفقودين أثناء عكس com.your.class: ملخص ملف التوقيع غير صالح للخصائص الرئيسية لل Manifest

مجرد فتح ملفات JAR باستخدام برنامج Winzip وحذف الدلائل الفوقية. إعادة البناء - العمل المنجز


يرجى استخدام الأمر التالي

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

كان لدي مشكلة مماثلة. وكان السبب في ذلك أنني كنت تجميع باستخدام JDK مع JRE مختلفة من الافتراضي واحد في بلدي ويندوز مربع.

باستخدام java.exe الصحيح حل مشكلتي.


خطأ: حدث خطأ في JNI ، يرجى التحقق من التثبيت الخاص بك وحاول مرة أخرى استثناء في java.lang.Security thread "main" thread: ملخص ملف التوقيع غير صالح لسمات Manifest الرئيسية في sun.security.util.SignatureFileVerifier.processImpl (SignatureFileVerifier.java: 314) at sun.security.util.SignatureFileVerifier.process (SignatureFileVerifier.java:268) at 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:450) at sun.misc.URLClassPath $ JarLoader $ 2.getInputStream (URLClassPath .java: 977) at sun.misc.Resource.cachedInputStream (Resource.java:77) at 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.URLClassLoade r $ 1.run (URLClassLoader.java:362) at java.security.AccessController.doPrivileged (Native Method) at java.net.URLClassLoader.findClass (URLClassLoader.java:361) at java.lang.ClassLoader.loadClass (ClassLoader.java : 424) at sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:331) at java.lang.ClassLoader.loadClass (ClassLoader.java:357) at sun.launcher.LauncherHelper.checkAndLoadMain (LauncherHelper.java:495)

ما ساعدني (IntelliJ IDEA 2016.3): File -> Project Structure -> Artifacts -> Add JAR -> Select Main Class -> Choose "copy to the output directory and link via manifest" -> OK -> Apply -> Build - > بناء المصنوعات ... -> البناء


يبدو أن TestNG لا يعاني من هذه المشكلة . أنا لست يائسًا لذلك قمت بتعديل الفئة المضمّنة المضمّنة لدعم هذه الميزة. علق فقط الاختبارات المعمول بها على أنها @ NonParameterized. لاحظ أن هذه الفئة لا تعمل إلا مع التعليقات التوضيحية ، أي تحقق من الواردات.

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.junit.Test;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.Suite;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.junit.runners.model.TestClass;

/**
 * <p>
 * The custom runner <code>Parameterized</code> implements parameterized tests.
 * When running a parameterized test class, instances are created for the
 * cross-product of the test methods and the test data elements.
 * </p>
 * For example, to test a Fibonacci function, write:
 *
 * <pre>
 * &#064;RunWith(Parameterized.class)
 * public class FibonacciTest {
 *     &#064;Parameters
 *     public static List&lt;Object[]&gt; data() {
 *         return Arrays.asList(new Object[][] {
 *                 Fibonacci,
 *                 { {0, 0}, {1, 1}, {2, 1}, {3, 2}, {4, 3}, {5, 5},
 *                         {6, 8}}});
 *     }
 *
 *     private int fInput;
 *
 *     private int fExpected;
 *
 *     public FibonacciTest(int input, int expected) {
 *         fInput = input;
 *         fExpected = expected;
 *     }
 *
 *     &#064;Test
 *     public void test() {
 *         assertEquals(fExpected, Fibonacci.compute(fInput));
 *     }
 * }
 * </pre>
 * <p>
 * Each instance of <code>FibonacciTest</code> will be constructed using the
 * two-argument constructor and the data values in the
 * <code>&#064;Parameters</code> method.
 * </p>
 */
public class Parameterized extends Suite {

    /**
     * Annotation for a method which provides parameters to be injected into the
     * test class constructor by <code>Parameterized</code>
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public static @interface Parameters {
    }

    /**
     * Annotation for a methods which should not be parameterized
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public static @interface NonParameterized {
    }

    private class TestClassRunnerForParameters extends
            BlockJUnit4ClassRunner {
        private final int fParameterSetNumber;

        private final List<Object[]> fParameterList;

        TestClassRunnerForParameters(Class<?> type,
                List<Object[]> parameterList, int i) throws InitializationError {
            super(type);
            fParameterList = parameterList;
            fParameterSetNumber = i;
        }

        @Override
        public Object createTest() throws Exception {
            return getTestClass().getOnlyConstructor().newInstance(
                    computeParams());
        }

        private Object[] computeParams() throws Exception {
            try {
                return fParameterList.get(fParameterSetNumber);
            } catch (ClassCastException e) {
                throw new Exception(String.format(
                        "%s.%s() must return a Collection of arrays.",
                        getTestClass().getName(), getParametersMethod(
                                getTestClass()).getName()));
            }
        }

        @Override
        protected String getName() {
            return String.format("[%s]", fParameterSetNumber);
        }

        @Override
        protected String testName(final FrameworkMethod method) {
            return String.format("%s[%s]", method.getName(),
                    fParameterSetNumber);
        }

        @Override
        protected void validateConstructor(List<Throwable> errors) {
            validateOnlyOneConstructor(errors);
        }

        @Override
        protected Statement classBlock(RunNotifier notifier) {
            return childrenInvoker(notifier);
        }

        @Override
        protected List<FrameworkMethod> computeTestMethods() {
            List<FrameworkMethod> ret = super.computeTestMethods();
            for (Iterator<FrameworkMethod> i = ret.iterator(); i.hasNext();) {
                FrameworkMethod frameworkMethod =
                    (FrameworkMethod) i.next();
                if (isParameterized() ^
                    !frameworkMethod.getMethod().isAnnotationPresent(
                        NonParameterized.class)) {
                    i.remove();
                }
            }
            return ret;
        }

        protected boolean isParameterized() {
            return true;
        }
    }

    private class TestClassRunnerForNonParameterized extends
        TestClassRunnerForParameters {

        TestClassRunnerForNonParameterized(Class<?> type,
            List<Object[]> parameterList, int i)
            throws InitializationError {
            super(type, parameterList, i);
        }

        protected boolean isParameterized() {
            return false;
        }
    }

    private final ArrayList<Runner> runners = new ArrayList<Runner>();

    /**
     * Only called reflectively. Do not use programmatically.
     */
    public Parameterized(Class<?> klass) throws Throwable {
        super(klass, Collections.<Runner> emptyList());
        List<Object[]> parametersList = getParametersList(getTestClass());
        if (parametersList.size() > 0) {
            try {
                runners.add(new TestClassRunnerForNonParameterized(
                    getTestClass()
                        .getJavaClass(), parametersList, 0));
            } catch (Exception e) {
                System.out.println("No non-parameterized tests.");
            }
        }
        try {
            for (int i = 0; i < parametersList.size(); i++) {
                runners.add(new TestClassRunnerForParameters(getTestClass()
                    .getJavaClass(),
                    parametersList, i));
            }
        } catch (Exception e) {
            System.out.println("No parameterized tests.");
        }
    }

    @Override
    protected List<Runner> getChildren() {
        return runners;
    }

    @SuppressWarnings("unchecked")
    private List<Object[]> getParametersList(TestClass klass)
            throws Throwable {
        return (List<Object[]>) getParametersMethod(klass).invokeExplosively(
                null);
    }

    private FrameworkMethod getParametersMethod(TestClass testClass)
            throws Exception {
        List<FrameworkMethod> methods = testClass
                .getAnnotatedMethods(Parameters.class);
        for (FrameworkMethod each : methods) {
            int modifiers = each.getMethod().getModifiers();
            if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))
                return each;
        }

        throw new Exception("No public static parameters method on class "
                + testClass.getName());
    }

}

تحديث: أحاول الحصول على هذا النوع من الأشياء المضافة إلى junit.





java jar executable-jar