JavaTM Cryptography Architecture(JCA)
API Specification & Reference
for the JavaTM 2 SDK, v 6.0
Last Modified: 20th November 2007
Copyright information
Note: Before using this information and the product it supports, be sure to read the general information under Notices.
(c) Copyright Sun Microsystems, Inc. 1998, 2005, 901 San Antonio Rd., Palo Alto, CA 94303 USA. All rights reserved.
(c) Copyright International Business Machines Corporation, 1998, 2007. All rights reserved.
U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- Introduction
-
- Design Principles
-
- Architecture
-
- Concepts
-
- What's New in JCE in IBM SDK for Java 6
-
- Core Classes and Interfaces
-
- The
Provider Class
-
- How Provider Implementations are Requested and Supplied
-
- Installing Providers
-
- The
Security Class
-
- The
MessageDigest Class
-
- The
Signature Class
-
- Algorithm Parameters Classes
-
- Algorithm Parameter Specification Interfaces and Classes
-
- The
AlgorithmParameterSpec Interface
-
- The
DSAParameterSpec Class
-
- The
AlgorithmParameters Class
-
- The
AlgorithmParameterGenerator Class
-
Key Interfaces
-
Key Specification Interfaces and Classes
-
- The
KeySpec Interface
-
- The
DSAPrivateKeySpec Class
-
-
The DSAPublicKeySpec Class -
-
The RSAPrivateKeySpec Class -
-
The RSAPrivateCrtKeySpec Class -
-
The RSAMultiPrimePrivateCrtKeySpec Class -
-
The RSAPublicKeySpec Class -
-
The EncodedKeySpec Class
-
- The
PKCS8EncodedKeySpec Class
-
-
The X509EncodedKeySpec Class
-
- The
KeyFactory Class
-
-
The CertificateFactory Class -
-
The KeyPair Class -
- The
KeyPairGenerator Class
-
- Key Management
-
- Keystore Location
-
-
Keystore Implementation -
-
The KeyStore Class
-
- The
SecureRandom Class
-
- The
Cipher Class
-
- The
CipherStream Class
-
- The
CipherInputStream Class
-
- The
CipherOutputStream Class
-
- The
KeyGenerator Class
-
- The
SecretKeyFactory Class
-
- The
SealedObject Class
-
- The
KeyAgreement Class
-
- The
Mac Class
-
- How to Make Applications "Exempt" from Cryptographic Restrictions
-
- Code Examples
-
- Computing a
MessageDigest Object
-
- Generating a Pair of Keys
-
- Generating and Verifying a Signature Using Generated Keys
-
- Generating/Verifying Signatures Using
Key Specifications and KeyFactory
-
- Determining If Two Keys Are Equal
-
- Reading Base64-Encoded Certificates
-
- Parsing a Certificate Reply
- Using Encryption
- Using Password-Based Encryption
- Using Key Agreement
-
- Appendix A: Standard Names
-
- Appendix B: Algorithms
-
- Appendix C: IBMJCE Keysize Restrictions
-
- Appendix D: Jurisdiction Policy File Format
-
- Appendix E: Maximum Key Sizes Allowed by "Strong" Jurisdiction Policy Files
-
- Notices
The Security API is a core API of the Java programming language, built around the java.security package (and its subpackages). This API is designed to allow developers to incorporate both low-level and high-level security functionality into their programs.
The first release of Security API in JDK 1.1 introduced the "Java Cryptography Architecture" (JCA), a framework for accessing and developing cryptographic functionality for the Java platform. In JDK 1.1, the JCA included APIs for digital signatures and message digests.
In subsequent releases, the Java 2 SDK significantly extended the Java Cryptography Architecture, as described in this document. It also upgraded the certificate management infrastructure to support X.509 v3 certificates, and introduced a new Java Security Architecture for fine-grain, highly configurable, flexible, and extensible access control.
The Java Cryptography Architecture encompasses the parts of the Java 2 SDK Security API related to cryptography, as well as a set of conventions and specifications provided in this document. It includes a "provider" architecture that allows for multiple and interoperable cryptography implementations.
The Java Cryptography Extension (JCE) extends the JCA API to include APIs for encryption, key exchange, and Message Authentication Code (MAC). Together, the JCE and the cryptography aspects of the SDK provide a complete, platform-independent cryptography API. JCE was previously an optional package (extension) to the Java 2 SDK, Standard Edition, versions 1.2.x and 1.3.x. JCE has now been integrated into the Java 2 SDK, v 1.4.
This document is both a high-level description and a specification of the Java Cryptography Architecture API and its default providers, as included in the Java 2 SDK v 1.6. See the JCE API User Guide for information about the IBM JCE provider. See the "Java Security Architecture Specification" for information about the Java Security Architecture aspects of the Security API.
The Java Cryptography Architecture (JCA) was designed around these principles:
- Implementation independence and interoperability
- Algorithm independence and extensibility
Implementation independence and algorithm independence are complementary; you can use cryptographic services, such as digital signatures and message digests, without worrying about the implementation details or even the algorithms that form the basis for these concepts. When complete algorithm-independence is not possible, the JCA provides standardized, algorithm-specific APIs. When implementation-independence is not desirable, the JCA lets developers indicate a specific implementation.
Algorithm independence is achieved by defining types of cryptographic "engines" (services), and defining classes that provide the functionality of these cryptographic engines. These classes are called engine classes, and examples are the MessageDigest, Signature, KeyFactory, and KeyPairGenerator classes.
Implementation independence is achieved using a "provider"-based architecture. The term Cryptographic Service Provider (used interchangeably with "provider" in this document) refers to a package or set of packages that implement one or more cryptographic services, such as digital signature algorithms, message digest algorithms, and key conversion services. A program can simply request a particular type of object (such as a Signature object) that is implementing a particular service (such as the DSA signature algorithm) and get an implementation from one of the installed providers. If desired, a program can instead request an implementation from a specific provider. Providers can be updated transparently to the application, for example when faster or more secure versions are available.
Implementation interoperability means that various implementations can work with each other, use each other's keys, or verify each other's signatures. This interoperability would mean, for example, that for the same algorithms, a key generated by one provider would be usable by another, and a signature generated by one provider would be verifiable by another.
Algorithm extensibility means that new algorithms that fit in one of the supported engine classes can be added easily.
The Java Cryptography Architecture introduced the notion of a Cryptographic Service Provider. This term refers to a package (or a set of packages) that supplies a concrete implementation of a subset of the cryptography aspects of the Security API.
For example, in JDK 1.1 a provider could contain an implementation of one or more digital signature algorithms, message digest algorithms, and key generation algorithms. Java 2 SDK adds five additional types of services: key factories, keystore creation and management, algorithm parameter management, algorithm parameter generation, and certificate factories. It also enables a provider to supply a random number generation (RNG) algorithm. Previously, RNGs were not provider-based; a particular algorithm was hard-coded in the JDK.
As previously noted, a program can simply request a particular type of object (such as a Signature object) for a particular service (such as the DSA signature algorithm) and get an implementation from one of the installed providers. Alternatively, the program can request the objects from a specific provider. (Each provider has a name used to refer to it.)
Previous versions of the Java runtime environment (1.2.x and 1.3.x) came with a default provider, named SUN. The 1.4 environment has replaced this provider with a number of new providers, including IBMJCE. The IBMJCE provider package includes:
- An implementation of the Digital Signature Algorithm (DSA), described in NIST
FIPS 186-2.
- An implementation of the MD2, MD5 (
RFC 1321), SHA-1 ( FIPS 180-2), SHA-256, SHA-384, SHA-512 message digest algorithms.
- A DSA key pair generator for generating a pair of public and private keys suitable for the DSA algorithm.
- A DSA algorithm parameter generator.
- A DSA algorithm parameter manager.
- A DSA key factory providing bidirectional conversions between (opaque) DSA private and public key objects and their underlying key material.
- An implementation of the proprietary "IBMSecureRandom" random number generation algorithm.
- A keystore implementation for the proprietary keystore type named
JKS.
Each SDK installation has one or more provider packages installed. New providers can be added statically or dynamically (see the Provider and Security classes). The Java Cryptography Architecture offers a set of APIs that allow users to query which providers are installed and what services they support.
Clients can configure their runtime with different providers, and specify a preference order for each of them. The preference order is the order in which providers are searched for requested services when no specific provider is requested.
A database called a "keystore" can be used to manage a repository of keys and certificates. A keystore is available to applications that need it for authentication or signing purposes.
Applications can access a keystore via an implementation of the KeyStore class, which is in the java.security package. A default KeyStore implementation, called "JKS", is provided. It implements the keystore as a file, using a proprietary keystore type (format).
Applications can choose different types of keystore implementations from different providers, using the getInstance factory method supplied in the KeyStore class.
See the Key Management section for more information.
Several concepts are introduced in the API.
An engine class defines a cryptographic service in an abstract fashion (without a concrete implementation).
A cryptographic service is always associated with a particular algorithm or type, and it either provides cryptographic operations (such as those for digital signatures or message digests), generates or supplies the cryptographic material (keys or parameters) required for cryptographic operations, or generates data objects (keystores or certificates) that encapsulate cryptographic keys (that can be used in a cryptographic operation) in a secure fashion. For example, two of the engine classes are the Signature and KeyFactory classes. The Signature class provides access to the functionality of a digital signature algorithm. A DSA KeyFactory supplies a DSA private or public key (from its encoding or transparent specification) in a format usable by the initSign or initVerify methods, respectively, of a DSA Signature object.
The Java Cryptography Architecture encompasses the classes of the Java 2 SDK Security package related to cryptography, including the engine classes. Users of the API request and use instances of the engine classes to carry out corresponding operations. The following engine classes are defined in the Java 2 SDK:
MessageDigest: used to calculate the message digest (hash) of specified data.
Signature: used to sign data and verify digital signatures.
KeyPairGenerator: used to generate a pair of public and private keys suitable for a specified algorithm.
KeyFactory: used to convert opaque cryptographic keys of type Key into key specifications (transparent representations of the underlying key material), and vice versa.
CertificateFactory: used to create public key certificates and Certificate Revocation Lists (CRLs).
KeyStore: used to create and manage a keystore. A keystore is a database of keys. Private keys in a keystore have a certificate chain associated with them, that authenticates the corresponding public key. A keystore also contains certificates from trusted entities.
AlgorithmParameters: used to manage the parameters for a particular algorithm, including parameter encoding and decoding.
AlgorithmParameterGenerator: used to generate a set of parameters suitable for a specified algorithm.
SecureRandom: used to generate random or pseudo-random numbers.
In the 1.4 release of the Java 2 SDK, the following new engines were added and the services are provided by the IBMCertPath provider:
 CertPathBuilder: used to build certificate chains (also known as certification paths).
 CertPathValidator: used to validate certificate chains.
 CertStore: used to retrieve Certificate objects and CRL objects from a repository.
Note: A generator creates objects with brand-new contents, whereas a factory creates objects from existing material (for example, an encoding).
An engine class provides the interface to the functionality of a specific type of cryptographic service (independent of a particular cryptographic algorithm). It defines Application Programming Interface (API) methods that allow applications to access the specific type of cryptographic service it provides. The actual implementations (from one or more providers) are those for specific algorithms. The Signature engine class, for example, provides access to the functionality of a digital signature algorithm. The actual implementation supplied in a SignatureSpi subclass would be that for a specific kind of signature algorithm, such as SHA-1 with DSA, SHA-1 with RSA, or MD5 with RSA. The application interfaces supplied by an engine class are implemented in terms of a Service Provider Interface (SPI). That is, for each engine class, there is a corresponding abstract SPI class, which defines the SPI methods that cryptographic service providers must implement.
An instance of an engine class, the API object, encapsulates (as a private field) an instance of the corresponding SPI class, the SPI object. All API methods of an API object are declared final and their implementations invoke the corresponding SPI methods of the encapsulated SPI object. An instance of an engine class (and of its corresponding SPI class) is created by a call to the getInstance factory method of the engine class.
The name of each SPI class is the same as that of the corresponding engine class, followed by Spi. For example, the SPI class corresponding to the Signature engine class is the SignatureSpi class.
Each SPI class is abstract. To supply the implementation of a particular type of service, for a specific algorithm, a provider must subclass the corresponding SPI class and provide implementations for all the abstract methods.
Another example of an engine class is the MessageDigest class, which provides access to a message digest algorithm. Its implementations, in MessageDigestSpi subclasses, can be those of various message digest algorithms such as SHA-1, MD5, or MD2.
As a final example, the KeyFactory engine class supports the conversion from opaque keys to transparent key specifications, and vice versa. (See the Key Specification Interfaces and Classes section.) The KeyFactorySpi subclass supplies an actual implementation for a specific type of key, for example, DSA public and private keys.
Implementations and Providers
Implementations for various cryptographic services are provided by JCA Cryptographic Service Providers. Cryptographic service providers are essentially packages that supply one or more cryptographic service implementations. The Engine Classes and Algorithms section includes a list of some of the implemenations supplied by IBMJCE.
Other providers might define their own implementations of these services or of other services.
Using Factory Methods to Obtain Implementation Instances
For each engine class in the API, a particular implementation is requested and instantiated by calling a factory method on the engine class. A factory method is a static method that returns an instance of a class.
The basic mechanism for obtaining an appropriate Signature object, for example, is as follows: A user requests such an object by calling the getInstance method in the Signature class, specifying the name of a signature algorithm (such as "SHA1withDSA"), and, optionally, the name of the provider or the Provider class. The getInstance method finds an implementation that satisfies the supplied algorithm and provider parameters. If no provider is specified, getInstance searches the registered providers, in preference order, for one with an implementation of the specified algorithm. See The Provider Class for more information about registering providers.
Here are the differences in JCE between v5.0 and IBM SDK for Java 6:
CTS is described in Bruce Schneier's book "Applied Cryptography-Second Edition", John Wiley & Sons, 1996 (pg. 195-196), and is used by some Kerberos implementations.
This padding for block ciphers is described in 5.2 Block Encryption Algorithms in the W3C's "XML Encryption Syntax and Processing" document.
Constructs secret keys using the Password-Based Key Derivation Function function found in PKCS5 v2.0.
These classes enable secure communications via IETF RFC 2246 "Transport Layer Security" (TLS) protocols.
The core classes and interfaces provided in the Java Cryptography Architecture are as follows:
- The
Provider and Security classes
- The
MessageDigest, Signature, KeyPairGenerator, KeyFactory, AlgorithmParameters, AlgorithmParameterGenerator, CertificateFactory, KeyStore, SecureRandom,  CertPathBuilder,  CertPathValidator, and  CertStore engine classes
- The
Key interfaces and classes
- The Algorithm Parameter Specification interfaces and classes and the Key Specification interfaces and classes
This section shows the signatures of the main methods in each class and interface. Examples for some of these classes (MessageDigest, Signature, KeyPairGenerator, SecureRandom, KeyFactory, and key specification classes) are supplied in the corresponding Examples sections. The complete reference documentation for the relevant Security API packages can be found in:
A Provider is a package or set of packages that supplies a concrete implementation of a subset of the Java 2 SDK Security API cryptography features. The Provider class is the interface to such a package or set of packages. It has methods for accessing the provider name, version number, and other information. In addition to registering implementations of cryptographic services, the Provider class can also be used to register implementations of other security services that might get defined as part of the Java 2 SDK Security API or one of its extensions.
To supply implementations of cryptographic services, an entity (such as a development group) writes the implementation code and creates a subclass of the Provider class. The constructor of the Provider subclass sets the values of various properties; the Java 2 SDK Security API uses these values to look up the services that the provider implements. In other words, the subclass specifies the names of the classes that are implementing the services.
There are several types of services that can be implemented by provider packages; for more information, see Engine Classes and Algorithms.
The different implementations might have different characteristics. Some might be software-based, while others might be hardware-based. Some migth be platform-independent, while others might be platform-specific. Some provider source code might be available for review and evaluation, while some might not. The Java Cryptography Architecture (JCA) lets both end-users and developers decide what their needs are.
Note: For information about implementing a provider, see the guide How To Implement a Provider for the Java Cryptography Architecture.
For each engine class in the API, a particular implementation is requested and instantiated by calling a getInstance method on the engine class and by specifying the name of the desired algorithm and, optionally, the name of the provider (or the Provider class) whose implementation is desired. If no provider is specified, getInstance searches the registered providers for an implementation of the requested cryptographic service associated with the named algorithm. In any given Java Virtual Machine (JVM), providers are installed in a given preference order, the order in which the provider list is searched if a specific provider is not requested. For example, suppose there are two providers installed in a JVM, PROVIDER_1 and PROVIDER_2. Assume that:
PROVIDER_1 implements SHA1withDSA, SHA-1, MD5, DES, and DES3.
PROVIDER_1 has preference order 1 (the highest priority).
PROVIDER_2 implements SHA1withDSA, MD5withRSA, MD2withRSA, MD2, MD5, RC4, RC5, DES, and RSA.
PROVIDER_2 has preference order 2.
Now let's look at three scenarios:
- If we are looking for an MD5 implementation, both providers supply such an implementation. The
PROVIDER_1 implementation is returned because PROVIDER_1 has the highest priority and is searched first.
- If we are looking for an MD5withRSA signature algorithm,
PROVIDER_1 is first searched for it. No implementation is found, so PROVIDER_2 is searched. An implementation is found and returned.
- Suppose we are looking for a SHA1withRSA signature algorithm. Because no installed provider implements it, a
NoSuchAlgorithmException is thrown.
The getInstance methods that include a provider argument are for developers who want to specify which provider they want an algorithm from. A federal agency, for example, will want to use a provider implementation that has received federal certification. Let's assume that the SHA1withDSA implementation from PROVIDER_1 has not received such certification, while the DSA implementation of PROVIDER_2 has received it.
A federal agency program would then have the following call, specifying PROVIDER_2 since it has the certified implementation:
Signature dsa = Signature.getInstance("SHA1withDSA", "PROVIDER_2");
In this case, if PROVIDER_2 was not installed, a NoSuchProviderException would be thrown, even if another installed provider implements the algorithm requested.
A program also has the option of getting a list of all the installed providers (using the getProviders method in the Security class) and choosing one from the list.
There are two parts to installing a provider:
- Installing the provider package classes,
- Configuring the provider.
Installing the Provider Classes
There are two possible ways to install the provider classes:
- Place a zip or JAR file containing the classes anywhere in your classpath.
- Supply your provider JAR file as an "installed" or "bundled" extension. For more information on how to deploy an extension, see
How is an extension deployed?.
Configuring the Provider
The next step is to add the provider to your list of approved providers. This step can be done statically by editing the java.security file in the lib/security directory of the SDK; therefore, if the SDK is installed in a directory called j2sdk1.2, the file would be j2sdk1.2/lib/security/java.security. One of the types of properties you can set in java.security has the following form:
security.provider.n=masterClassName
This property declares a provider, and specifies its preference order n. The preference order is the order in which providers are searched for requested algorithms (when no specific provider is requested). The order is 1-based: 1 is the most preferred, followed by 2, and so on.
The masterClassName must specify the provider's master class. The provider's documentation will specify its master class. This class is always a subclass of the Provider class. The subclass constructor sets the values of various properties that are required for the Java Cryptography API to look up the algorithms or other facilities that the provider implements.
Suppose that the master class is COM.acme.provider.Acme, and that you would like to configure Acme as your third preferred provider. To do so, you would add the following line to the java.security file:
security.provider.3=COM.acme.provider.Acme
Providers can also be registered dynamically. To do so, call either the addProvider or insertProviderAt method in the Security class. This type of registration is not persistent and can be done only by "trusted" programs. See Security.
Provider Class Methods
Each Provider class instance has a (currently case-sensitive) name, a version number, and a string description of the provider and its services. You can query the Provider instance for this information by calling the following methods:
public String getName() public double getVersion() public String getInfo()
The Security class manages installed providers and security-wide properties. It contains only static methods and is never instantiated. The methods for adding or removing providers, and for setting Security properties, can be executed only by a trusted program. Currently, a "trusted program" is either
- A local application not running under a security manager, or
- An applet or application with permission to execute the specified method (see below).
To determine if code is considered trusted to perform an attempted action (such as adding a provider), the applet must be granted permission for that particular action. For example, in the Policy reference implementation, the policy configuration files for a SDK installation specify what permissions (which types of system resource accesses) are allowed by code from specified code sources. (See below and the "Default Policy Implementation and Policy File Syntax" and "Java Security Architecture Specification" files for more information.)
Code being executed is always considered to come from a particular "code source." The code source includes not only the location (URL) where the applet originated from, but also a reference to the public key(s_ corresponding to the private key(s) that is used to sign the code. Public keys in a code source are referenced by (symbolic) alias names from the user's keystore .
In a policy configuration file, a code source is represented by two components: a code base (URL) and an alias name (preceded by signedBy), where the alias name identifies the keystore entry containing the public key that must be used to verify the code's signature.
Each "grant" statement in such a file grants to a specified code source a set of permissions, specifying which actions are allowed.
Here is a sample policy configuration file:
grant codeBase "file:/home/sysadmin/", signedBy "sysadmin" { permission java.security.SecurityPermission "insertProvider.*"; permission java.security.SecurityPermission "removeProvider.*"; permission java.security.SecurityPermission "putProviderProperty.*"; };
This configuration file specifies that only code loaded from a signed JAR file from the /home/sysadmin/ directory on the local file system can add or remove providers or set provider properties. (Note that the signature of the JAR file can be verified using the public key referenced by the alias name sysadmin in the user's keystore.) Either component of the code source (or both) can be missing. Here's an example of a configuration file where codeBase is missing:
grant signedBy "sysadmin" { permission java.security.SecurityPermission "insertProvider.*"; permission java.security.SecurityPermission "removeProvider.*"; };
If this policy is in effect, code that comes in a JAR File signed by sysadmin can add or remove providers--regardless of where the JAR File originated. Here's an example without a signer:
grant codeBase "file:/home/sysadmin/" { permission java.security.SecurityPermission "insertProvider.*"; permission java.security.SecurityPermission "removeProvider.*"; };
In this case, code that comes from anywhere within the /home/sysadmin/ directory on the local filesystem can add or remove providers. The code does not need to be signed. An example where neither codeBase nor signedBy is included is:
grant { permission java.security.SecurityPermission "insertProvider.*"; permission java.security.SecurityPermission "removeProvider.*"; };
Here, with both code source components missing, any code (regardless of where it originates, or whether or not it is signed, or who signed it) can add or remove providers. Managing Providers
The following tables summarize the methods in the Security class that you can use to query which providers are installed, and to install or remove providers at runtime.
|
Quering Providers
|
| Method |
Description |
static Provider[] getProviders() |
Returns an array containing all the installed providers (technically, the Provider subclass for each package provider). The order of the Provider in the array is their preference order. |
static Provider getProvider (String providerName) |
Returns the Provider named providerName. It returns null if the Provider is not found. |
|
Adding Providers
|
| Method |
Description |
static int addProvider(Provider provider)
|
Adds a Provider to the end of the list of installed Providers. It returns the preference position in which the Provider was added, or -1 if the Provider was not added because it was already installed. |
static int insertProviderAt (Provider provider, int position) |
Adds a new Provider at a specified position. If the given provider is installed at the requested position, the provider formerly at that position and all providers with a position greater than position are shifted up one position (towards the end of the list). This method returns the preference position in which the Provider was added, or -1 if the Provider was not added because it was already installed.
|
|
Removing Providers
|
| Method |
Description |
static void removeProvider(String name) |
Removes the Provider with the specified name. It returns silently if the provider is not installed. When the specified provider is removed, all providers located at a position greater than where the specified provider was located are shifted down one position (towards the head of the list of installed providers). |
Note: If you want to change the preference position of a provider, you must first remove it, and then insert it back in at the new preference position.
Security Properties
The Security class maintains a list of system-wide security properties. These properties are accessible and ca be set by a trusted program using the following methods:
static String getProperty(String key) static void setProperty(String key, String datum)
The MessageDigest class is an engine class designed to provide the functionality of cryptographically secure message digests such as SHA-1 or MD5. A cryptographically secure message digest takes arbitrary-sized input (a byte array), and generates a fixed-size output, called a digest or hash. A digest has two properties:
- It should be computationally infeasible to find two messages that hashed to the same value.
- The digest should not reveal anything about the input that was used to generate it.
Message digests are used to produce unique and reliable identifiers of data. They are sometimes called the "digital fingerprints" of data.
Creating a MessageDigest Object
The first step for computing a digest is to create a message digest instance. As with all engine classes, the way to get a MessageDigest object for a particular type of message digest algorithm is to call the getInstance static factory method on the MessageDigest class:
static MessageDigest getInstance(String algorithm)
Note: The algorithm name is not case-sensitive. For example, all the following calls are equivalent: MessageDigest.getInstance("SHA-1") MessageDigest.getInstance("sha-1") MessageDigest.getInstance("sHa-1")
A caller might optionally specify the name of a provider or a Provider instance, which guarantees that the implementation of the algorithm requested is from the specified provider:
static MessageDigest getInstance(String algorithm, String provider) static MessageDigest getInstance(String algorithm, Provider provider)
A call to getInstance returns an initialized message digest object. It therefore does not need further initialization.
Updating a Message Digest Object
The next step for calculating the digest of some data is to supply the data to the initialized message digest object. This step is done by calling one of the update methods:
void update(byte input) void update(byte[] input) void update(byte[] input, int offset, int len)
Computing the Digest
After the data has been supplied by calls to update methods, the digest is computed using a call to one of the digest methods:
byte[] digest() byte[] digest(byte[] input) int digest(byte[] buf, int offset, int len)
The first two methods return the computed digest. The latter method stores the computed digest in the provided buffer buf, starting at offset. len is the number of bytes in buf allotted for the digest. The method returns the number of bytes actually stored in buf.
A call to the digest method that takes an input byte array argument is equivalent to making a call to the following method with the specified input, followed by a call to the digest method without any arguments:
void update(byte[] input)
See the Examples section for more details.
The Signature class is an engine class designed to provide the functionality of a cryptographic digital signature algorithm such as DSA or RSA with MD5. A cryptographically secure signature algorithm takes arbitrary-sized input and a private key and generates a relatively short (often fixed-size) string of bytes, called the signature, with the following properties:
- Given the public key corresponding to the private key used to generate the signature, it should be possible to verify the authenticity and integrity of the input.
- The signature and the public key do not reveal anything about the private key.
A Signature object can be used to sign data. It can also be used to verify whether or not an alleged signature is in fact the authentic signature of the data associated with it. See the Examples section for an example of signing and verifying data.
Signature Object States
Signature objects are modal objects which means that a Signature object is always in a given state, where it can do only one type of operation. States are represented as final integer constants defined in their respective classes. The three states a Signature object can have are:
UNINITIALIZED
SIGN
VERIFY
When it is first created, a Signature object is in the UNINITIALIZED state. The Signature class defines two initialization methods, initSign and initVerify, which change the state to SIGN and VERIFY, respectively.
Creating a Signature Object
The first step for signing or verifying a signature is to create a Signature instance. As with all engine classes, the way to get a Signature object for a particular type of signature algorithm is to call the getInstance static factory method on the Signature class: static Signature getInstance(String algorithm)
Note: The algorithm name is not case-sensitive.
A caller can optionally specify the name of a provider or the Provider class, which will guarantee that the implementation of the algorithm requested is from the named provider:
static Signature getInstance(String algorithm, String provider) static Signature getInstance(String algorithm, Provider provider)
Initializing a Signature Object
A Signature object must be initialized before it is used. The initialization method depends on whether the object is going to be used for signing or for verification.
If it is going to be used for signing, the object must first be initialized with the private key of the entity whose signature is going to be generated. This initialization is done by calling the method:
final void initSign(PrivateKey privateKey)
This method puts the Signature object in the SIGN state. If instead the Signature object is going to be used for verification, it must first be initialized with the public key of the entity whose signature is going to be verified. This initialization is done by calling either of these methods:
final void initVerify(PublicKey publicKey)
final void initVerify(Certificate certificate)
This method puts the Signature object in the VERIFY state.
Signing
If the Signature object has been initialized for signing (if it is in the SIGN state), the data to be signed can then be supplied to the object by making one or more calls to one of the update methods:
final void update(byte b) final void update(byte[] data) final void update(byte[] data, int off, int len)
Calls to the update methods should be made until all the data to be signed has been supplied to the Signature object.
To generate the signature, simply call one of the sign methods:
final byte[] sign() final int sign(byte[] outbuf, int offset, int len)
The first method returns the signature result in a byte array. The second stores the signature result in the provided buffer outbuf, starting at offset. len is the number of bytes in outbuf allotted for the signature. The method returns the number of bytes actually stored.
Signature encoding is algorithm specific. See Appendix B for more information about the use of ASN.1 encoding in the Java Cryptography Architecture.
A call to a sign method resets the signature object to the state it was in when it was previously initialized for signing using a call to initSign. That is, the object is reset and available to generate another signature with the same private key, if desired, using new calls to update and sign.
Alternatively, a new call can be made to initSign specifying a different private key or to initVerify (to initialize the Signature object to verify a signature).
Verifying
If the Signature object has been initialized for verification (if it is in the VERIFY state), it can then verify if an alleged signature is in fact the authentic signature of the data associated with it. To start the process, the data to be verified (as opposed to the signature itself) is supplied to the object. The data is passed to the object by calling one of the update methods:
final void update(byte b) final void update(byte[] data) final void update(byte[] data, int off, int len)
Calls to the update methods should be made until all the data to be verified has been supplied to the Signature object. The signature can now be verified by calling one of the verify methods:
final boolean verify(byte[] signature)
final boolean verify(byte[] signature, int offset, int length)
The argument must be a byte array containing the signature. The argument must be a byte array containing the signature. This byte array would hold the signature bytes that were returned by a previous call to one of the sign methods.
The verify method returns a boolean indicating whether or not the encoded signature is the authentic signature of the data supplied to the update methods.
A call to the verify method resets the signature object to its state when it was initialized for verification using a call to initVerify. That is, the object is reset and available to verify another signature from the identity whose public key was specified in the call to initVerify.
Alternatively, a new call can be made to initVerify specifying a different public key (to initialize the Signature object for verifying a signature from a different entity), or to initSign (to initialize the Signature object for generating a signature).
An algorithm parameter specification is a transparent representation of the sets of parameters used with an algorithm.
A transparent representation of a set of parameters means that you can access each parameter value in the set individually. You can access these values through one of the get methods defined in the corresponding specification class (for example, DSAParameterSpec defines getP, getQ, and getG methods, to access p, q, and g, respectively).
In contrast, the AlgorithmParameters class supplies an opaque representation, in which you have no direct access to the parameter fields. You can get only the name of the algorithm associated with the parameter set (using getAlgorithm) and some kind of encoding for the parameter set (using getEncoded).
The algorithm parameter specification interfaces and classes in the java.security.spec package are described in the following sections.
AlgorithmParameterSpec is an interface to a transparent specification of cryptographic parameters. This interface contains no methods or constants. Its only purpose is to group (and provide type safety for) all parameter specifications. All parameter specifications must implement this interface.
This class (which implements the AlgorithmParameterSpec interface) specifies the set of parameters used with the DSA algorithm. It has the following methods: BigInteger getP() BigInteger getQ() BigInteger getG()
These methods return the DSA algorithm parameters: the prime p, the sub-prime q, and the base g.
The AlgorithmParameters class is an engine class that provides an opaque representation of cryptographic parameters. An opaque representation is one in which you have no direct access to the parameter fields; you can get only the name of the algorithm associated with the parameter set and some kind of encoding for the parameter set. This method is in contrast to a transparent representation of parameters, in which you can access each value individually, through one of the get methods defined in the corresponding specification class. Note that you can call the AlgorithmParameters getParameterSpec method to convert an AlgorithmParameters object to a transparent specification (see the following section).
Creating an AlgorithmParameters Object
As with all engine classes, the way to get an AlgorithmParameters object for a particular type of algorithm is to call the getInstance static factory method on the AlgorithmParameters class:
static AlgorithmParameters getInstance(String algorithm)
Note: The algorithm name is not case-sensitive.
A caller can optionally specify the name of a provider or the Provider class, which will guarantee that the algorithm parameter implementation requested is from the named provider: static AlgorithmParameters getInstance(String algorithm, String provider) static AlgorithmParameters getInstance(String algorithm, Provider provider)
Initializing an AlgorithmParameters Object
After an AlgorithmParameters object is instantiated, it must be initialized using a call to init, with an appropriate parameter specification or parameter encoding:
void init(AlgorithmParameterSpec paramSpec) void init(byte[] params) void init(byte[] params, String format)
In these init methods, params is an array containing the encoded parameters, and format is the name of the decoding format. In the init method with a params argument but no format argument, the primary decoding format for parameters is used. The primary decoding format is ASN.1, if an ASN.1 specification for the parameters exists.
Note: AlgorithmParameters objects can be initialized only once. They are not reusable.
Obtaining the Encoded Parameters
A byte encoding of the parameters represented in an AlgorithmParameters object can be obtained using a call to getEncoded:
byte[] getEncoded()
This method returns the parameters in their primary encoding format. The primary encoding format for parameters is ASN.1, if an ASN.1 specification for this type of parameters exists. If you want the parameters returned in a specified encoding format, use
byte[] getEncoded(String format)
If format is null, the primary encoding format for parameters is used, as in the other getEncoded method.
Note: In most AlgorithmParameters implementations, supplied by the "IBMJCE" provider, the format argument is currently ignored.
Converting an AlgorithmParameters Object to a Transparent Specification
A transparent parameter specification for the algorithm parameters can be obtained from an AlgorithmParameters object using a call to getParameterSpec:
AlgorithmParameterSpec getParameterSpec(Class paramSpec)
paramSpec identifies the specification class in which the parameters should be returned. The specification class could be, for example, DSAParameterSpec.class to indicate that the parameters should be returned in an instance of the DSAParameterSpec class. (This class is in the java.security.spec package.)
The AlgorithmParameterGenerator class is an engine class used to generate a set of parameters suitable for a certain algorithm (the algorithm specified when an AlgorithmParameterGenerator instance is created). Creating an AlgorithmParameterGenerator Object
As with all engine classes, the way to get an AlgorithmParameterGenerator object for a particular type of algorithm is to call the getInstance static factory method on the AlgorithmParameterGenerator class:
static AlgorithmParameterGenerator getInstance( String algorithm)
Note: The algorithm name is not case-sensitive.
A caller can optionally specify the name of a provider or the Provider class, which will guarantee that the algorithm parameter generator implementation is from the named provider:
static AlgorithmParameterGenerator getInstance( String algorithm, String provider)
static AlgorithmParameterGenerator getInstance( String algorithm, Provider provider)
Initializing an AlgorithmParameterGenerator Object
The AlgorithmParameterGenerator object can be initialized in two different ways: an algorithm-independent manner or an algorithm-specific manner.
The algorithm-independent approach uses the fact that all parameter generators share the concept of a "size" and a source of randomness. The measure of size is universally shared by all algorithm parameters, though it is interpreted differently for different algorithms. For example, in the case of parameters for the DSA algorithm, "size" corresponds to the size of the prime modulus, in bits. (See Appendix B: Algorithms for information about the sizes for specific algorithms.) When using this approach, algorithm-specific parameter generation values--if any--default to some standard values. One init method that takes these two universally shared types of arguments:
void init(int size, SecureRandom random);
Another init method takes only a size argument and uses a system-provided source of randomness: void init(int size)
A third approach initializes a parameter generator object using algorithm-specific semantics, which are represented by a set of algorithm-specific parameter generation values supplied in an AlgorithmParameterSpec object:
void init(AlgorithmParameterSpec genParamSpec, SecureRandom random)
void init(AlgorithmParameterSpec genParamSpec)
To generate Diffie-Hellman system parameters, for example, the parameter generation values usually consist of the size of the prime modulus and the size of the random exponent, both specified in number of bits. (The Diffie-Hellman algorithm has been part of the JCE since JCE 1.2.)
Generating Algorithm Parameters
After you have created and initialized an AlgorithmParameterGenerator object, you can use the generateParameters method to generate the algorithm parameters: AlgorithmParameters generateParameters()
The Key interface is the top-level interface for all opaque keys. It defines the functionality shared by all opaque key objects.
An opaque key representation is one in which you have no direct access to the key material that constitutes a key. In other words, "opaque" gives you limited access to the key--just the three methods defined by the Key interface: getAlgorithm, getFormat, and getEncoded. This is in contrast to a transparent representation, in which you can access each key material value individually, through one of the get methods defined in the corresponding specification class.
All opaque keys have three characteristics:
- An Algorithm
- The key algorithm for that key. The key algorithm is usually an encryption or asymmetric operation algorithm (such as DSA or RSA), which will work with those algorithms and with related algorithms (such as MD5 with RSA, SHA-1 with RSA, and so on.) The name of the algorithm of a key is obtained using this method:
String getAlgorithm()
- An Encoded Form
- The external encoded form for the key used when a standard representation of the key is needed outside the Java Virtual Machine, as when transmitting the key to some other party. The key is encoded according to a standard format (such as X.509 or
PKCS #8), and is returned using the method:
byte[] getEncoded()
- A Format
- The name of the format of the encoded key. It is returned by the method:
String getFormat()
Keys are generally obtained through key generators, certificates, key specifications (using a KeyFactory), or a KeyStore implementation accessing a keystore database used to manage keys. It is possible to parse encoded keys, in an algorithm-dependent manner, using a KeyFactory.
It is also possible to parse certificates, using a CertificateFactory.
The interfaces that extend the Key interface in the java.security and javax.crypto packages are:
The PublicKey and PrivateKey Interfaces
The PublicKey and PrivateKey interfaces (which both extend the Key interface) are methodless interfaces, used for type-safety and type-identification.
Key specifications are transparent representations of the key material that constitutes a key. If the key is stored on a hardware device, its specification might contain information that helps identify the key on the device.
A transparent representation of keys means that you can access each key material value individually, through one of the get methods defined in the corresponding specification class. For example, DSAPrivateKeySpec defines getX, getP, getQ, and getG methods, to access the private key x, and the DSA algorithm parameters used to calculate the key: the prime p, the sub-prime q, and the base g.
This representation is contrasted with an opaque representation, as defined by the Key interface, in which you have no direct access to the key material fields. In other words, an "opaque" representation gives you limited access to the key--just the three methods defined by the Key interface: getAlgorithm, getFormat, and getEncoded.
A key can be specified in an algorithm-specific way or in an algorithm-independent encoding format (such as ASN.1). For example, a DSA private key can be specified by its components x, p, q, and g (see DSAPrivateKeySpec), or it may be specified using its DER encoding (see PKCS8EncodedKeySpec).
The key specification interfaces and classes in the java.security.spec package are:
This interface contains no methods or constants. Its only purpose is to group and provide type safety for all key specifications. All key specifications must implement this interface.
This class (which implements the KeySpec interface) specifies a DSA private key with its associated parameters. DSAPrivateKeySpec has the following methods: BigInteger getX() BigInteger getP() BigInteger getQ() BigInteger getG()
These methods return the private key x, and the DSA algorithm parameters used to calculate the key: the prime p, the sub-prime q, and the base g.
This class (which implements the KeySpec interface) specifies a DSA public key with its associated parameters. DSAPublicKeySpec has the following methods: BigInteger getY() BigInteger getP() BigInteger getQ() BigInteger getG()
These methods return the public key y, and the DSA algorithm parameters used to calculate the key: the prime p, the sub-prime q, and the base g.
This class (which implements the KeySpec interface) specifies an RSA private key. RSAPrivateKeySpec has the following methods: BigInteger getModulus() BigInteger getPrivateExponent()
These methods return the RSA modulus n and private exponent d values that constitute the RSA private key.
This class (which extends the RSAPrivateKeySpec class) specifies an RSA private key, as defined in the PKCS #1 standard, using the Chinese Remainder Theorem (CRT) information values. RSAPrivateCrtKeySpec has the following methods (in addition to the methods inherited from its superclass RSAPrivateKeySpec): BigInteger getPublicExponent() BigInteger getPrimeP() BigInteger getPrimeQ() BigInteger getPrimeExponentP() BigInteger getPrimeExponentQ() BigInteger getCrtCoefficient()
These methods return the public exponent e and the CRT information integers: the prime factor p of the modulus n, the prime factor q of n, the exponent d mod (p-1), the exponent d mod (q-1), and the Chinese Remainder Theorem coefficient (inverse of q) mod p. An RSA private key logically consists of only the modulus and the private exponent. The presence of the CRT values is intended for efficiency.
This class (which extends the RSAPrivateKeySpec class) specifies an RSA multi-prime private key, as defined in the PKCS #1 v2.1, using the Chinese Remainder Theorem (CRT) information values. RSAMultiPrimePrivateCrtKeySpec has the following methods (in addition to the methods inherited from its superclass RSAPrivateKeySpec): BigInteger getPublicExponent() BigInteger getPrimeP() BigInteger getPrimeQ() BigInteger getPrimeExponentP() BigInteger getPrimeExponentQ() BigInteger getCrtCoefficient() RSAOtherPrimeInfo[] getOtherPrimeInfo()
These methods return the public exponent e and the CRT information integers: the prime factor p of the modulus n, the prime factor q of n, the exponent d mod (p-1), the exponent d mod (q-1), and the Chinese Remainder Theorem coefficient (inverse of q) mod p. Method getOtherPrimeInfo returns a copy of the otherPrimeInfo (defined in PKCS #1 v 2.1) or null if there are only two prime factors (p and q).
An RSA private key logically consists of only the modulus and the private exponent. The presence of the CRT values is intended for efficiency.
This class (which implements the KeySpec interface) specifies an RSA public key. RSAPublicKeySpec has the following methods: BigInteger getModulus() BigInteger getPublicExponent()
These methods return the RSA modulus n and public exponent e values that constitute the RSA public key.
This abstract class (which implements the KeySpec interface) represents a public or private key in encoded format. Its getEncoded method returns the encoded key: abstract byte[] getEncoded();
and its getFormat method returns the name of the encoding format: abstract String getFormat();
See the next sections for the concrete implementations PKCS8EncodedKeySpec and X509EncodedKeySpec.
This class, which is a subclass of EncodedKeySpec, represents the DER encoding of a private key, according to the format specified in the PKCS #8 standard. Its getEncoded method returns the key bytes, encoded according to the PKCS #8 standard. Its getFormat method returns the string "PKCS#8".
This class, which is a subclass of EncodedKeySpec, represents the DER encoding of a public key, according to the format specified in the X.509 standard. Its getEncoded method returns the key bytes, encoded according to the X.509 standard. Its getFormat method returns the string "X.509".
The KeyFactory class is an engine class designed to provide conversions between opaque cryptographic keys (of type Key) and key specifications (transparent representations of the underlying key material). Key factories are bidirectional. They allow you to build an opaque key object from a given key specification (key material), or to retrieve the underlying key material of a key object in a suitable format.
Multiple compatible key specifications can exist for the same key. For example, a DSA public key can be specified by its components y, p, q, and g (see DSAPublicKeySpec), or it can be specified using its DER encoding according to the X.509 standard (see X509EncodedKeySpec).
A key factory can be used to translate between compatible key specifications. Key parsing can be achieved through translation between compatible key specifications, for example, when you translate from X509EncodedKeySpec to DSAPublicKeySpec, you basically parse the encoded key into its components. For an example, see the end of the Generating/Verifying Signatures Using Key Specifications and KeyFactory section.
Creating a Ke |