Java Cryptography & X.509 Authentication

Dr. Dobb's Journal February, 2005

Putting the Java cryptography architecture to work

By Snezana Sucurovic and Zoran Jovanovic

Snezana is a researcher at Belgrade's Institute Mihailo Pupin and can be contacted at snezana@impcs.com. Zoran is director of the Belgrade University Computing Center.

Most systems use passwords as a verification of claimed identity. However, conventional passwords have disadvantages. For one thing, they can easily be shared among users or become easy targets for eavesdropping. Another way for proving identity is by the use of digital certificates, also known as "digital IDs." The most widely accepted format for digital certificates is defined by the ITU-T X.509 International Standard, enabling certificates to be read or written by any application complying with X.509. In short, X.509 is a Standard that makes it possible to identify someone on the Internet.

Authentication methods specified on X.509 are based upon public-key cryptosystems. For users to trust the authentication procedure, the procedure needs to get the other user's public key from a source that it trusts. The source, called a "certification authority" (CA), uses the public-key algorithm to certify the public key, producing a certificate. Because certificates are unforgeable, they can be published by being placed in the Directory, without the need for the latter to make special efforts to protect them.

As shown in Listing One(a), in addition to the public key of the certificate owner, digital certificates contain the following:

Digital certificates are signed with the CA's private key. The protocol used by applications to obtain the certificate from the Directory is the Directory Access Protocol (DAP), specified in ITU-T Recommendation X.519.

Standards-compliant applications that use the authentication framework need to specify the protocol exchanges that must be performed to achieve authentication based upon the authentication information obtained from the Directory. In this article, we present an application based on the authentication protocol given in the Comité Européen de Normalisation (CEN) Standard for medical information systems—CEN ENV 13729 "Health Informatics—Secure User Identification: Strong Authentication Using Microprocessor Cards" (see Figure 1). In this protocol, a reply attack (sending of old messages) is prevented by the entity that requires authentication through sending a generated random number on which the entity that proves identity creates a digital signature. X.509 supports one-way authentication, where only one party proves identity, and two-way authentication, which is mutual identification. The Standard also describes three-way authentication, which involves one additional data transfer. In our application, one-way authentication is applied (two-way could be applied analogously).

We use Java Crypto API for the realization of authentication in a distributed system, where clients access servers in the system via a central server. All certificates are generated centrally on demand and imported in a central repository—the keystore. Certificates are signed with the "CA" key; that is, a private key that belongs to a central server. Certificates and private key files are sent to clients before authentication begins. Clients import certificates and private keys into a local keystore using the AppletImportCertificates applet (available electronically; see "Resource Center," page 5). This application has been tested using Tomcat 4.1 and Netscape 6 with a Java 1.3.0_1 plugin. Before running the application, a read/write permissions must be added to the java.policy file on directory javaPlugIn_home/java/lib/security.

The application comprises several applets and one servlet:

In our application, access control is achieved using certificate extensions that contain a ROLE belonging to a certificate owner. Each extension is identified by an Object Identifier, which, according to ASN.1, is a string of integer values assigned by the Registration Authority; see Listing One(b).

Java Cryptography Architecture

The first version of Java Crypto Architecture (JCA), contained in JDK1.1, included an API for a digital signature and message digest. Version 1.2 was the first to include an infrastructure supporting X.509 v3 certificates.

JCA is a provider-based framework that provides a particular functionality (Message Digest, Digital Signing) and is independent of algorithms, and there exist providers that implement algorithms.

The infrastructure supporting X.509 certificates involves these services:

Keys in JCA can have a "transparent" or an "opaque" representation. The opaque representation has three characteristics: an algorithm, coded form, and format. The most important attribute of the opaque representation is its coded form that permits, when necessary, the keys to be used out of JVM; for example, when the keys are sent to some other party. Contrary to this, the most important characteristic of the transparent representation is the possibility of access to single parts of a key. In our application, we have used the opaque representation of keys only.

The algorithm in the opaque representation of a key denotes an algorithm (such as DSA and RSA) in which a given key is used together with the hash function algorithm (for example, MD5withRSA or SHA1withRSA).

A format is the format in which keys are coded (X.509 for a public key and PKCS#8 for a private key, for example). The name of ASN.1 data type for a public key is SubjectPublicKeyInfo, and this data type is defined in the X.509 Standard. The SubjectPublicKeyInfo is defined in the X.509 Standard in ASN.1 terms, as in Listing Two.

Similar to this, the ASN.1 data type that represents private keys is named "PrivateKeyInfo" and defined in the PKCS#8 Standard. PKCS#8 denotes a Standard whose full name is "Private Key Information Syntax Standard" (see http://www.rsa.com/). In Listing Three, Attribute is a data type consisting of an attribute type (given as an OBJECT IDENTIFIER) and one or more values. Certificates are generated by creating first the class X509CertInfo and then all the attributes of a certificate; see Listing Four. After that, a CA private key is used to create a digital signature on a certificate.

The keystore database can be used to manage the repository of keys and certificates. Several different actual implementations may exist, each of them being characterized by a particular type. At present, there also exists keytool, a keystore management tool that is started from the command line. There is also a built-in default implementation provided by Sun. According to this implementation, a keystore is a file of JKS format. In Sun's implementation, passwords are used to protect each private key as well as the entire keystore.

Keystore type determines the format of information contained in the keystore as well as the algorithms used for protecting private keys and the keystore itself. Different keystore implementations are not compatible. "JKS," a default keystore type (implemented by Sun), is specified in the line keystore.type=jks, from the file java_home/jre/lib/java.security. If some other keystore implementation is used, the type of that implementation ("pkcs12," for instance) should be entered into this file.

A KeyStore class represents a collection of keys and certificates. There are two types of entry:

Each entry in the keystore is identified by an "alias" string. In case of a private key and an associated chain of certificates, the alias distinguishes between the different methods an identity can use for authentication purposes. For example, an entity may authenticate itself using various CA. Listings Five(a) and Five(b) illustrate the JKS data format

Conclusion

The Java Cryptography Architecture 1.2 and later support X.509 certificates. A DSA algorithm with 1024-bit key length is implemented in a default provider. Moreover, Java supports keystore, an in-memory collection of keys and certificates (http://java.sun.com/j2se/1.4.2/docs/api/java/ security/KeyStore.html). In this article, we've implemented X.509 authentication according to the CEN ENV 13729 Standard. Although authentication protocols appear simple, the choice of a protocol is important, because protocol steps may interfere with some auxiliary relations satisfied by symmetric or asymmetric cryptosystems.

DDJ



Listing One (a)
Certificate             ::= SIGNED {SEQUENCE{
            version                  [0]     Version DEFAULT v1,
            serialNumber                     CertificateSerialNumber,
            signature                        AlgorithmIdentifier,
            issuer                                           Name,
            validity                         Validity,
            subject                                          name,
            subjectPublicKeyInfo             SubjectPublicKeyInfo,
            issuerUniqueIdentifier   [1]     IMPLICIT UniqueIdentifier OPTIONAL,
            subjectUniqueIdentifier  [2]     IMPLICIT UniqueIdentifier OPTIONAL,
            extensions               [3]     Extensions OPTIONAL       }}

Validity                                     ::=             SEQUENCE {
            notBefore                        Time,
            notAfter                         Time
}

(b)
Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension

Extension  ::=  SEQUENCE  {
      extnId        OBJECT IDENTIFIER,
      critical      BOOLEAN DEFAULT FALSE,
      extnValue     OCTET STRING
        -- DER coded value
  }
Back to article


Listing Two
SubjectPublicKeyInfo    ::=  SEQUENCE {
    Algorithm       AlgorithmIdentifier,
    SubjectPublicKey    BIT STRING
     }
AlgorithmIdentifier    : :=  SEQUENCE {
    Algorithm       OBJECT IDENTIFIER,
    Parameters      ANY DEFINED BY algorithm OPTIONAL 
     }
Back to article


Listing Three
    PrivateKeyInfo  ::= SEQUENCE {
        Version     Version,
    PrivateKeyAlgorithm     PrivateAlgorithmIdentifier,
    PrivateKey          PrivateKey,
    Attributes      [0] IMPLICIT Attributes OPTIONAL        
}
    Version         ::=   INTEGER
    PrivateKeyAlgorithm ::=   AlgorithmIdentifier
    PrivateKey          ::=   OCTET STRING
    Attributes          ::=    SET OF Attribute
Back to article


Listing Four
      X509CertInfo certinfo = new X509CertInfo();
      CertificateVersion cv = new CertificateVersion(CertificateVersion.V3); 
         ...   etc
      certinfo.set(certinfo.VERSION,cv);
       ... etc
      X509CertImpl cert = new X509CertImpl(certinfo);
Back to article


Listing Five (a)
Magic number (big-endian integer),
Version of this file format (big-endian integer),
Count (big-endian integer),
followed by "count" instances of either:
    {
     tag=1 (big-endian integer),
     alias (UTF string)
     timestamp
     encrypted private-key info according to PKCS #8
        (integer length followed by encoding)
    cert chain (integer count, then certs; for each cert,
         integer length followed by encoding)
    }

(b)
    {
     tag=2 (big-endian integer)
     alias (UTF string)
     timestamp
     cert (integer length followed by encoding)
    }
ended by a keyed SHA1 hash (bytes only) of
    { password + whitener + preceding body }
Back to article