| ## Java 1.1 Unleashed # - 37 - Code Signing and JAR Security by Mike Fletcher IN THIS CHAPTER Introduction to Digital Signatures The java.security APE Signing Code with javakey Several additions and changes have been made to Java's security facilities in JDK 1.1. One of the most anticipated new features is the ability to digitally sign Java code--and to allow code signed by trusted entities to be granted access outside the normal applet sandbox. This chapter introduces the new `java.security` API, shows you how to use the `javakey` utility to create and manage digital keys, and shows you how to distribute signed code in JAR files. ## Introduction to Digital Signatures Before delving into the details of signed applets, you may find it useful to know how digital signatures work. Digital signatures provide a way to indicate that some piece of information was generated by some entity (for Java digital signatures, this "entity" is usually either a programmer or a company) and that the information has not been altered. Methods for generating signatures are designed so that it is mathematically impossible to create two different documents with the same signature in any reasonable period of time. Public key cryptography differs from what is referred to as conventional or secret key cryptography. In public key cryptography, you have one key to encrypt a message and a different key to decrypt the message. For a well-designed algorithm, it is mathematically impossible to determine the secret key given the encrypting key. The encrypting key (usually referred to as the public key) can be given to anyone who wants to send an encrypted message to the holder of the corresponding secret key (usually referred to as the private key). Anyone can use the public key to encrypt, but only the secret key can decrypt the message and recover the original text. Some public-key encryption algorithms can also be used to create digital signatures. Instead of the sender using the public key to encrypt a message to the private key holder, the private key holder encrypts the message using his or her private key. Anyone who has the public key can decrypt this message and verify that it did in fact come from the private key holder (because that person should be the only person with access to the private key). The signature algorithm used by the default JDK security package is known as DSA (Digital Signature Algorithm). DSA was created by the U.S. government's National Institute of Standards and Technology (the standard is FIPS 186, if you are interested) and the National Security Agency. The DSA has public keys that use anywhere from 512-bit to 1024-bit prime numbers and a 160-bit private key. Rather than using DSA to generate a signature of the entire document (a possibly time-consuming operation), a one-way hash of the document is generated using the MD5 algorithm; this hash is signed. MD5 generates a 128-bit string that is unique for a given input document. To verify the signature, the one-way hash of the received document is generated and checked against the signed 128-bit string from the sender. If the two match, the document has not been tampered with. NOTE: For more information on digital signatures and public key cryptography, check out Applied Cryptography, Second Edition, by Bruce Shneier (published by John Wiley & Sons, ISBN 0-471-11709-9). This book is a very good introduction to cryptography in general, as well as an excellent reference for the details on specific algorithms. On the Web, the NIST's Computer Security Resource Clearing house (`http://csrc.ncsl.nist.gov/`) provides copies of the Federal Information Processing Standards for DSA and SHA. The `sci.crypt` newsgroup and its Frequently Asked Questions posting is another good starting place for cryptography resources. ## The java.security API The `java.security` package implements the new Java Security API. This API is intended to give developers access to security functionality in a standard, cross-platform way. In addition to the digital signatures, key management, and access control lists provided in the 1.1 release, future releases of `java.security` will provide support for exchanging digital keys and data encryption. For more information on the `java.security` package, see Chapter 16, "The Security Package." ### The Signature Class The `Signature` class represents a digital signature 94gorithm. The constructor takes as its parameter a `String` representing the name of the signature algorithm desired. Once a `Signature` reference has been obtained, it must be initialized with either the private key (for signing) or the public key (for verifying a signature). To generate a signature, call the `update()` method with the contents of the document to be signed. The `update()` method takes either a single `byte` argument or a `byte[]` array with an optional offset and length. After the contents of the document have been given to `Signature()`, the `sign()` method can be called to obtain a `byte[]` representing the signature. Verifying a signature is very similar to creating one: After calling the `initVerify()` method with the `PublicKey`, the contents of the document are passed to `update()`. Once the entire contents have been given, the `verify()` method is called with the `byte[]` representing what the signature should be. The `verify()` method returns a `boolean` specifying whether the signature was valid; the `Signature()` method is reset and ready to verify another signature by the same `PublicKey`. ### The KeyPairGenerator and KeyPair Classes These classes are used to generate a pair of public and private keys for use with other security packages. The `KeyPairGenerator` class's static method `getInstance()` returns a reference to an object, which in turn may be used to generate public and private keys for the algorithm specified. The `initialize()` method sets up the generator to provide a key of a specific strength (that is, a key of a certain length, such as 512 bits or 1,024 bits). The `generateKeyPair()` method returns a `KeyPair` object. The `KeyPair` class provides two methods, `getPrivateKey()` and `getPublicKey()`, which return the corresponding key references. ### The PrivateKey and PublicKey Interfaces These two interfaces represent key material for various algorithms. Each algorithm returns objects implementing these interfaces, which then behave as appropriate for the algorithm. For example, the DSA algorithm has the `DSAPrivateKey` and `DSAPublicKey` interfaces. In general (unless you are implementing an algorithm), you do not manipulate keys directly, only give them as parameters. ### The Identity, IdentityScope, and Certificate Classes The `Identity` class represents an entity that can be authenticated by a public key. The entity represented can be a person, a company, or even a particular computer. `Identity` objects have a name associated with them; this name should be unique within a given scope. An `IdentityScope` represents a scope for an `Identity`, giving the context in which the `Identity` object exists. Both `Identity` and `IdentityScope` objects can have one or more `Certificate` objects associated with them. A `Certificate` represents a guarantee by some entity that the `Identity` and its associated public key actually belong to the owner represented by the `Identity`. For example, a programmer can be represented by an `Identity` object, which he or she uses to sign code he or she produces. The `IdentityScope` for this `Identity` object could be set to Acme Software, the company for which the programmer works. The programmer's `Identity` would have a `Certificate` signed by Acme Software. The `IdentityScope` for the company might have a `Certificate` signed by an entity providing certification of signatures (such as VeriSign or the U.S. Post Office). The `Certification` object can then be used to verify that the `Identity` is valid and belongs to the programmer. ## Signing Code with javakey The `javakey` utility included with the JDK provides facilities for managing identities and certificates, and for signing code. Along with the `jar` utility used to generate JAR files, `javakey` allows you to sign code and place the class files (and other resources used by an applet) into a single archive. Identities are stored in a database file named `identitydb.obj`, which is stored in a location specified in the `java.security` properties file in the JDK `lib/security` directory. When the applet is run in a properly configured browser, the signed code is granted privileges beyond those given to unsigned code. For example, a department can develop a signed applet for its intranet that stores its preferences in a local file on the user's computer. All the members of the department then set their browsers to allow code signed by the department to read and write files from their hard drives. ### Creating an Identity and Key Pair The first step in signing applets is to generate an identity and a public/private key pair for the identity. This is done with the following command:
    % javakey -cs "MySigner" true
NOTE: In this section, all the examples that show `javakey` commands use the `%` character to represent the command or shell prompt. The `-cs "MySigner"` part of the preceding command tells `javakey` that we want to create an identity in our `identitydb.obj` database for a signer with the name `MySigner`. The `true` parameter indicates that we will trust code signed by this particular signer. If the last argument is omitted, signatures from this signer can be verified but the code signed is not granted extra privileges. Now that we have an identity in our database, we must have `javakey` generate a key pair for our identity. The following command is used to have `javakey` create a key pair:
    % javakey -gk "MySigner" DSA 512 MySigner.public MySigner.private
This command tells `javakey` to generate a key (`-gk`) for the signer named `MySigner`. The next two arguments specify that we want a key for the DSA algorithm that is 512 bits long. The last two arguments are optional; they specify that we want `javakey` to store a copy of the public and private keys in the files named `MySigner.public` and `MySigner.private`, respectively. CAUTION: Be careful with your private keys. Anyone who can get a copy of a private key can generate signatures for the corresponding identity. ### Generating an X.509 Certificate Before you can sign code, `javakey` must generate a certificate for your identity. To do this, you have to create a text file containing the parameters for the certificate, such as the identity to create the certificate for and what period of time the certificate is valid for. For this example, the last line of the text file specifies that we want a copy of the certificate saved into the file named `MySigner.x509`. This certificate file can be distributed to people who want to verify signatures from our sample identity. You can embed comments in the directive file by preceding the comment with a `#` character. Listing 37.1 shows the contents of the directive file for our example. #### Listing 37.1. The certificate directive file.
    # This is a comment
    issuer.name=MySigner

    issuer.cert=1

    subject.name=MySigner

    subject.real.name=Example Signer
    subject.org.unit=Bogus Organization
    subject.org=Bogus Corporation
    subject.country=US

    start.date=15 Feb 1997
    end.date=15 Feb 1998
    serial.number=2000
    out.file=MySigner.x509
Once we have the certificate directive in a file, we can use the `javakey` `-gc` options to generate the actual certificate. The following command assumes that the certificate directive in List- ing 37.1 was placed in a file named `cdirective`:
    % javakey -gc cdirective
### Signing the JAR File Now we are ready to sign a JAR file with our `MySigner` identity. Assume that a JAR file named `example.jar` has already been created, and that this JAR file contains an applet (see Chap- ter 36, "JAR Basics," for more information on creating JAR files). The next step is to create a signing directive file that tells `javakey` what identity to use to sign the file, what certificate to use, and what to name the signature file. The `signer` parameter in the directive file specifies which identity we want to use to create the signature. The `cert` directive specifies which certificate the identity is to use (for this example, we use `1` because our signer has only one certificate). The next parameter, `chain`, is not used in JDK 1.1 and should be set to zero. The final parameter gives the name of the signature file that will be generated and included in the JAR file. Listing 37.2 shows the complete signing directive file. #### Listing 37.2. The signature directive file.
    # This is a comment
    signer=MySigner

    cert=1

    chain=0

    signature.file=MySig
The last step is to have `javakey` sign the JAR file. The signed version of the JAR file has `.sig` \ appended to its name. Here is the command line to use to have `javakey` sign our example JAR file:
    % javakey -gs sdirective example.jar
### Distributing Signed Code You now should have a JAR file named `example.jar.sig` which contains your applet resources and a signature by the `MySigner` identity. This JAR file can be manipulated with the `jar` utility in the same way as any other file. If you extract the contents of the JAR file, the `META-INF` directory contains the signature file just created. To grant trusted status to signed code, you must make available to users the X.509 certificate file created when the certificate was generated (this file is called `MySigner.x509` in the preceding example). Once a user has a copy of the certificate file, he or she can use `javakey` to add the identity to his or her own database. The first step in verifying a signature is similar to creating the identity--but instead of using the `-cs` flags, you use only the `-c` flag, as shown here:
    % javakey -c MySigner true
After creating the identity, you must import the actual information about the identity from the certificate file. This is done using the `javakey` `-ic` options, which take the identity name and the filename containing the certificate as parameters:
    % javakey -ic MySigner MySigner.x509
Now any code signed by the `MySigner` identity that is loaded over the network is given full access, just as if it had been loaded from a local disk. ### Other javakey Operations The `javakey` utility controls your database of identities and certificates. It can be used to list or remove identities as well as to create them. The `-l` option allows you to list a summary of all of the identities contained in `identitydb.obj`. You can use the `-ld` option to list detailed information for all entities in the database; use `-li` to limit the detailed display to a specific identity. Listing 37.3 shows what an identity listing looks like. #### Listing 37.3. An identity listing.
    % javakey -ld

    Scope: sun.security.IdentityDatabase, source file: \fletch\identitydb.obj

    MySigner[identitydb.obj][trusted]
            public key initialized
            certificates:
            certificate 1   for  : CN=Example Signer, OU=Bogus Organization, O=Bogus
     Corporation, C=US
                            from : CN=Example Signer, OU=Bogus Organization, O=Bogus
     Corporation, C=US
            No further information available.
If you want to remove an identity from the database, you can use the `-r` option with the name of the identity to delete:
    % javakey -r MySigner
## Summary You should now have an idea how the new code-signing facilities in the JDK 1.1 extend the capabilities of applets. The new `java.security` API provides a framework for manipulating digital signatures in general, as well as for creating signed code. You now understand how to use `javakey` to create and manage identities and certificates for distributing and verifying signed code.
| ©Copyright, Macmillan Computer Publishing. All rights reserved.