1. Trang chủ >
  2. Công Nghệ Thông Tin >
  3. An ninh - Bảo mật >

Chapter 12. Java Gets Out of Its Box

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (5.59 MB, 702 trang )


First of all, let’s consider the command below, which creates an archive for

the PointlessButton applet (see Figure 17 on page 37):

jar cvf pbutton.jar PointlessButton.class jamjar\examples\Button.class



Figure 181 shows the format of the pbutton.jar file that the command above

creates:



pbutton.jar

META-INF

MANIFEST.MF

PointlessButton.class



JAR Payload



jamjar

examples

Button.class



Figure 181. The pbutton Archive



The files that make up the payload of the JAR are packed into a copy of the

original directory structure. The MANIFEST.MF file, also known as the

manifest file, contains details of the payload of the JAR. The manifest file is

created under a directory META-INF. This is what the manifest looks like in

this case:



Manifest-Version: 1.0

Created-By: 1.2 (Sun Microsystems Inc.)

Figure 182. Manifest File Created by the jar cvf Command



JAR files can be digitally signed. A digital signature on a JAR file guarantees

the sender’s identity to the receiver, but it also vouches for the integrity of the

JAR file itself – that is, the JAR file was not altered after signing. JAR signing

allows you to generate digital signatures for any of the files in the archive. In

fact, files can be signed by more than one signer. So, for example, an applet



386



Java 2 Network Security



could be signed by the developer who created it and then also signed by the

IT department of the company that uses it. When the user loads the applet,

he or she not only knows that the applet comes from a trustworthy source, but

also knows that it has been approved for corporate use.

As we can see in Figure 181 on page 386, the manifest file is created by the

jar command in the META-INF directory. However, when you sign a file in a

JAR archive with the Java 2 SDK jarsigner tool, two new files are added to

the META-INF directory; we will call them the signature file and signature

block file.

Let’s discuss in detail these files one by one.



12.1.1 Manifest File

A manifest file, MANIFEST.MF, is created by default in the META-INF

directory whenever a new JAR file is created. According to the specifications

(see http://java.sun.com/products/jdk/1.2/docs/guide/jar/manifest.html), the

manifest file must include as a minimum the following line:

Manifest Version: 1.0



Figure 182 on page 386 shows the sample manifest file created by using the

jar command with the option cvf. However, you have the possibility to include

your own manifest information from a specified text file.

A customized manifest file can be manually edited, but this is a risky

operation, because you must be sure that you respect the syntax. Another

option you have is to let the jar tool create a default manifest file while

compressing the files. Then you should extract the JAR file, modify the

manifest, customizing it according to your needs, and then compress the JAR

file again including the manifest file you modified. This operation also requires

editing the manifest file, but at least you can use part of the manifest

information produced by default by the jar tool. A customized manifest can be

packed with a JAR file by using the M or m option provided with the jar utility:

• The M option does not create the manifest file at all. So the command:

jar cvfM jarFile file1 file2 ... fileN



compresses all the files in a single JAR file, without adding any manifest

information file. This can be useful if you wish to include your own manifest

file. In this case, in fact, you can use the M option and your predefined

manifest file will appear as one of the regular files that must be

compressed, as shown:

jar cvfM jarFile file1 file2 ... fileN META-INF\MANIFEST.MF



Java Gets Out of Its Box



387



where META-INF\MANIFEST.MF is the manifest file you previously created.

Remember that there can be only one manifest file in the archive. It must

be called MANIFEST.MF and it is required to be in the directory META-INF,

otherwise it will not be recognized as the manifest file during signing,

updating, verifying, etc. and will be treated as a normal file in the JAR. The

names META-INF and MANIFEST.MF should be generated as uppercase,

but they will be recognized in any case. Also, if you manually edited the

manifest file, be sure you respect the syntax.

• The m option is probably the most useful one. It can be applied as follows:

jar cvfm jarFile manifestInput file1 file2 ... fileN



or:

jar cvmf manifestInput jarFile file1 file2 ... fileN



Using the m option, a new manifest file is created taking the information

contained in an existing manifest input text file, specified on the command

prompt.

Note the order of the files to be specified on the command prompt. If the

option f is specified before m, then jarFile must come before

manifestInput; otherwise the order will have to be manifestInput

jarFile. The files to be compressed, file1 file2 ... fileN , are

always specified last.

Another important thing to notice is that, with the m option, the file you pass

on the command line as the manifest file does not need to be called

MANIFEST.MF and does not need to reside in the directory META-INF.

The jar utility will create a file called MANIFEST.MF and will place it in a

directory called META-INF, as you can see by extracting the resulting JAR

file.

There are several reasons why you might want to create a JAR file with a

specific manifest. These reasons depend on what role you want your JAR file

to play. If you're interested only in the ZIP-like features of JAR files, such as

compression and archiving, you do not have to worry about the manifest file.

The manifest doesn't really play any role in those situations. However, for

other purposes, you will need to change the default manifest file. For

example, you can add special-purpose name-value attribute headers to the

manifest file that are not contained in the default manifest. Examples of such

headers would be those for vendor information, package sealing, downloaded

extensions, and headers to make JAR-bundled applications executable.

For applications bundled in a JAR file, you have to add the following line to

your manifest file:



388



Java 2 Network Security



Main-Class: ClassName



An example of this can be found in 1.4.2.4, “Packing the Application Class in

a JAR File” on page 30.

For downloaded extensions, which are JAR files referenced by other JAR files

(see 3.4.2, “Extensions Framework” on page 86), you need to add the

following line to your manifest file:

Class-Path: extensionJarName



A package within a JAR file can be optionally sealed, which means that all

classes defined in that package must be archived in the same JAR file.

Package sealing is a new feature introduced for the first time with Java 2

SDK, Standard Edition, V1.2. You might want to seal a package, for example,

to ensure version consistency among the classes in your software or as a

security measure. To seal a package, you need to add a Name header for the

package, followed by a Sealed header, similar to this:



Name: myCompany/myPackage/

Sealed: true



The Name header’s value is the package's relative path name. Note that it

ends with a forward slash (/) to distinguish it from a file name. Any headers

following a Name header, without any intervening blank lines, apply to the file

or package specified in the Name header. In the above example, because the

Sealed header occurs after the Name header, with no blank lines between,

the Sealed header will be interpreted as applying (only) to the package

myCompany/myPackage/.

Another new feature introduced only with Java 2 SDK, Standard Edition, V1.2

is package versioning. The package versioning specification defines several

manifest headers to hold versioning information. One set of such headers can

be assigned to each package. The versioning headers should appear directly

beneath the Name header for the package. This example shows all the

versioning headers:



Name: java/util/

Specification-Title: "Java Utility Classes"

Specification-Version: "1.2"

Specification-Vendor: "Sun Microsystems, Inc.".

Implementation-Title: "java.util"

Implementation-Version: "build57"

Implementation-Vendor: "Sun Microsystems, Inc."



Java Gets Out of Its Box



389



Header information, such as vendor information, package sealing,

downloaded extensions, and headers to make JAR-bundled applications

executable, is not inserted in the default manifest file created by the jar utility.

Therefore you must provide those headers in a manifest input file and then

use the m option, or in alternative you have to edit a manifest file with the

information you need and include it in the JAR file using the M option, to

prevent jar from creating the default manifest.

Notice that the default manifest has the Created-By and Manifest-Version

information (see Figure 182 on page 386). If you use the m option and either

or both of these two pieces of information are also present in the manifest

input file you pass on the command line, the same values will be present in

the new manifest file, although the order of the entries might be rearranged.

For example if your manifest input file is:



Manifest-Version: 1.0

Created-By: DEEPAK GUPTA

Main-Class: GetProps



then the manifest file created is:



Manifest-Version: 1.0

Main-Class: GetProps

Created-By: DEEPAK GUPTA



As you can see, the jar utility has rearranged the order of the entries in the

manifest file.

On the other hand, if your original manifest file contained only the line:

Main-Class: GetProps



then the manifest file that is created is:



Manifest-Version: 1.0

Main-Class: GetProps

Created-By: 1.2 (Sun Microsystems Inc.)



So, in this case, the jar utility has provided the missing manifest information.

Also, note that the manifest file entries must have the syntax:

Name: value



390



Java 2 Network Security



When the jar utility encounters incorrect syntax, the following error is

returned in the Command Prompt window:



java.io.IOException: invalid header field

at java.util.jar.Attributes.read(Compiled Code)

at java.util.jar.Manifest.read(Compiled Code)

at java.util.jar.Manifest.(Manifest.java:55)

at sun.tools.jar.Main.run(Main.java:87)

at sun.tools.jar.Main.main(Main.java:760)



As we said also in Step 1 on page 274, the last line of the manifest input file

must be empty. That is, there should be a new line character at the end of the

file. If this is missing, the jar utility simply ignores the manifest file. Therefore,

when you are manually editing the manifest file, make sure to press the Enter

key after the last line.

When a manifest file is signed, the digest values of the files in the JAR are

added to the manifest file. Note that this behavior is different from what

happened with the JDK 1.1 jar utility, which always computed the digests,

regardless of whether or not the JAR file was signed. In other words, in JDK

1.1, the digests were calculated and added to the manifest file when the JAR

file was created. In Java 2 SDK, Standard Edition, V1.2, this operation is

done only when the JAR file is signed for the first time. This is to speed up the

creation of unsigned JAR files, for which you do not need any digests.

The following lines are present in the manifest of a signed JAR file:



Name: dirpath/whatever.class

Algorithm-Digest: base-64_representation_of_digest



So after a JAR file is signed, the manifest should look like the following:



Manifest-Version: 1.0

Created-By: 1.2 (Sun Microsystems Inc.)

Name: PointlessButton.class

SHA1-Digest: Sj15dptWhrZhiIFRNU27WRY1brc=

Name: jamjar/examples/Button.class

SHA1-Digest: Fo6pYkn6ZR17eessxEiN7fK5xpE=



The digest values recorded in the manifest are calculated from the contents

of the payload files they refer to. They are used to validate the payload files

when they are verified.



Java Gets Out of Its Box



391



Notice that by default only the SHA-1 digest is present.



12.1.2 Signature File

A signature file is automatically generated and placed in the META-INF

directory each time a JAR file is signed. This file looks very similar to the

manifest file shown above, except that the digests in it are calculated from the

manifest file entries, not from the actual contents of the payload files.

The name of this file is signerID.SF, where signerID is an arbitrary name for

the creator of the signature. If the JAR has been signed by more than one

signer, each signer will generate a separate SF file. The signature file looks

like the following:



Signature-Version: 1.0

SHA1-Digest-Manifest: 3jdG5UfTfZHcBQxGCBWSnCRb0p4=

Created-By: 1.2 (Sun Microsystems Inc.)

Name: jamjar/examples/Button.class

SHA1-Digest: WuhnnW3v9MiVHl0zlT8qnwFDY0o=

Name: PointlessButton.class

SHA1-Digest: L1S9Bcrbn4ZGAOflam1Cwn9qDFw=



The SHA1-Digest-Manifest header gives the digest of the complete manifest

file. The SHA1-Digest header for the different file entries in the SF file give

the digests of the entries of the respective files in the manifest file. By default,

the digest is calculated using the SHA-1 algorithm.



12.1.3 Signature Block File

In addition to the signature file, a signature block file is automatically placed

in the META-INF directory each time a JAR file is signed. Unlike the manifest

file or the signature file, which are ASCII files, signature block files are binary,

so they are not human-readable.

The signature block file is in PKCS#7 format1. It contains two elements

essential for verification:

1. The digital signature for the JAR file, generated with the signer’s private

key

2. The certificate containing the signer’s public key, to be used by anyone

wanting to verify the signed JAR file

1 Public Key Cryptography Standards (PKCS) is a set of rules for encoding various cryptographic structures. PKCS#7

defines a general-purpose signature format, including the signed digest, the certificate of the signer and the certification

authority (CA) certificates that support it.



392



Java 2 Network Security



Signature block file names typically will have a .DSA extension indicating that

they were created by the default Digital Signature Algorithm (DSA). Other file

name extensions are possible if keys associated with some other standard

algorithm are used for signing. For example, .RSA is the extension if the

signature is obtained from an algorithm that uses RSA encryption, and .PGP

is the extension with a Pretty Good Privacy (PGP) signature.



12.2 Signed Code Scenario in JDK 1.1 and Sun HotJava

In this section we show how to use the commands to create three key

databases:

1. A certificate authority database

2. A database for a Web server

3. A database for a Web client

We then use these keys to sign a JAR file containing an applet that attempts

to read a file on the browser system.



12.2.1 Creating the CA Key Database

The certificate authority is a principal in its own key database, with a

self-signed certificate. We create it as follows:

1. The first thing to do is to create a new key database. The key database is

created implicitly when you add the first principal to it:



D:\work\sun_signed_jar>javakey -cs "JamJar CA" true

Created identity [Signer]JamJar CA[identitydb.obj][trusted]

D:\work\sun_signed_jar>



This creates the key database identitydb.obj in your home directory.

2. Next, generate a key pair for the CA principal. We choose to use a

1024-bit key:



D:\work\sun_signed_jar>javakey -gk "JamJar CA" DSA 1024

Generated DSA keys for JamJar CA (strength: 1024).

D:\work\sun_signed_jar>



This can take a while to do. We ran it on a 75 MHz 486 machine and the

command ran for 2 minutes and 40 seconds (the time is related to the key

size).



Java Gets Out of Its Box



393



3. We use the list option of javakey to check the results so far:



D:\work\sun_signed_jar>javakey -ld

Scope: sun.security.IdentityDatabase, source file: C:\users\default\identitydb.obj

[Signer]JamJar CA[identitydb.obj][trusted]

public and private keys initialized

certificates:

No further information available.

D:\work\sun_signed_jar>



4. The key pair allows the CA to sign certificates, but we also need to

generate a certificate for the CA itself, so that others can accept the CA’s

signatures. The first thing to do is to create a certificate information file,

containing the distinguished name information for the CA and the

certificate issuer. In this case, the certificate is self-signed, so the issuer

and the subject are the same:



issuer.name=JamJar CA

issuer.cert=1

subject.name=JamJar CA

subject.real.name=Project JamJar Certificate Authority

subject.org.unit=ISL

subject.org=IBM

subject.country=UK

start.date=12 Sep 1997

end.date=12 Sep 1998

serial.number=1

out.file=cert.jamjar



We save this file as certinfo.jamjar.

5. Finally we can generate the CA’s certificate:



D:\work\sun_signed_jar>javakey -gc certinfo.jamjar

Generated certificate from directive file certinfo.jamjar.

D:\work\sun_signed_jar>javakey -ld

Scope: sun.security.IdentityDatabase, source file: C:\users\default\identitydb.o

bj

[Signer]JamJar CA[identitydb.obj][trusted]

public and private keys initialized

certificates:

certificate 1 for : CN=Project JamJar Certificate Authority, OU=ISL,O=IBM, C=UK

from : CN=Project JamJar Certificate Authority, OU=ISL,O=IBM, C=UK

No further information available.

D:\work\sun_signed_jar>



394



Java 2 Network Security



12.2.2 Creating the Server Key Database

Now we want to create a key database for our server:

1. If we use javakey to create the principal for the server, it will add it to the

CA database. So first we must choose to use a different key database, by

setting the identity.database directive in the main security properties file,

${java.home}\lib\security\java.security, where ${java.home} in this case is

the directory where JDK 1.1 was installed. We add the following line:

identity.database=D:/work/sun_signed_jar/serverdb.obj



2. The server has to know about the CA that signed its own certificate, so

first we add the CA principal to the key database and import the CA

certificate:



D:\work\sun_signed_jar>javakey -cs "JamJar CA" true

Created identity [Signer]JamJar CA[D:/work/sun_signed_jar/serverdb.obj][trusted]

D:\work\sun_signed_jar>javakey -ic "JamJar CA" cert.jamjar

Imported certificate from cert.jamjar for JamJar CA.

D:\work\sun_signed_jar>javakey -ld

Scope: sun.security.IdentityDatabase, source file: D:/work/sun_signed_jar/serverdb.obj

Signer]JamJar CA[D:/work/sun_signed_jar/serverdb.obj][trusted]

no keys

certificates:

certificate 1 for : CN=Project JamJar Certificate Authority, OU=ISL,O=IBM, C=UK

from : CN=Project JamJar Certificate Authority, OU=ISL,O=IBM, C=UK

D:\work\sun_signed_jar>



Notice that in this case the list command shows a key database with no

keys in it, just a public key certificate. This is slightly misleading, because

the certificate contains the public key; the display should really say that

there are no key pairs.

3. We create the principal and generate a key pair for our server:



D:\work\sun_signed_jar>javakey -cs "Robusta"

Created identity [Signer]Robusta[D:/work/sun_signed_jar/serverdb.obj][not trusted]

D:\work\sun_signed_jar>javakey -gk "Robusta" DSA 512

Generated DSA keys for Robusta (strength: 512).

D:\work\sun_signed_jar>



4. Next we want to use the CA key pair to sign the server’s public key. First

we export the public key to a file:



Java Gets Out of Its Box



395



D:\work\sun_signed_jar>javakey -ek Robusta pubkey.robusta

Public key exported to pubkey.robusta.

D:\work\sun_signed_jar>



5. We need to import this key into the CA’s key database. To do this we

comment out the identity.database entry that we added to java.security

(see Step 1 on page 395), create the server’s principal in the CA database

and import the public key:



D:\work\sun_signed_jar>javakey -cs "Robusta"

Created identity [Signer]Robusta[D:/work/sun_signed_jar/serverdb.obj][not trusted]

D:\work\sun_signed_jar>javakey -ik Robusta pubkey.robusta

Set public key from pubkey.robusta for Robusta.

D:\work\sun_signed_jar>



6. Now we can sign the server’s certificate. The process is the same as for

the CA certificate. First we create the certificate information file:



issuer.name=JamJar CA

issuer.cert=1

subject.name=Robusta

subject.real.name=All Java is secure but signed Java is Robusta

subject.org.unit=ISL

subject.org=IBM

subject.country=UK

start.date=12 Sep 1997

end.date=12 Sep 1998

serial.number=2

out.file=cert.robusta



7. Then we sign the certificate:



D:\work\sun_signed_jar>javakey -gc certinfo.robusta

Generated certificate from directive file certinfo.robusta.

D:\work\sun_signed_jar>



8. To use the certificate, we have to import it into the server’s key database,

which means that we first have to find out the number assigned to the

certificate in the CA database and export the certificate to a file:



396



Java 2 Network Security



Xem Thêm
Tải bản đầy đủ (.pdf) (702 trang)

×