Question

I want to sign two dozen jar files using jarsigner, giving the password only once.

Giving multiple files to jarsigner is not possible, according to the man page and using a for-loop on the command line still forces me to input the password for every file.

I would prefer a solution for the command line, but would be okay with ant/maven solution.
System is Linux.

How do I sign a dozen jar-files, giving the password only once?

Was it helpful?

Solution

Here is a snippet from the Ant build file for PSCode - it signs a slew of Jars. The trick is in the foreach element.

<target name="createjars"
  depends="compile"
  description="Jars the compiled classes">
    <mkdir dir="${build}/jar/" />

    <foreach target="jar.package" param="package" inheritall="true">
        <path>
            <dirset dir="${src}/java/org/pscode" includes="**/*" />
        </path>
    </foreach>
</target>

..and..

<target name='jar.package'>
    <script language='javascript'>
        <![CDATA[
            prop = pscode.getProperty('package');
            index1 = prop.lastIndexOf('pscode') + 7;
            index2 = prop.length();
            prop1 = prop;
            path = prop1.substring( index1, index2 );
            path2 = path.replaceAll('\\\\','/');
            pscode.setProperty('path', path2 );

            name = path2.replaceAll('/','.');
            pscode.setProperty('jar.name', name + '.jar' );
        ]]>
    </script>

    <xmlproperty file="${src}/java/org/pscode/${path}/manifest.xml" />
    <!-- echo message='jar.name: ${jar.name} *** ${application.title}' / -->
    <if>
        <not>
            <uptodate targetfile='${build}/dist/lib/${jar.name}' >
                <srcfiles dir= '${build}/share/org/pscode/${path}' includes='*.class'/>
            </uptodate>
        </not>
        <then>
            <jar
                destfile='${build}/dist/lib/${jar.name}'
                index='true'
                update='true'>
                <manifest>
                        <attribute name="Implementation-Title" value="${application.title}" />
                        <attribute name="Implementation-Vendor" value="${vendor}" />
                        <attribute name="Implementation-Vendor-Id" value="org.pscode" />
                        <attribute name='Implementation-Version' value='${now}' />
                </manifest>
                <fileset dir='${build}/share'>
                    <include name='org/pscode/${path}/*.class' />
                </fileset>
                <fileset dir='${src}/java'>
                    <include name='org/pscode/${path}/*.png' />
                    <include name='org/pscode/${path}/*.jpg' />
                    <include name='org/pscode/${path}/*.gif' />
                    <include name='org/pscode/${path}/*.xml' />
                    <include name='org/pscode/${path}/*.html' />
                    <include name='org/pscode/${path}/*.ser' />
                </fileset>
            </jar>
        </then>
    </if>

    <!-- If the Jar is updated, any previous signatures will be invalid, it
    needs to be signed again. We cannot use the issigned condition since
    that merely checks if a Jar is signed, not if the digital signatures are
    valid. -->
    <exec
        executable='${jar.signer}'
        resultproperty='jar.signer.result.property'
        outputproperty='jar.signer.output.property'>
        <arg value='-verify' />
        <arg value='${build}/dist/lib/${jar.name}' />
    </exec>

    <if>
        <or>
            <not>
                <equals arg1='${jar.signer.result.property}' arg2='0' />
            </not>
            <or>
                <contains
                    string='${jar.signer.output.property}'
                    substring='unsigned'
                    casesensitive='false' />
                <or>
                    <contains
                        string='${jar.signer.output.property}'
                        substring='SecurityException'
                        casesensitive='false' />
                </or>
            </or>
        </or>
        <then>
            <signjar
                jar='${build}/dist/lib/${jar.name}'
                alias='pscode'
                storepass='${sign.password}'
                force='true'
                verbose='${verbose}'
                keystore='${user.home}/${sign.pathfilename}' />
        </then>
    </if>

</target>

OTHER TIPS

Just for the records: jarsigner is able to read the keystore and key passwords from a file or from an environment variable, using the -keypass / -storepass command line option together with the :file or the :env modifier.

So, it's possible to put each of the passwords in a file (in my example: ~/.storepass and ~/.keypass) and use a for loop like this to sign all jars in the current directory using the key key_alias:

for i in ./*.jar; do jarsigner -storepass:file ~/.storepass -keypass:file ~/.keypass "$i" key_alias;done

To make jarsigner read the passwords from an env variable, you'll have to create those variables first:

export storepass="mystorepassword"
export keypass="mykeypassword"

Now, the loop would look like:

for i in ./*.jar; do jarsigner -storepass:env storepass -keypass:env keypass jarfile.jar key_alias;done
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top