<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Konstantin Shemyak - Tech Notes (Posts about jarsigner)</title><link>https://technotes.shemyak.com/</link><description></description><atom:link href="https://technotes.shemyak.com/categories/jarsigner.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2021 &lt;a href="mailto:konstantin@shemyak.com"&gt;Konstantin Shemyak&lt;/a&gt; </copyright><lastBuildDate>Fri, 02 Apr 2021 15:51:34 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Support for elliptic curves by jarsigner</title><link>https://technotes.shemyak.com/posts/support-for-elliptic-curves-by-jarsigner/</link><dc:creator>Konstantin Shemyak</dc:creator><description>&lt;div&gt;&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; Support for cryptography features by jarsigner depends on available Java crypto providers.&lt;/p&gt;
&lt;p&gt;Suppose you are defining a PKI profile. You naturally want to use the
stronger algorithms with better performance, which (as of year 2014)
means elliptic curves. Besides bit strength and performance,
you want to be sure that the curve is supported by your software.
If the latter includes &lt;strong&gt;jarsigner&lt;/strong&gt;, you'll be surprised to find that 
&lt;a href="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/jarsigner.html"&gt;Oracle documentation&lt;/a&gt;
seems to not mention at all, 
&lt;em&gt;which elliptic curves does jarsigner support&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Signing a JAR means adding digests of the JAR entries to the &lt;em&gt;manifest file&lt;/em&gt;
(&lt;code&gt;META-INF/*.MF&lt;/code&gt;),
adding digest of the latter to the &lt;em&gt;manifest signature file&lt;/em&gt;
(&lt;code&gt;META-INF/*.EC&lt;/code&gt;, in case &lt;code&gt;E&lt;/code&gt;lliptic &lt;code&gt;C&lt;/code&gt;urve is used),
and then creating the
&lt;a href="https://technotes.shemyak.com/posts/jar-signature-block-file-format/"&gt;JAR signature block file&lt;/a&gt;.
The last step involves two operations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;calculating a digest over the &lt;em&gt;manifest signature file&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;signing (i.e. encrypting with the private key) that digest.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Jarsigner has an option &lt;code&gt;-sigalg&lt;/code&gt;,
which is supposed to specify the two algorithms used in these two steps.
(There is also &lt;code&gt;-digestalg&lt;/code&gt;' option, but it is not used for the signature
block file; it defines the algorithm used in the two initial steps.)
Well, this option is irrelevant for our question: the curve is in fact
defined by the provided private key. So jarsigner will either do the job
or choke on the key which comes from an unsupported curve.&lt;/p&gt;
&lt;p&gt;A curve may "not work" because it is unknown to jarsigner itself, or to
an underlying crypto provider. (The latter case was a reason to a
&lt;a href="https://bugs.launchpad.net/ubuntu/+source/openjdk-6/+bug/1006776"&gt;bug 1006776&lt;/a&gt;,
a setup where only three curves actually worked.) Attempt to sign the JAR 
with &lt;code&gt;jarsigner&lt;/code&gt; using a non-supported private key would result in a
not very helpful error message:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;certificate&lt;/span&gt; &lt;span class="k"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IOException&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Could&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;EC&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;To be on the safe side, it's best to test. For curves, supported by OpenSSL,
the test can be done by creating the keypair on each curve and attempting
the signing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create the list of curves with &lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;openssl&lt;/span&gt; &lt;span class="n"&gt;ecparam&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;list_curves&lt;/span&gt;
&lt;/pre&gt;


&lt;ul&gt;
&lt;li&gt;remove manually some extra words openssl puts there in the beginning&lt;/li&gt;
&lt;li&gt;and feed it to the stdin:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;  &lt;span class="c1"&gt;#!/bin/bash&lt;/span&gt;
  &lt;span class="c1"&gt;# Test, which OpenSSL-supported elliptic curves from the list are supported also by jarsigner.&lt;/span&gt;
  &lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"supported- curves.txt"&lt;/span&gt;
  &lt;span class="nv"&gt;source_data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"data.txt"&lt;/span&gt;
  &lt;span class="nv"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"data.jar"&lt;/span&gt;
  &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"key.pem"&lt;/span&gt;
  &lt;span class="nv"&gt;cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"cert.pem"&lt;/span&gt;
  &lt;span class="nv"&gt;pfx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"keystore.pfx"&lt;/span&gt;
  &lt;span class="nv"&gt;key_alias&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;         &lt;span class="c1"&gt;# Identificator of the key in the keystore&lt;/span&gt;
  &lt;span class="nv"&gt;storepass&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"123456"&lt;/span&gt;      &lt;span class="c1"&gt;# jarsigner requires some&lt;/span&gt;

  touch &lt;span class="nv"&gt;$source_data&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; curve&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Generate an ECDSA private key for the selected curve:&lt;/span&gt;
    openssl ecparam -name &lt;span class="nv"&gt;$curve&lt;/span&gt; -genkey -out &lt;span class="nv"&gt;$key&lt;/span&gt;
    &lt;span class="c1"&gt;# Generate the certificate for the key; give some dummy subject:&lt;/span&gt;
    openssl req -new -x509 -nodes -key &lt;span class="nv"&gt;$key&lt;/span&gt; -out &lt;span class="nv"&gt;$cert&lt;/span&gt; -subj /CN&lt;span class="o"&gt;=&lt;/span&gt;foo
    &lt;span class="c1"&gt;# Wrap key+cert in a PKCS12, so that jarsigner can use it:&lt;/span&gt;
    openssl pkcs12 -export -in &lt;span class="nv"&gt;$cert&lt;/span&gt; -inkey &lt;span class="nv"&gt;$key&lt;/span&gt; -passout pass:&lt;span class="nv"&gt;$storepass&lt;/span&gt; -out &lt;span class="nv"&gt;$pfx&lt;/span&gt; -name &lt;span class="nv"&gt;$key_alias&lt;/span&gt;
    &lt;span class="c1"&gt;# Create a fresh jar and attempt to sign it&lt;/span&gt;
    jar cf &lt;span class="nv"&gt;$jar&lt;/span&gt; &lt;span class="nv"&gt;$source_data&lt;/span&gt;
    jarsigner -keystore &lt;span class="nv"&gt;$pfx&lt;/span&gt; -storetype PKCS12 -storepass &lt;span class="nv"&gt;$storepass&lt;/span&gt; &lt;span class="nv"&gt;$jar&lt;/span&gt; &lt;span class="nv"&gt;$key_alias&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; -eq &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$curve&lt;/span&gt; &amp;gt;&amp;gt; &lt;span class="nv"&gt;$result&lt;/span&gt;
  &lt;span class="k"&gt;done&lt;/span&gt;
  rm &lt;span class="nv"&gt;$source_data&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="nv"&gt;$cert&lt;/span&gt; &lt;span class="nv"&gt;$pfx&lt;/span&gt; &lt;span class="nv"&gt;$jar&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;And enjoy the list in &lt;code&gt;supported-curves.txt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;support of elliptic curves by &lt;b&gt;jarsigner&lt;/b&gt; depends on jarsigner itself and on the used JRE.&lt;/li&gt;
&lt;li&gt;There is no command-line option to list all supported curves.&lt;/li&gt;
&lt;li&gt;For a particular system, support for curves known by &lt;b&gt;OpenSSL&lt;/b&gt; can be easily tested.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</description><category>elliptic curves</category><category>jarsigner</category><category>openssl</category><guid>https://technotes.shemyak.com/posts/support-for-elliptic-curves-by-jarsigner/</guid><pubDate>Sun, 21 Dec 2014 19:45:00 GMT</pubDate></item><item><title>JAR signature block file format</title><link>https://technotes.shemyak.com/posts/jar-signature-block-file-format/</link><dc:creator>Konstantin Shemyak</dc:creator><description>&lt;div&gt;&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; this post explains the content of the &lt;strong&gt;JAR signature block file&lt;/strong&gt; - 
that is, the file &lt;code&gt;META-INF/*.RSA&lt;/code&gt;, &lt;code&gt;META-INF/*.DSA&lt;/code&gt;, &lt;code&gt;META-INF/*.EC&lt;/code&gt;
or &lt;code&gt;SIG-*&lt;/code&gt; inside the JAR.&lt;/p&gt;
&lt;h3&gt;Oracle does not document it&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Signed JAR file&lt;/strong&gt; contains the following additions over a non-signed JAR:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Checksums over the JAR content, stored in text files
  &lt;code&gt;META-INF/MANIFEST.MF&lt;/code&gt; and &lt;code&gt;META-INF/*.SF&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The actual cryptographic signature (created with the private key
  of the signer) over the checksums in a binary &lt;strong&gt;signature block file&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Surprisingly, format of the latter does not seem to be documented by Oracle. &lt;a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Digital_Signatures"&gt;JAR file specification&lt;/a&gt;
provides only a useful knowledge that
&lt;em&gt;"These are binary files not intended to be interpreted by humans"&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Here, the content of this "signature block file" is explained.
We show how it can be created and verified with non-Java tool: OpenSSL.&lt;/p&gt;
&lt;h3&gt;Create a sample signature block file&lt;/h3&gt;
&lt;p&gt;For our investigation, generate such file by signing some data with &lt;strong&gt;jarsigner&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make an RSA private key (and store it unencrypted), corresponding
  self-signed certificate, pack them in a format jarsigner understands:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;openssl genrsa -out key.pem
openssl req -x509 -new -key key.pem -out cert.pem -subj &lt;span class="s1"&gt;'/CN=foo'&lt;/span&gt;
openssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.pfx -passout pass:123456 -name SEC_PAD
&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;openssl req&lt;/code&gt; command reads the default OpenSSL configuration file.
If you care about exact content of your certificate, you should
not rely on the system default but write your own (you can start with a
&lt;a href="https://technotes.shemyak.com/posts/min-openssl-cnf"&gt;minimal example&lt;/a&gt;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create the data, jar it, sign the JAR, and unpack the "META-INF" directory:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Hello, world!'&lt;/span&gt; &amp;gt; data
jar cf data.jar data
jarsigner -keystore keystore.pfx -storetype PKCS12 -storepass &lt;span class="m"&gt;123456&lt;/span&gt; data.jar SEC_PAD
unzip data.jar META-INF/*
&lt;/pre&gt;


&lt;p&gt;The "signature block file" is &lt;code&gt;META-INF/SEC_PAD.RSA&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;What does this block contain&lt;/h3&gt;
&lt;p&gt;The file appears to be a &lt;a href="http://www.herongyang.com/Cryptography/Certificate-Format-DER-Distinguished-Encoding-Rules.html"&gt;DER-encoded&lt;/a&gt;
&lt;a href="https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One"&gt;ASN.1&lt;/a&gt;
&lt;a href="https://tools.ietf.org/html/rfc2315"&gt;PKCS#7&lt;/a&gt; data structure.
DER-encoded ASN.1 file can be examined with &lt;code&gt;asn1parse&lt;/code&gt; subcommand of the OpenSSL:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;openssl asn1parse -in META-INF/SEC_PAD.RSA -inform der -i &amp;gt; jarsigner.txt
&lt;/pre&gt;


&lt;p&gt;For more verbosity, you may use some ASN.1 decoder such as one at
&lt;a href="http://lapo.it/asn1js/"&gt;lapo.it&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You'll see that the two top-level components are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The certificate.&lt;/li&gt;
&lt;li&gt;256-byte RSA signature.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can extract the signature bytes from the binary data and
&lt;a href="http://qistoph.blogspot.com/2012/01/manual-verify-pkcs7-signed-data-with.html"&gt;verify&lt;/a&gt; (=decrypt with the public key) them with &lt;code&gt;openssl rsautl&lt;/code&gt;.
That includes some "low-level" operations and brings you one more step down 
to understanding the file's content.
A simple "high-level" verification command, not involving manual byte
manipulation, would be:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;openssl cms -verify -noverify -content META-INF/SEC_PAD.SF -in META-INF/SEC_PAD.RSA -inform der
&lt;/pre&gt;


&lt;p&gt;This command tells: &lt;em&gt;"Check that the CMS structure in &lt;code&gt;META-INF/SEC_PAD.RSA&lt;/code&gt;
is really a signature of &lt;code&gt;META-INF/SEC_PAD.SF&lt;/code&gt;; do not attempt to validate
the certificate"&lt;/em&gt;. Congratulations, we have verified the JAR signature
without Java tools.&lt;/p&gt;
&lt;h3&gt;Creating the signature block file with OpenSSL&lt;/h3&gt;
&lt;p&gt;For this example, we created the signature block file with &lt;strong&gt;jarsigner&lt;/strong&gt;. 
There are at least two OpenSSL commands which can produce similar 
structures: &lt;code&gt;openssl cms&lt;/code&gt; and &lt;code&gt;openssl smime&lt;/code&gt;, with the options given below:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;openssl cms -sign -binary -noattr -in META-INF/SEC_PAD.SF -outform der -out openssl-cms.der -signer cert.pem -inkey key.pem -md sha256
openssl smime -sign -noattr -in META-INF/SEC_PAD.SF -outform der -out openssl-smime.der -signer cert.pem -inkey key.pem -md sha256
&lt;/pre&gt;


&lt;p&gt;Let's decode the created files and compare them to what has been produced
with &lt;code&gt;jarsigner&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;openssl asn1parse -inform der -in openssl-cms.der -i &amp;gt; openssl-cms.txt
openssl asn1parse -inform der -in openssl-smime.der -i &amp;gt; openssl-smime.txt
&lt;/pre&gt;


&lt;h3&gt;Testing the "DIY signature"&lt;/h3&gt;
&lt;p&gt;Underlying ASN.1 structures are, in both &lt;strong&gt;cms&lt;/strong&gt; and &lt;strong&gt;smime&lt;/strong&gt; cases,
very close but not identical to those made by &lt;code&gt;jarsigner&lt;/code&gt;. 
As the format of the signature block file is not specified,
we can only do tests to have some ground to say that "it works".
Just replace the original signature block file with our signature
created by OpenSSL:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;cp openssl-cms.der META-INF/SEC_PAD.RSA
zip -u data.jar META-INF/SEC_PAD.RSA
jarsigner -verify -keystore keystore.pfx -storetype PKCS12 -storepass &lt;span class="m"&gt;123456&lt;/span&gt; data.jar SEC_PAD
&lt;/pre&gt;


&lt;p&gt;Lucky strike: a signature produced by &lt;code&gt;openssl cms&lt;/code&gt; is recognized by
&lt;code&gt;jarsigner&lt;/code&gt; (that is, at least "it worked for me").&lt;/p&gt;
&lt;p&gt;Note that the &lt;strong&gt;data&lt;/strong&gt; which is signed is &lt;code&gt;SEC_PAD.SF&lt;/code&gt;, and it was 
itself created by jarsigner. If not using the latter, you'll need to
produce that file in some way.&lt;/p&gt;
&lt;h3&gt;What's the use for this knowledge?&lt;/h3&gt;
&lt;p&gt;Besides better understanding your data, one can think of at least two
reasons to sign JARs with non-native tools. Both are somewhat untypical,
but not completely irrelevant:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The signature must be produced in a system, where native Java tools are not available. 
Such system must have access to private key, and security administrators
may like the idea of not having such overbloated software as JRE in a
tightly controlled environment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The signature must be produced or verified in a system, where available tools do not support the required signature algorithm.
Examples "why" include compliance with regulations or compatibility with
legacy systems. There are systems where &lt;a href="https://technotes.shemyak.com/posts/support-for-elliptic-curves-by-jarsigner/"&gt;testing which elliptic curves are supported by jarsigner&lt;/a&gt;
reveals just three curves (which is not much).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Summary (again)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;JAR signature block file&lt;/strong&gt; is a DER-encoded PKCS#7 structure.&lt;/li&gt;
&lt;li&gt;Its exact content can be viewed with any ASN.1 decoder, e.g. with &lt;code&gt;openssl asn1parse&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;OpenSSL can verify signatures in signature block files and create almost
  identical structures, which have been reported to be accepted by Java
  tools.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</description><category>jar</category><category>jarsigner</category><category>openssl</category><category>pkcs#7</category><category>signature</category><guid>https://technotes.shemyak.com/posts/jar-signature-block-file-format/</guid><pubDate>Mon, 08 Dec 2014 12:18:00 GMT</pubDate></item></channel></rss>