The Java Cryptography Architecture is split into two different packages, part lies within the JDK, while the other lies within the Java Cryptology Extension. Sun had to split the architecture due to US export laws which prohibits software encryption technology from being released outside of the United States or Canada (certain types of cryptographic software are considered "weapons" by the U.S. government).
Cryptography in Java was first released in JDK 1.1. It included APIs for digital signatures and message digests (hash), but was limited compared to what the platform offers today. The JDK 1.2 added security APIs that relate to cryptography, and also the Java Cryptography Extension, a separate extension with encryption, key exchange, message digest and authentication. The JCE was released separately in accordance with the United States export laws.
Cryptography in the JDK
The JDK 1.2 includes the following service classes:
- Signature Used to sign and verify digital signatures.
- Message Digest Used to calculate the message digest (hash) of specified data.
- KeyPairGenerator Generate a pair of public and private keys suitable for a specific algorithm
- KeyFactory Converts cryptographic keys of type 'key' into key specifications.
- AlgorithmParameterGenerator Generates parameters for a particular algorithm.
- AlgorithmParameters Manages the parameters for a particular algorithm
- KeyStore Used to create and manage a key store.
- CertificateFactory Defines the functionality of a certificate factory, used to generate certificate and CRL objects from their encodings.
- SecureRandom Generates pseudo random numbers.
These service classes provide an interface to the functionality of a specific service or Cryptographic Security Provider by defining the APIs that allow access. The Application Interfaces supplied by a service class are implemented in terms of a SPI (Service Provider Interface). For each service class there is an abstract SPI class that defines the SPI methods which a specific cryptography service provider must implement.
The Java Cryptography Extension
The JCE removes users from the implementation of cryptography, and the algorithms involved, making both easy to use. A programmer can specify algorithms, or the JCE architecture will choose the default algorithms. The JCE uses a provider based architecture, based on using Cryptographic Security Providers (CSPs). An application that uses an object that needs a specific CSP service or algorithm will run through the installed providers, and choose the first default provider with an appropriate service. Alternately programmers can choose specific providers for specific services.
The original JCE extension included the following packages:
Includes classes and interfaces for various cryptographic operations.
Includes interfaces for Diffie-Hellman keys.
Holds classes and interfaces for key specifications and algorithm parameter specifications.
Recently, the JCE 1.2.1 was released Sun. The primary difference between JCE 1.2 and JCE 1.2.1 is that JCE 1.2.1 is exportable outside the U.S. and Canada due to mechanisms it implements to ensure that only qualified providers can be plugged into the framework. It does this by using added jurisdiction policy files, which are transparent, do not cause any API changes, and differentiate between U.S. and other country specific laws. JCE 1.2.1 also includes more support for key wrapping, key usage and control. Added are functions to retrieve key sizes, which are necessary to enforce the jurisdiction policies, and the
, which allow applets and applications to use higher strength cryptography than the default based on the jurisdiction policy files.
Random numbers are crucial to cryptography. They are used to create cryptographic keys and to encrypt or sign data.
Java has had historic difficulty generating random numbers. Most random number generators are hardware dependent, or require specialized hardware. Java, by principle, is hardware independent, and so uses pseudorandom number generators.
Pseudorandom numbers are numbers that are actually generated by a deterministic procedure, and so are not truly random, but the procedure makes any relationship among the numbers unnoticeable by most applications. Linear congruential method is the default method set for Java's two built in random number generators:
. Both are effective pseudorandom number generation methods. Linear congruential method needs an integer seed, which is a number selected at random by some external means (like the timing of keyboard strikes, or the system clock). Pseudorandom numbers are then generated from the seed using an algorithm using extremely large numbers. These large numbers are multiplied by an appropriate factor that will produce numbers in the range desired.
Random uses a 48 bit seed. The user can construct a Random object and assign it a seed either on the constructor or by using the setSeed method. If a seed isn't assigned, Random turns to the system clock.
SecureRandom was added in JDK 1.1 because the simple
class could be easy to crack, especially if the system clock was being used as the seed, and the time the application was run is known. Even if the class is provided a different seed, it isn't considered truly random or secure.
class uses the system clock,
uses thread timing as its default seed. This is based around a message digest that uses the Secure Hash Algorithm (SHA-1) developed by the National Institute of Standards and Technology in conjunction with the National Security Agency (some critics argue that, since SHA was developed in conjunction with the NSA, that the NSA have quick and easy ways to crack it).
To use SecureRandom, you create a SecureRandom instance and call its
SecureRandom random = new SecureRandom(); byte pseudoRandom = new byte [numberofbyteshere]; random.nextBytes(pseudoRandom); SecureRandom can also be set to use a specific provider: SecureRandom random = SecureRandom.getInstance("specificalgorythmproviderhere"); random.setSeed(seed);
Cryptographic Security Providers (CSPs)
Added in JCE 1.1, CSPs were included to provide keyfactories, keystore creation and management, algorithm parameter management, algorithm parameter generation, certificate factories, and random number generators (RNGs). Sun includes a default provider, "SUN". Provider lists allow programmers to specify the algorithms used for cryptography, or alternately, the provider list has a preference order, and an object searching for a specific provider for an algorithm will simply run down the list until it finds one that is suitable.
This allows providers to be assigned statically or dynamically. The user can install the provider classes by placing a ZIP JAR file containing the classes anywhere on CLASS PATH, or supply the provider JAR file as an installed or bundled extension. The user can add providers dynamically by using addProvider, but only with a program or applet that is considered trusted. The java security properties file can also be edited. Providers are stored in the following format:
The variable n is equal to the provider preference order. When searching for a service with no specified provider, the search order is determined by this value, starting with
, and counting upwards. The masterClassName specifies the provider MasterClass, which should be in the provider documentation.
Sun lists several compatible cryptographic service providers:
- RSA Data Security Inc.
- eSec Limited (formally Australian Business Access )
- Forge Research
- Entrust Technologies
It is also relatively easy to program your own default provider, which will be discussed in part two of this series.
References and Resources
- Inside Java 2 Platform Security, Li Gong, Addison Wesley, 1999
- Introduction to Algorithms A Creative Approach, Udi Manber, Addison Wesley Publishing Company, 1989
- Java Cryptology, Jonathon Knudsen, O'reily and Associates, 1998
- Java Security Handbook, Jamie Jaworski and Paul Perrone, SAMS Publishing, 2000
About the AuthorThomas Gutschmidt is a freelance writer, in Bellevue, Wash., who also works for Widevine Technologies.