Java Cryptography Architecture (JCA)


In J2SE, the JCA provides the Java platform with cryptographic services and algorithms to secure messages. JCA defines a notion of provider implementation and a generic API framework for accessing cryptographic services and implementing related functionalities. JCA is also designed to provide algorithm and implementation independence via a standardized API framework and provider implementation.

Figure 4-2 illustrates the JCA and its cryptographic services.

Figure 4-2. JCA architectural model and its cryptographic services


JCA Cryptographic Services

JCA provides support for various cryptographic algorithms by defining the types and functionalities of cryptographic services. The cryptographic services include support for message digests and digital signatures. JCA also ensures interoperability among the provider implementations using a standardized set of APIs, which implements those required cryptographic algorithms and services. For example, using the same algorithms, a key generated by one provider can be usable by another provider; likewise, a digital signature generated by one provider can be verified using another provider.

Let's take a closer look at the JCA provider architecture, its core API classes, and its programming model.

JCA Cryptographic Service Provider

JCA introduces the notion of a Cryptographic Service Provider, which is an API package containing a set of packages that implements cryptographic services. A JCA provider package can contain one or more digital signature algorithms, message digest algorithms, and key generation algorithms, as well as services related to keys and keystore creation and management, certificate management, and algorithm parameter generation and management.

As part of the J2SE bundle, the JCA framework includes a default provider implementation named SUN, which provides the following features:

  • Implementation of Digital Signature Algorithm (DSA) and Message Digest Algorithms (MD5 and SHA1)

  • DSA key pair generator for generating public and private keys based on DSA

  • DSA algorithm parameter generator and manager

  • DSA key factory to provide conversations between public and private keys

  • Certificate path builder and validator for X.509 certificates

  • Certificate factory for X.509 certificates and revocation lists

  • Keystore implementation named JKS, which allows managing a repository of keys and certificates

JCA Classes and Interfaces

In J2SE, the JCA framework provides the core classes and interfaces of the Java platform security package related to cryptography. It exists as part of java.security package.

JCA Provider Classes

The JCA API provides a specific set of Java security APIs that allow interacting with the cryptographic services of the provider.

  • Provider (java.security.Provider): This class represents a cryptographic service provider that implements some or all parts of Java cryptographic functions such as Algorithms (such as DSA, RSA, MD5, or SHA-1), key generation, conversion, and management. It also contains methods for registering other security services and accessing the provider name, version, and other provider-specific information. The types of services implemented by the provider are represented using an Engine class.

  • Security (java.security.Security): This class manages all installed providers and security properties. It provides static methods for adding providers, removing providers, and setting and maintaining security properties. These methods can only be executed by a trusted application. The J2SE security policy configuration file (i.e., security.policy) specifies the security properties of the trusted application.

Example 4-1 shows a JCA code fragment for retrieving the list of available cryptographic service providers.

Example 4-1. Listing available cryptographic service providers
Provider[] csps = Security.getProviders(); for (int i=0; i < csps.length, i++) {    System.out.println (csps[i].getName()); } 

JCA Engine Classes

The JCA also defines a set of engine classes. An engine class represents a cryptographic service associated with a particular algorithm and provides interfaces to the functionality of the service. The application interfaces provided by an engine class are implemented as Service Provider Interfaces (SPIs). For each engine API class, JCA has a corresponding SPI class for which the cryptographic service provider must provide an implementation. Let's take a look at some of the most important engine classes.

  • MessageDigest (java.security.MessageDigest): Defines the functionality of using a message digest algorithm such as MD5 or SHA. Message digests are secure one-way hash functions that take arbitrary-sized data and output a fixed-length hash value.

  • Signature (java.security.Signature): Defines the functionality of using a digital signature algorithm. Digital signatures are mainly used for authentication validation and integrity assurance of digital data.

  • KeyPairGenerator (java.security.KeyPairGenerator): Defines the functionality for generating pairs of public and private keys for a chosen algorithm.

  • KeyFactory (java.security.KeyFactory): Defines the functionality for converting opaque cryptographic keys into key specifications, and vice-versa.

  • CertificateFactory (java.security.cert.CertificateFactory): Defines the functionality for generating certificates along with certification path (CertPath) and certificate revocation list (CRL) objects.

  • KeyStore (java.security.KeyStore): Defines the functionality for creating and managing a keystore. A keystore represents an in-memory collection of keys and certificates. It stores them as key and certificate entries.

  • AlgorithmParameters (java.security.AlgorithmParameters): Used to manage the parameters of a particular algorithm, which includes its encoding and decoding.

  • AlgorithmParameterGenerator (java.security.AlgorithmParameterGenerator): Defines the functionality for generating a set of parameters suitable for a specified algorithm.

  • SecureRandom (java.security.SecureRandom): Defines the functionality for generating cryptographically strong random or pseudo-random numbers.

Now, let's take a look at the programming model for some of these classes.

Understanding JCA API Programming Model

JCA provides flexible API mechanisms to install one or more JCA provider implementations. This allows for the use of a variety of cryptographic services and algorithms provided by different vendor implementations. For example, to get the cryptographic service provider that implements a specified algorithm, the getInstance() method is used. The service providers can be used independently or in combination with one another to achieve the required level of cryptographic security. JCA also provides API mechanisms to support the JCA providercryptographic operations such as computing message digests, generating key pairs, and generating and verifying digital signatures. Let's take a closer look at the supported cryptographic operations and how to use those APIs.

Message Digests

Message digest is a one-way secure hash function. Its computed values are referred to as message digests or hash values and act as fingerprints of messages. The message digest values are computationally impossible to reverse and thus protect the original message from being derived.

As a cryptographic technique, message digests are applied for preserving the secrecy of messages, files, and objects. In conjunction with digital signature, message digests are used to support integrity, authentication, and non-repudiation of messages during transmission or storage. Message digest functions are publicly available and use no keys. In J2SE, the JCA provider supports two message digest algorithms: Message Digest 5 (MD5) and secure hash algorithm (SHA-1). MD5 produces a 128-bit (16-byte) hash and SHA-1 produces a 160-bit message digest value.

Computing a Message Digest Object

Message digests are represented using the Engine class java.security.MessageDigest as byte arrays. The MessageDigest.getInstance(algorithm) creates an instance of a message digest object implementing the given algorithm, if this algorithm is available with the provider. The MessageDigest.update method updates the digest using the data specified as byte array and the MessageDigest.digest method computes the hash value and returns a byte array.

Example 4-2 would compute a message digest with MD5.

Example 4-2. Computing a message digest using MD5
 try {       MessageDigest md5 = MessageDigest.getInstance("MD5");       byte[] testdata = { 1,2,3,4,5 };       md5.update(testdata);       byte []  myhash =  md5.digest();       } catch (NoSuchAlgorithmException e) {     } 

Example 4-3 computes a message digest with SHA-1.

Example 4-3. Computing a message digest using SHA-1
try {       MessageDigest sha = MessageDigest.getInstance("SHA-1");       byte[] testdata = { 1,2,3,4,5 };       sha.update(testdata);       byte []  myhash =  sha.digest();       } catch (NoSuchAlgorithmException e) {     } 

Key Pair Generation

Generating key pairs and securely distributing them is one of the major challenges in implementing cryptographic security. JCA provides the ability to generate key pairs using digital signature algorithms such as DSA, RSA, and Diffie-Hellman. JCA also supports using random number algorithms to add a high degree of randomness, which makes it computationally difficult to predict and determine the generated values.

The key is represented using the java.security.Key interface, which provides three methods: getAlgorithm() for obtaining the associated key algorithm, getEncoded() for returning the key as a byte array in its primary encoded format, and getFormat() for returning the format in which the key is encoded. The key interface is extended by PrivateKey and PublicKey interfaces that are used to identify the private and public keys as key pairs representing asymmetric algorithms.

The java.security.KeyPairGenerator is an abstract class that provides the functionality for creating both public and private key pairs using public key algorithms.

  • To generate a public/private key pair, use the KeyPairGenerator.getInstance (algorithm) to create an instance of the KeyPairGenerator object implementing the given algorithm:

    KeyPairGenerator kpg            = KeyPairGenerator.getInstance("DSA"); 

  • Use the KeyPairGenerator.initialize(bitSize) method to initialize the key generator specifying the size of the key in bits (for DSA, the size should be between 512 and 1024 with a multiple of 64) and to securely randomize the key generation in an unpredictable fashion:

    kpg.initialize(1024); 

  • To generate the key pair, use KeyPairGenerator.genKeyPair() to create the KeyPair object. To obtain the private and public keys, use the KeyPair.getPrivate() and KeyPair.getPublic() methods, respectively.

Example 4-4 is a code fragment showing generation of a key pair for public/private key algorithms such as "DSA" and "DH".

Example 4-4. Key pair generation using DSA and DH algorithms
    try {         //1024-bit Digital Signature Algorithm(DSA) key pairs         KeyPairGenerator keyGen                 = KeyPairGenerator.getInstance("DSA");         keyGen.initialize(1024);         KeyPair keypair = keyGen.genKeyPair();         PrivateKey privateKey = keypair.getPrivate();         PublicKey publicKey = keypair.getPublic();         //576-bit DiffieHellman key pair         keyGen = KeyPairGenerator.getInstance("DH");         keyGen.initialize(576);         keypair = keyGen.genKeyPair();         privateKey = keypair.getPrivate();         publicKey = keypair.getPublic();         } catch (java.security.NoSuchAlgorithmException e) {        } 

Digital Signature Generation

A digital signature is computed using public-key cryptographic techniques. The sender signs a message using a private key and the receiver decodes the message using the public key. This allows the receiver to verify the source or signer of the message and guarantee its integrity and authenticity.

The java.security.Signature class provides the functionalities for digitally signing and verifying a message during its transmission or its storage.

To generate a signature object, Signature.getInstance(algorithm) creates an instance of the Signature object implementing the given algorithm. To sign the message, the Signature.initSign(key) method is used with a private key as an input, Signature.update (message) updates the message to be signed using the specified byte array, and finally, Signature.sign() finishes the operation resulting in the signature bytes.

Example 4-5 shows how to apply a signature to a message using a private key.

Example 4-5. Applying digital signature using a private key
try {        byte[] testdata = { 1,2,3,4,5 };        Signature dsig             = Signature.getInstance(privateKey.getAlgorithm());        dsig.initSign(privateKey);        dsig.update(testdata);        byte[] signedData = dsig.sign();         } catch (SignatureException e) {           } catch (InvalidKeyException e) {            } catch (NoSuchAlgorithmException e) {     } 

To verify a digital signature object using a public key, use the Signature.getInstance(algorithm), which creates an instance of Signature implementing the algorithm, if such an algorithm is available with the provider. To verify the message, the Signature.initVerify(key) method is used with a public key as an input, Signature.update(message) takes the signed message to be verified using the specified byte array, and finally, Signature.verify(signature) takes the signature as a byte array for verification and results in a boolean value indicating success or failure. The signature verification will be successful only if the signature corresponds to the message and its public key.

Example 4-6 shows how to verify a digital signature on a message using a public key.

Example 4-6. Verifying digital signature using a public key
      try {        Signature dsig          = Signature.getInstance(myPublicKey.getAlgorithm());        dsig.initVerify(publicKey);        dsig.update(signedData);        boolean result = dsig.verify(signatureToVerify);      } catch (SignatureException e) {      } catch (InvalidKeyException e) {      } catch (NoSuchAlgorithmException e) {      } 

So far we have looked at JCA and the use of standard-based cryptographic services. Now, let's explore Java Cryptographic Extensions (JCE), an enhancement to JCA that has additional features and capabilities.




Core Security Patterns. Best Practices and Strategies for J2EE, Web Services, and Identity Management
Core Security Patterns: Best Practices and Strategies for J2EE, Web Services, and Identity Management
ISBN: 0131463071
EAN: 2147483647
Year: 2005
Pages: 204

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net