Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / Security / April 2004

Tip: Looking for answers? Try searching our database.

Programmatic verification of signed JAR archives: CAUTION

Thread view: 
Michel Gallant - 21 Apr 2004 04:29 GMT
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/guide/jar/jar.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 - 21 Apr 2004 06:13 GMT
>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 - 21 Apr 2004 15:37 GMT
> >I checked this by changing a part of a .sf file, reinserting it into the same
> >JAR archive and reading the streamed entries succeeds!
[quoted text clipped - 6 lines]
> 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 - 21 Apr 2004 20:56 GMT
> 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 - 21 Apr 2004 23:53 GMT
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/JarVerifIssue/verijar.java

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

testbad.jar has one of the entry files (content2.txt) changed and reinserted (but not resigned):
http://www.jensign.com/JavaScience/JarVerifIssue/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/JarVerifIssue/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

> > 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
[quoted text clipped - 5 lines]
> --
> Shane
Michel Gallant - 22 Apr 2004 20:25 GMT
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

> To clarify, here is a test case showing what I mean (for those who find
> this a bit confusing):
[quoted text clipped - 79 lines]
> > --
> > Shane


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.