The Java Cryptographic Engine – short JCE – is a concept to simply supply developers with cryptographic services. The concept includes several interfaces which shall be implemented via SPI classes. A SPI class implements a specific cryptographic service and is then registered to a Provider. Providers cryptographic or non-cryptographic are registered static- or dynamically to the system and can be used by everyone who needs their functionality. Within this chapter we give you some information about the basic concepts of the JCE where detailed information can be found at www.oracle.com.
Provider
A provider can be seen as a kind of container offering different services. Each of its services is registered to the provider before or after the provider is registered to the system. During system registration the provider receives a priority number starting by 1 signaling highest priority. This priority is necessary when someone requests a service not indicating from what provider it shall come from. The JCE then seeks for the service and – assuming more than one provider would offer that service – returns the one from the provider with the highest priority.
Service
A Service is an implementation of a SPI class offering a specific algorihm. Services can be registered before the containing provider is registered to the system or at any time later. Furthermore a Service can be de-registered at any time.
SPI
The JCE describes several SPI classes containing pre-defined functions. These functions are specific for the class-type and shall be implemented by the extending class implementing the specific algorithm. The JCE distinguishs between the following class types there are even more SPI classes – within this document we only focus the ones we implemented:
- Cipher
- Signature
- MessageDigest
- KeyGenerator
- KeyPairGenerator
- SecureRandom
- KeyStore
Each SPI class offers static functions in order to request a specific algorithm. Triggering this request is done provider specific or even anonym when it is not important where the service shall come from. The following example shows three common variants how to receive e.g. a cipher object implementing the RSA algorithm:
//get RSA cipher from any provider who implements it
//
//in fact the service will come from the provider implementing it
//having highest priority
Cipher c = Cipher.getInstance("RSA");
//get RSA cipher from "myProvider"-provider
Cipher c = Cipher.getInstance("RSA", "myProvider");
Provider xy = null;
//xy is retrieved somewhere
…
//get RSA cipher from provider-instance xy
Cipher c = Cipher.getInstance("RSA", xy);
The last two examples do exactly the same. They use a specific provider – once identified by the provider's name, once identified by the instance – in order to get the RSA algorithm from it.
getInstance is supported by each SPI class and is always used for receiving algorithms. When the algorithm can not be found at any provider / is unsupported by the provider an exception is thrown.