For Programmers: Free Programming Magazines  


Home > Archive > Java Security > April 2004 > Programmatic verification of signed JAR archives: CAUTION









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Programmatic verification of signed JAR archives: CAUTION
Michel Gallant

2004-04-21, 12:32 am

I just noticed that one has to be careful about programatically verifying
signed JAR archives.
The constructors for JarFile and JarInputStream indicate that signature
verification is checked (with suitable flag).
This is true if you change say the contents of a specific entry file manually
(reading the streamed input raises the exception).

HOWEVER, reading entries via JarFile and JarInputStream by themselves
don't seem to actually authenticate the .rsa signature over the .sig file (which
uses 2 levels of indirection to the hash values of the actual target files).

The verification caused by the constructor invocation and reading streamed
entries only seems to relate to verifying hashes in the Manifest file against
the hash of the target file.

I checked this by changing a part of a .sf file, reinserting it into the same
JAR archive and reading the streamed entries succeeds!
This is bad, since it means that anyone could simply replace the files, manifest
and .sf files.
Note that jarsigner -verify -verbose does report that the signature is broken.

It seems to me that the .rsa (or .dsa) signature file itself should be the FIRST thing
that gets verified. Does the java security api support explicit .rsa signature verification
alone?

Also, this documentation is rather confusing:
http://java.sun.com/j2se/1.4.2/docs....html#Signature Validation

"The signature is first verified when the manifest is first parsed. This verification
can be remembered, for efficiency. This only validates the signature
directions themselves, not the actual archive files.
To validate a file, a digest value in the signature file is compared against a
digest calculated against the corresponding entry in the manifest file. Then, a
digest value in the manifest file is compared against a digest calculated
against the actual data referenced in the "Name:" attribute, which specifies either a
relative file path or URL. "


Are there any discussions about using the Java api to thoroughly verify
JAR signatures?

- Mitch




Roedy Green

2004-04-21, 2:34 am

On Tue, 20 Apr 2004 23:29:39 -0400, "Michel Gallant"
<neutron@NOSPAMistar.ca> wrote or quoted :

>I checked this by changing a part of a .sf file, reinserting it into the same
>JAR archive and reading the streamed entries succeeds!
>This is bad, since it means that anyone could simply replace the files, manifest
>and .sf files.
>Note that jarsigner -verify -verbose does report that the signature is broken.


The only thing that is signed is that list of digests, right? How is
someone to create a new manifest with your signature to match the
changes? He would have to sign it with HIS key, and then the user
would be asked to ok. He would see it was not you.

Of course YOU are allowed to change the manifest and resign it.

--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
Michel Gallant

2004-04-21, 11:51 am

"Roedy Green" <see@mindprod.com.invalid> wrote in message
news:dk0c8017m7qt5hta2kv2knls19c2tt2ud0@
4ax.com...
> On Tue, 20 Apr 2004 23:29:39 -0400, "Michel Gallant"
> <neutron@NOSPAMistar.ca> wrote or quoted :
>
>
> The only thing that is signed is that list of digests, right? How is
> someone to create a new manifest with your signature to match the
> changes? He would have to sign it with HIS key, and then the user
> would be asked to ok. He would see it was not you.
>


I am not talking about the signed JAR applet infrastructure which DOES seem
to properly check the .rsa file against the .sig file and then verifying this authenciated
file against the recalculated hashes specified in the manifest file.

I am referring to developers who want to manually verify JAR archives. The JAR
and related api imply that the Jar constructor checks the signature (of the .rsa against
the .sig) which is clearly not true, as my test hash shown.


Cheers,
Mitch


Shane Petroff

2004-04-21, 4:42 pm

Michel Gallant wrote:
>
> I am referring to developers who want to manually verify JAR archives. The JAR
> and related api imply that the Jar constructor checks the signature (of the .rsa against
> the .sig) which is clearly not true, as my test hash shown.


Glad to know I'm not nuts. I did a similar test but figured that I was
misusing something.

--
Shane
Michel Gallant

2004-04-21, 7:43 pm

To clarify, here is a test case showing what I mean (for those who find
this a bit confusing):

Minimal Java code used to programatically load (with verification on) Jar:
http://www.jensign.com/JavaScience/...ue/verijar.java

Samples JARs:
test.jar has technically "good" signature (self-signed certificate however)
http://www.jensign.com/JavaScience/...fIssue/test.jar

testbad.jar has one of the entry files (content2.txt) changed and reinserted (but not resigned):
http://www.jensign.com/JavaScience/...sue/testbad.jar

testbadsig.jar ONLY changed the .sig file (simply replaced the header line
from Signature-Version: 1.0 to Signature-Version: 1.0a ). No contents
are changed (nor are the hash-entry statements changed.
Since the .rsa file is a PKCS#7 signature over the entire .sig file, this breaks
the signature completely.
http://www.jensign.com/JavaScience/.../testbadsig.jar

(The above changes were made simply using WinZip ... very handy tool to
look at all files in signed JAR).

The following output using jarsigner.exe tool shows that correct verification status
is reported for all these sample JARs:

------------- jarsigner.exe verification results on good and corrupt JARs ------
jarsigner -verify test.jar
jar verified.


jarsigner -verify testbad.jar
jarsigner: java.lang.SecurityException: SHA1 digest error for contents2.txt


jarsigner -verify testbadsig.jar
jar is unsigned. (signatures missing or not parsable)
----------------------------------------------------------------------------------------

Now, the problem (or lack of understanding) arises when one uses the sample code
verijar.java to load and stream the JAR entries. Reading testbad.jar correctly reports
a bad hash result, but reading testbadsig.jar DOES NOT REPORT ANY PROBLEM, which
seems like a big problem (or serious flaw in the documentation). Evidently the .sig file
is not verified at all:

java verijar testbadsig.jar

Entry META-INF/_F8B7B1C.RSA
Starting to read entry ...
Finished reading entry.

Entry contents1.txt
Starting to read entry with attributes 1
Finished reading entry.

Entry contents2.txt
Starting to read entry with attributes 1
Finished reading entry.

Entry META-INF/_F8B7B1C.SF
Starting to read entry ...
Finished reading entry.


What this means is that to provide complete and proper signed JAR signature verification
(not just hash verification which can always been changed unnoticed) is that JAR loading should
ALWAYS first check the .rsa file against the .sig file and THEN verify the hashed via
..sig through the manifest file to the actual file entries.

So, we need to look at the source code for jarsigner.exe to see when in the process it
invokes the first (.rsa/.sig) signature verification step :-) But I suppose that source is
not public? Next best would be how to use JAR or related public Java api to force
this signature verification (instead of simple and insufficient hash-entry verification).

- Mitch Gallant
www.jensign.com



"Shane Petroff" <shane@mayet.ca> wrote in message news:plAhc.199690$Ig.98111@pd7tw2no...
> Michel Gallant wrote:
>
> Glad to know I'm not nuts. I did a similar test but figured that I was
> misusing something.
>
> --
> Shane



Michel Gallant

2004-04-22, 4:36 pm

To add a bit more to this, one can completely remove the .sig and .rsa files
from the jar and the with verify = true for Jar or JarInputStream constructors,
there are no errors reported on reading any manifest entries.

Therefore, it seems that Jar and JarInputStream initially must try to verify
the .sig/.rsa signature and if that signature fails, then the entry hashes are not
verified at all against hash values in the manifest.mf, nor are any errors returned.

- Mitch Gallant

"Michel Gallant" <neutron@NOSPAMistar.ca> wrote in message
news:5YChc.20446$CO3.911860@news20.bellglobal.com...
> To clarify, here is a test case showing what I mean (for those who find
> this a bit confusing):
>
> Minimal Java code used to programatically load (with verification on) Jar:
> http://www.jensign.com/JavaScience/...ue/verijar.java
>
> Samples JARs:
> test.jar has technically "good" signature (self-signed certificate however)
> http://www.jensign.com/JavaScience/...fIssue/test.jar
>
> testbad.jar has one of the entry files (content2.txt) changed and reinserted (but not resigned):
> http://www.jensign.com/JavaScience/...sue/testbad.jar
>
> testbadsig.jar ONLY changed the .sig file (simply replaced the header line
> from Signature-Version: 1.0 to Signature-Version: 1.0a ). No contents
> are changed (nor are the hash-entry statements changed.
> Since the .rsa file is a PKCS#7 signature over the entire .sig file, this breaks
> the signature completely.
> http://www.jensign.com/JavaScience/.../testbadsig.jar
>
> (The above changes were made simply using WinZip ... very handy tool to
> look at all files in signed JAR).
>
> The following output using jarsigner.exe tool shows that correct verification status
> is reported for all these sample JARs:
>
> ------------- jarsigner.exe verification results on good and corrupt JARs ------
> jarsigner -verify test.jar
> jar verified.
>
>
> jarsigner -verify testbad.jar
> jarsigner: java.lang.SecurityException: SHA1 digest error for contents2.txt
>
>
> jarsigner -verify testbadsig.jar
> jar is unsigned. (signatures missing or not parsable)
> ----------------------------------------------------------------------------------------
>
> Now, the problem (or lack of understanding) arises when one uses the sample code
> verijar.java to load and stream the JAR entries. Reading testbad.jar correctly reports
> a bad hash result, but reading testbadsig.jar DOES NOT REPORT ANY PROBLEM, which
> seems like a big problem (or serious flaw in the documentation). Evidently the .sig file
> is not verified at all:
>
> java verijar testbadsig.jar
>
> Entry META-INF/_F8B7B1C.RSA
> Starting to read entry ...
> Finished reading entry.
>
> Entry contents1.txt
> Starting to read entry with attributes 1
> Finished reading entry.
>
> Entry contents2.txt
> Starting to read entry with attributes 1
> Finished reading entry.
>
> Entry META-INF/_F8B7B1C.SF
> Starting to read entry ...
> Finished reading entry.
>
>
> What this means is that to provide complete and proper signed JAR signature verification
> (not just hash verification which can always been changed unnoticed) is that JAR loading should
> ALWAYS first check the .rsa file against the .sig file and THEN verify the hashed via
> .sig through the manifest file to the actual file entries.
>
> So, we need to look at the source code for jarsigner.exe to see when in the process it
> invokes the first (.rsa/.sig) signature verification step :-) But I suppose that source is
> not public? Next best would be how to use JAR or related public Java api to force
> this signature verification (instead of simple and insufficient hash-entry verification).
>
> - Mitch Gallant
> www.jensign.com
>
>
>
> "Shane Petroff" <shane@mayet.ca> wrote in message news:plAhc.199690$Ig.98111@pd7tw2no...
>
>



Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2009 codecomments.com