JDK 1.1 introduced the notion of a
Cryptographic Service Provider, or
"provider" for short. This term refers to
a package (or a set of packages) that supply
a concrete implementation of a subset of the cryptography aspects of
the JDK Security API.
In JDK 1.1 a provider could,
for example, 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.
A program wishing to use cryptography functionality
may simply request a particular type of object
(such as a Signature object) implementing a particular
service (such as the DSA signature algorithm) and get
an implementation from one of
the installed providers. If an implementation from a
particular provider is desired, the program can request
that provider by name, along with the service desired.
Each SDK installation has one or more provider packages installed.
Clients may configure their runtimes 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
algorithms when no particular provider is requested.
This document is intended for experienced programmers
wishing to create their own provider packages supplying cryptographic
service implementations. It documents what you need to do in order
to integrate your provider into Java 2 SDK Security so that
your algorithms and other services can be found when SDK
Security API clients request them.
Programmers that only need to use the SDK Security API to
access existing cryptography algorithms and other services
do not need to read this document.
It also discusses various classes and interfaces in the
Java 2 Security API. The complete reference documentation for
the relevant Security API packages can be found in:
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
(like 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 (which 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 utilize
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.
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, which authenticates
the corresponding public key.
A keystore also contains certificates from trusted entities.
CertificateFactory - used to
create public key certificates and Certificate Revocation Lists (CRLs).
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.
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 (see next paragraph) would be that
for a specific kind of signature
algorithm, such as SHA1 with DSA, SHA1 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 Service Provider
Interface 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, may 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 Key Specification Interfaces and Classes
Required by Key Factories.)
The actual implementation supplied in a KeyFactorySpi subclass
would be that for a specific type of keys, e.g., DSA public
and private keys.
The first thing you need to do is write the code supplying
algorithm-specific implementations of the cryptographic
services you want to support.
In Java 2 SDK, you can supply signature, message digest, key pair
generation, and (pseudo-)random number generation algorithms, as well as
key and certificate factories and keystore creation and
management, algorithm parameter
management, and algorithm parameter generation services.
For each cryptographic service, you need to create a subclass
of the appropriate SPI class: SignatureSpi,
MessageDigestSpi, KeyPairGeneratorSpi, SecureRandomSpi,
AlgorithmParameterGeneratorSpi,
AlgorithmParametersSpi, KeyFactorySpi, CertificateFactorySpi,
or KeyStoreSpi. (See
"Engine Classes and Corresponding SPI Classes".)
ensure there is a public constructor without any arguments. Here's why:
When one of your services is requested, SDK Security looks up
the subclass implementing that service, as specified by
a property in your "master class" (see Step 3).
Java 2 SDK Security then creates the Class object associated with your subclass,
and creates an instance of your subclass by calling the
newInstance method on that Class object.
newInstance requires your subclass to have a public
constructor without any parameters.
A default constructor without arguments will automatically be generated
if your subclass doesn't have any constructors. But if your subclass
defines any constructors, you must explicitly define a public
constructor without arguments.
The third step is to create a subclass of the Provider class.
Your subclass should be a final class, and its
constructor should
call super, specifying the provider name (see
Step 2), version number,
and a string of information about the provider and algorithms it
supports. For example:
super("ACME", 1.0, "ACME provider v1.0, implementing " +
"RSA signing and key generation, SHA-1 and MD5 message digests.");
set the values of various properties that are required
for the Java 2 Security API to look up the cryptographic services
implemented by the provider.
For each service implemented by the provider, there must be a
property whose name is the type of service (Signature, MessageDigest,
KeyPairGenerator, SecureRandom, KeyFactory, KeyStore, CertificateFactory,
AlgorithmParameterGenerator, or
AlgorithmParameters), followed by a period and the name of the
algorithm, certificate type, or keystore type to which the service
applies. The property value must
specify the fully qualified name of the class implementing the service.
The list below
shows the various types of properties that must be defined for
the various types of services, where the actual algorithm
name is substitued for algName, certificate type for
certType, and keystore type for storeType:
Signature.algName
MessageDigest.algName
KeyPairGenerator.algName
SecureRandom.algName
KeyFactory.algName
CertificateFactory.certType
KeyStore.storeType
AlgorithmParameterGenerator.algName
AlgorithmParameters.algName
In each of these, algName, certType , or
storeType is the "standard" name of the
algorithm, certificate type, or keystore type.
(See Appendix A
of the Java Cryptography Architecture API Specification
& Reference for the standard names that
should be used.)
The value of each property must be
the fully qualified name of the class implementing the
specified algorithm, certificate type, or keystore type.
That is, it must be the package name
followed by the class name, where the two are separated by
a period.
As an example, the default provider named "SUN" implements the
Digital Signature Algorithm (whose standard name is "SHA1withDSA")
in a class named DSA
in the sun.security.provider package. Its subclass of
Provider (which is the Sun class in the
sun.security.provider package) sets the
Signature.SHA1withDSA property to have the value
"sun.security.provider.DSA" via the following:
The list below shows more properties that can be defined for the various
types of services, where the actual algorithm name is substitued for
algName, certificate type for certType, keystore type for storeType, and
attribute name for attrName:
Signature.algName [one or more spaces] attrName
MessageDigest.algName [one or more spaces] attrName
KeyPairGenerator.algName [one or more spaces] attrName
SecureRandom.algName [one or more spaces] attrName
KeyFactory.algName [one or more spaces] attrName
CertificateFactory.certType [one or more spaces] attrName
KeyStore.storeType [one or more spaces] attrName
AlgorithmParameterGenerator.algName [one or more spaces] attrName
AlgorithmParameters.algName [one or more spaces] attrName
In each of these, algName, certType, storeType, or attrName is the
"standard"
name of the algorithm, certificate type, keystore type, or attribute.
(See Appendix A of the Java
Cryptography Architecture API Specification &
Reference
for the standard names that should be used.)
For a property in the above format, the value of the property must be
the value for the corresponding attribute.
(See Appendix A of the Java
Cryptography Architecture API Specification & Reference
for the definition of each standard attribute.)
As an example, the default provider named "SUN" implements the
SHA1withDSA Digital Signature Algorithm in software.
In the master class for the provider "SUN", it sets the
"Signature.SHA1withDSA ImplementedIn" to have the value "Software" via
the following:
For further master class property setting examples, see
Appendix A to view the current Java 2 SDK
Sun.java source file. This shows
how the Sun class constructor sets all the properties
for the "SUN" provider.
Note: The Provider subclass can get its information from wherever it
wants. Thus, the information can be hard-wired in, or retrieved at runtime,
e.g., from a file.
After you have created your implementation code
(Step 1), given your provider a name
(Step 2), and created the master class
(Step 3), use the compiler
to compile your files.
In order to prepare for testing your provider, you must
install it in the same manner as will be done by
clients wishing to use it. The installation enables
SDK Security to find your algorithm implementations
when clients request them.
There are two parts to installing a provider: installing the provider
package classes, and configuring the provider.
Installing the Provider Classes
The first thing you must do is
make your classes available so that they can be found when
requested.
You ship your provider classes as a JAR (Java ARchive) or ZIP file.
There are a couple possible ways
of installing the provider classes:
Place a zip or JAR file containing the classes
anywhere on 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?.
Here <java-home> refers to the directory where the
runtime environment was installed. For example, if you have Java 2 SDK
installed on Solaris, you need to edit the following file:
jdk1.3/jre/lib/security/java.security
Similarly, if you have the Java 2 Runtime Environment v1.3 installed
on Solaris, you need to edit this file:
jre1.3/lib/security
For each provider, this file should have a statement
of the following form:
security.provider.n=masterClassName
This 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.
masterClassName must specify the fully qualified
name of the provider's "master
class", which you implemented in Step 3.
This class is always a subclass of the Provider
class.
Whenever the Java 2 SDK is installed, it contains one built-in
(default) provider, the provider referred to as "SUN".
The java.security
file has just the following provider specification:
security.provider.1=sun.security.provider.Sun
(Recall that the "SUN" provider's master class is the
Sun class in the sun.security.provider
package.)
Suppose that your master class is the Acme class in the
COM.acme.provider package,
and that you would like to make your provider the second
preferred provider. To do so, add the following line to the
java.security file below the line for the "SUN"
provider:
security.provider.2=COM.acme.provider.Acme
Note: Providers may also be registered dynamically. To do so,
a program (such as your test program, to be written in
Step 7)
can call either the addProvider or
insertProviderAt method in the Security class.
This type of registration is not persistent and can only be
done by "trusted" programs. See the Security class section of the
Java Cryptography Architecture API Specification and
Reference.
Write and compile one or more test programs that test your provider's
incorporation into the Security API as well as the correctness
of its algorithm(s). Create any supporting files needed,
such as those for test data to be hashed or signed.
The first tests your program should perform are ones
to ensure that your provider is found, and that its name,
version number, and additional information is as expected. To do so,
you could write code like the following, substituting your
provider name for "MyPro":
import java.security.*;
Provider p = Security.getProvider("MyPro");
System.out.println("MyPro provider name is " + p.getName());
System.out.println("MyPro provider version # is " + p.getVersion());
System.out.println("MyPro provider info is " + p.getInfo());
Next, you should ensure that your services are found.
For instance, if you implemented a SHA-1 message digest
algorithm, you could check to ensure it's found when requested by
using the following code (again substituting your
provider name for "MyPro"):
MessageDigest sha = MessageDigest.getInstance("SHA", "MyPro");
System.out.println("My MessageDigest algorithm name is " +
sha.getAlgorithm());
If you don't specify a provider name in the call to
getInstance, all registered providers will be searched, in
preference order (see Configuring the Provider),
until one implementing the algorithm is found.
Run your test program(s). Debug your code and continue testing as
needed. If the Java 2 Security API cannot seem to find one of your
algorithms, review the steps above and ensure they are all
completed.
The next-to-last step is to write documentation for your clients. At the
minimum, you need to specify
the name programs should use to refer to your provider.
Please note: As of this writing, provider name searches are
case-sensitive. That is, if your master class
specifies your provider name as "ACME" but a user requests
"Acme", your provider will not be found. This behavior may
change in the future, but for now be sure to warn your
clients to use the exact case you specify.
the types of algorithms and other services implemented by your provider.
instructions for installing the provider, similar to those provided
in Step 5, except that the information and
examples should be specific to your provider.
In addition, your documentation should specify anything else of
interest to clients, such as any default algorithm parameters.
Message Digests
For each message digest algorithm, tell whether or not
your implementation is cloneable. This is not technically
necessary, but it may save clients some time and coding
by telling them
whether or not intermediate hashes may be possible through
cloning. Clients who do not know whether or not a message
digest implementation is cloneable can find out by attempting
to clone the MessageDigest object and catching the
potential exception, as illustrated by the following example:
try {
// try and clone it
/* compute the hash for i1 */
sha.update(i1);
byte[] i1Hash = sha.clone().digest();
/* compute the hash for i1 and i2 */
sha.update(i2);
byte[] i12Hash = sha.clone().digest();
/* compute the hash for i1, i2 and i3 */
sha.update(i3);
byte[] i123Hash = sha.digest();
} catch (CloneNotSupportedException cnse) {
// have to use an approach not involving cloning
}
where
sha is the message digest object they
received when they requested one via a call to
MessageDigest.getInstance,
i1,
i2 and i3 are input byte arrays, and
they want to calculate separate hashes for:
i1
i1 and i2
i1, i2, and i3
Signature Algorithms
If you implement a signature algorithm, you should
document the format in which the signature (generated by
one of the sign methods) is encoded. For example,
the SHA1withDSA signature algorithm supplied by the "SUN" provider
encodes the signature as a standard ASN.1 SEQUENCE of
two integers, r and s.
Random Number Generation (SecureRandom) Algorithms
For a random number generation algorithm, provide information
regarding how "random" the numbers generated are, and the quality
of the seed when the random number generator is self-seeding. Also note
what happens when a SecureRandom object (and its encapsulated SecureRandomSpi
implementation object) is deserialized:
If subsequent calls to the nextBytes method (which
invokes the engineNextBytes method of the encapsulated
SecureRandomSpi object) of the restored object yield the exact same
(random) bytes as the original object would, then let users know that
if this behaviour is undesirable, they should seed the restored
random object by calling its setSeed method.
Key Pair Generators
For a key pair generator algorithm,
in case the client does not explicitly initialize the key pair generator
(via a call to an initialize method),
each provider must supply and document a default initialization.
For example, the "SUN" provider uses a default modulus size (strength)
of 1024 bits.
Key Factories
A provider should document all the key specifications supported by its
key factory.
Certificate Factories
A provider should document what types of certificates
(and their version numbers, if relevant), can be created
by the factory.
Keystores
A provider should document any relevant information regarding the
keystore implementation, such as its underlying data format.
Algorithm Parameter Generators
In case the client does not explicitly initialize the
algorithm parameter generator (via a call to an init
method in the AlgorithmParameterGenerator engine class),
each provider must supply and document a default initialization.
For example, the "SUN" provider uses a default modulus prime size of 1024
bits for the generation of DSA parameters.
The final step is to make your class files and documentation available to clients in whatever form (.class files, zip files, JAR files, ...) and
methods (web download, floppy, mail, ...) you feel are appropriate.
For many cryptographic algorithms and types, there is a single
official "standard name" defined in
Appendix A
of the Java Cryptography Architecture API Specification
& Reference.
For example, "MD5" is the standard name for the RSA-MD5 Message Digest
algorithm defined by RSA DSI in RFC 1321.
In the Java 2 SDK, there is an aliasing scheme that enables clients to use
aliases when referring to algorithms or types, rather than their standard names.
For example, the "SUN" provider's master class
(Sun.java) defines the alias "SHA1/DSA" for the
algorithm whose
standard name is "SHA1withDSA". Thus, the following statements are equivalent:
Signature sig = Signature.getInstance("SHA1withDSA", "SUN");
Signature sig = Signature.getInstance("SHA1/DSA", "SUN");
Aliases can be defined in your "master class" (see
Step 3). To define an alias, create a property
named
Alg.Alias.engineClassName.aliasName
where engineClassName is the name of an engine
class (e.g., Signature), and
aliasName is your alias name. The value of the property
must be the standard algorithm (or type) name for the algorithm
(or type) being aliased.
As an example, the "SUN" provider
defines the alias "SHA1/DSA" for the signature
algorithm whose standard name is "SHA1withDSA" by setting a property
named Alg.Alias.Signature.SHA1/DSA to have the value
SHA1withDSA via the following:
Currently, aliases defined by the "SUN" provider are available to
all clients, no matter which provider clients request. For example, if
you create a provider named "MyPro" that implements the SHA1withDSA algorithm,
then even if you don't define
any aliases for it, the "SHA1/DSA" alias defined by "SUN" can be used
to refer to your provider's SHA1withDSA implementation as follows:
Signature sig = Signature.getInstance("SHA1/DSA", "MyPro");
WARNING: The aliasing scheme may be changed or eliminated in
future releases.
Some algorithms require the use of other types of algorithms.
For example, a signature algorithm usually needs to use a message
digest algorithm in order to sign and verify data.
If you are implementing one type of algorithm that requires
another, you can do one of the following:
Provide your own implementations for both.
Let your implementation of one algorithm
use an instance of the other type of algorithm, as supplied by the
default "SUN" provider that is included
with every SDK installation. For example, if you
are implementing a signature algorithm that requires a message
digest algorithm, you can obtain an instance of a class
implementing the MD5 message digest algorithm by calling
MessageDigest.getInstance("MD5", "SUN")
Let your implementation of one algorithm
use an instance of the other type of algorithm, as supplied by
another specific provider. This is only appropriate if you are
sure that all clients who will use your provider will also have
the other provider installed.
Let your implementation of one algorithm
use an instance of the other type of algorithm, as supplied by
another (unspecified) provider. That is, you can request an algorithm
by name, but without specifying any particular provider, as in
MessageDigest.getInstance("MD5")
This is only appropriate if you are sure that there will be at
least one implementation of the requested algorithm (in this case,
MD5) installed on each Java platform where
your provider will be used.
Here are some common types of algorithm interdependencies:
Signature and Message Digest Algorithms
A signature algorithm often requires use of a message digest
algorithm. For example, the SHA1withDSA signature algorithm requires
the SHA-1 message digest algorithm.
Signature and (Pseudo-)Random Number Generation Algorithms
A signature algorithm often requires use of a (pseudo-)random number
generation algorithm. For example,
such an algorithm is required in order to generate a DSA signature.
Key Pair Generation and Message Digest Algorithms
A key pair generation algorithm often requires use of a message digest
algorithm. For example, DSA keys are generated using the SHA-1 message digest
algorithm.
Algorithm Parameter Generation and Message Digest Algorithms
An algorithm parameter generator often requires use of a message digest
algorithm. For example, DSA parameters are generated using the
SHA-1 message digest algorithm.
KeyStores and Message Digest Algorithms
A keystore implementation will often utilize a message digest
algorithm to compute keyed hashes (where the "key" is a user-provided
password) to check the integrity of a keystore and make sure that the
keystore has not been tampered with.
Key Pair Generation Algorithms and Algorithm Parameter Generators
A key pair generation algorithm sometimes needs to generate a
new set of algorithm parameters. It can either generate the parameters
directly, or use an algorithm parameter generator.
Key Pair Generation, Algorithm Parameter Generation, and (Pseudo-)Random
Number Generation Algorithms
A key pair generation algorithm may require a source of
randomness in order to generate a new key pair and possibly
a new set of parameters associated with the keys.
That source of randomness is represented by a
SecureRandom object.
The implementation of the key pair generation algorithm
may generate the key parameters itself, or may use an
algorithm parameter generator to generate them, in which
case it may or may not initialize the algorithm parameter
generator with a source of randomness.
Algorithm Parameter Generators and Algorithm Parameters
An algorithm parameter generator's
engineGenerateParameters method must return an
AlgorithmParameters instance.
Signature and Key Pair Generation Algorithms or Key Factories
If you are implementing a signature algorithm, your implementation's
engineInitSign and engineInitVerify methods
will require
passed-in keys that are valid for the underlying algorithm (e.g., DSA
keys for the DSS algorithm). You can do one of the following:
Also create your own classes implementing appropriate
interfaces (e.g. classes implementing the DSAPrivateKey and DSAPublicKey
interfaces from the package java.security.interfaces), and
create your own key pair generator and/or key factory returning
keys of those types.
Require the keys passed to engineInitSign and
engineInitVerify to be the types of keys you have implemented,
that is, keys generated from your key pair generator or key factory.
Or you can
Accept keys from other key pair generators or other key factories,
as long as they are
instances of appropriate interfaces that enable your signature
implementation to obtain the information it needs (such as the private
and public keys and the key parameters). For example, the
engineInitSign method for a DSS Signature class could
accept any private keys that are instances of
java.security.interfaces.DSAPrivateKey.
KeyStores and Key and Certificate Factories
A keystore implementation will often utilize a key factory to
parse the keys stored in the keystore, and a
certificate factory to parse the certificates stored in the
keystore.
In case the client does not explicitly initialize a key pair generator
or an algorithm parameter generator, each provider of such a service must
supply (and document) a default initialization.
For example, the "SUN" provider uses a default modulus size (strength)
of 1024 bits for the generation of DSA parameters.
If you implement a key pair generator, your implementation
should supply default parameters that are used when clients
don't specify parameters. The documentation you supply
(Step 8) should state what the default parameters are.
For example, the DSA key pair generator in the "SUN" provider
supplies a set of pre-computed p, q, and
g default values for the
generation of 512, 768, and 1024-bit key pairs.
The following p, q, and
g values are used as the default values
for the generation of 1024-bit DSA key pairs:
If you implement a signature algorithm, the documentation you supply
(Step 8) should specify the format
in which the signature (generated by one of the sign methods)
is encoded.
For example, the SHA1withDSA signature algorithm supplied by the
"SUN" provider encodes the signature as a standard
ASN.1 sequence of two ASN.1 INTEGER values:
r and s, in that order:
The Java 2 Security API contains the following interfaces
(in the java.security.interfaces package)
for the convenience of programmers implementing DSA services:
This interface is obsolete. It used to be needed to enable
clients to provide DSA-specific parameters
to be used rather than the default parameters your implementation
supplies. However, in Java 2 it is no longer necessary;
a new KeyPairGenerator initialize method that
takes an AlgorithmParameterSpec parameter enables clients to indicate
algorithm-specific parameters.
If you are implementing a DSA key pair generator,
you need a class implementing DSAParams for holding and
returning the p, q, and g
parameters.
A DSAParams implementation is also required if you implement
the DSAPrivateKey and DSAPublicKey interfaces.
DSAPublicKey and DSAPrivateKey both extend the DSAKey
interface, which contains a getParams method
that must return a DSAParams object.
See DSAPrivateKey and DSAPublicKey
Implementations for more information.
Note: there is a DSAParams implementation built into the
SDK: the java.security.spec.DSAParameterSpec class.
If you implement a DSA key pair generator or key factory, you
need to create classes implementing the DSAPrivateKey and
DSAPublicKey interfaces.
If you implement a DSA key pair generator, your
generateKeyPair method (in your
KeyPairGeneratorSpi subclass) will return instances
of your implementations of those interfaces.
If you implement a DSA key factory, your
engineGeneratePrivate method (in your
KeyFactorySpi subclass) will return an instance
of your DSAPrivateKey implementation, and your
engineGeneratePublic method will return an instance
of your DSAPublicKey implementation.
Also, your engineGetKeySpec and
engineTranslateKey methods
will expect the passed-in key to be an instance of
a DSAPrivateKey or DSAPublicKey implementation.
The getParams method provided by the interface
implementations is useful for obtaining and extracting the
parameters from the keys and then using the parameters, for example
as parameters to the DSAParameterSpec constructor
called to create a parameter specification from parameter values
that could be used to initialize a KeyPairGenerator object for DSA.
If you implement a DSA signature algorithm, your
engineInitSign method (in your
SignatureSpi subclass) will expect to be passed a
DSAPrivateKey and your engineInitVerify method
will expect to be passed a DSAPublicKey.
Please note: The DSAPublicKey and DSAPrivateKey interfaces
define a very generic, provider-independent interface to DSA public and
private keys, respectively. The engineGetKeySpec and
engineTranslateKey methods (in your KeyFactorySpi
subclass) could additionally check if the passed-in key is actually
an instance of their provider's own implementation
of DSAPrivateKey or DSAPublicKey, e.g., to take advantage of provider-specific
implementation details. The same is true for the DSA signature algorithm
engineInitSign and engineInitVerify methods (in your
SignatureSpi subclass).
To see what methods need to be implemented by classes that
implement the DSAPublicKey and DSAPrivateKey interfaces, first
note the following interface signatures:
In the java.security.interfaces package:
public interface DSAPrivateKey extends DSAKey,
java.security.PrivateKey
public interface DSAPublicKey extends DSAKey,
java.security.PublicKey
public interface DSAKey
In the java.security package:
public interface PrivateKey extends Key
public interface PublicKey extends Key
public interface Key extends java.io.Serializable
In order to implement the DSAPrivateKey and
DSAPublicKey interfaces, you must implement the methods
they define as well as those defined by interfaces they
extend, directly or indirectly.
Thus, for private keys, you need to supply a class that implements
the getAlgorithm, getEncoded, and
getFormat methods from the
java.security.Key interface, since DSAPrivateKey
extends java.security.PrivateKey, and PrivateKey
extends Key.
Similarly, for public DSA keys, you need to supply a class that
implements
the getAlgorithm, getEncoded, and
getFormat methods from the
java.security.Key interface, since DSAPublicKey
extends java.security.PublicKey, and PublicKey
extends Key.
The Java 2 SDK Security API contains the following interfaces
(in the java.security.interfaces package)
for the convenience of programmers implementing RSA services:
If you implement an RSA key pair generator or
key factory, you need to create classes implementing the RSAPrivateKey
(and/or RSAPrivateCrtKey) and RSAPublicKey interfaces.
(RSAPrivateCrtKey is the interface to an RSA private key, using the
Chinese Remainder Theorem (CRT) representation.)
If you implement an RSA key pair generator, your
generateKeyPair method (in your
KeyPairGeneratorSpi subclass) will return instances
of your implementations of those
interfaces.
If you implement an RSA key factory, your
engineGeneratePrivate method (in your
KeyFactorySpi subclass) will return an instance
of your RSAPrivateKey (or RSAPrivateCrtKey) implementation, and your
engineGeneratePublic method will return an instance
of your RSAPublicKey implementation.
Also, your engineGetKeySpec and
engineTranslateKey methods
will expect the passed-in key to be an instance of
an RSAPrivateKey, RSAPrivateCrtKey, or RSAPublicKey implementation.
If you implement an RSA signature algorithm, your
engineInitSign method (in your
SignatureSpi subclass) will expect to be passed either an
RSAPrivateKey or an RSAPrivateCrtKey,
and your engineInitVerify method
will expect to be passed an RSAPublicKey.
Please note: The RSAPublicKey, RSAPrivateCrtKey, and RSAPrivateKey interfaces
define a very generic, provider-independent interface to RSA public and private
keys. The engineGetKeySpec and
engineTranslateKey methods (in your KeyFactorySpi
subclass) could additionally check if the passed-in key is actually
an instance of their provider's own implementation of RSAPrivateKey,
RSAPrivateCrtKey, or RSAPublicKey, e.g., to take advantage of provider-specific
implementation details. The same is true for the RSA signature algorithm
engineInitSign and engineInitVerify methods (in your
SignatureSpi subclass).
To see what methods need to be implemented by classes that
implement the RSAPublicKey, RSAPrivateCrtKey, and RSAPrivateKey interfaces, first
note the following interface signatures:
In the java.security.interfaces package:
public interface RSAPrivateKey extends java.security.PrivateKey
public interface RSAPrivateCrtKey extends RSAPrivateKey
public interface RSAPublicKey extends java.security.PublicKey
In the java.security package:
public interface PrivateKey extends Key
public interface PublicKey extends Key
public interface Key extends java.io.Serializable
In order to implement the RSAPrivateKey, RSAPrivateCrtKey, and
RSAPublicKey interfaces, you must implement the methods
they define as well as those defined by interfaces they
extend, directly or indirectly.
Thus, for RSA private keys, you need to supply a class that implements
the getModulus and getPrivateExponent
methods from the
RSAPrivateKey interface.
the getAlgorithm, getEncoded, and
getFormat methods from the
java.security.Key interface, since RSAPrivateKey
extends java.security.PrivateKey, and PrivateKey
extends Key.
Similarly, for RSA private keys using the
Chinese Remainder Theorem (CRT) representation,
you need to supply a class that implements
all the methods listed above for RSA private keys, since
RSAPrivateCrtKey extends java.security.interfaces.RSAPrivateKey.
the getPublicExponent, getPrimeP,
getPrimeQ, getPrimeExponentP,
getPrimeExponentQ, and getCrtCoefficient
methods from the
RSAPrivateCrtKey interface.
For public RSA keys, you need to supply a class that
implements
the getModulus and getPublicExponent
methods from the
RSAPublicKey interface.
the getAlgorithm, getEncoded, and
getFormat methods from the
java.security.Key interface, since RSAPublicKey
extends java.security.PublicKey, and PublicKey
extends Key.
As noted above, the Java 2 SDK Security API contains interfaces for the
convenience of programmers implementing DSA and RSA services.
The API does not at this time contain similar
interfaces for any other type of algorithm. Thus, you need
to define your own.
If you are implementing a key pair generator for a different algorithm, you
should create an interface with one or more initialize methods
that clients can call when they want to provide algorithm-specific
parameters to be used rather than the default parameters your
implementation supplies. Your subclass of KeyPairGeneratorSpi should
implement this interface.
For private and public keys for non-DSA and non-RSA algorithms,
there are currently no java.security.interfaces
interfaces corresponding to the DSAPrivateKey and
DSAPublicKey ones for DSA and the RSAPrivateKey, RSAPrivateCrtKey,
and RSAPublicKey ones for RSA. It is
recommended that you create similar interfaces and provide
implementation classes. Your public key interface should extend the
PublicKey interface. Similarly, your
private key interface should extend the
PrivateKey interface.
An algorithm parameter specification is a transparent representation of
the sets of parameters used with an algorithm.
A transparent representation of parameters means that you can access
each value individually, through one of the "get" methods defined
in the corresponding specification class (e.g., DSAParameterSpec
defines getP, getQ, and
getG methods, to access the p, q,
and g parameters, respectively).
This is contrasted with an opaque representation, as supplied by the
AlgorithmParameters engine class, in which
you have no direct access to the key material values;
you can only get the name of the algorithm associated with the
parameter set (via getAlgorithm) and some kind of encoding for the
parameter set (via getEncoded).
If you supply an AlgorithmParametersSpi, AlgorithmParameterGeneratorSpi,
or KeyPairGeneratorSpi implementation, you must utilize the
AlgorithmParameterSpec interface, since each of those classes
contain methods that take an AlgorithmParameterSpec parameter.
Such methods need to determine which actual implementation of
that interface has been passed in, and act accordingly.
The Java 2 SDK contains one AlgorithmParameterSpec implementation, the
DSAParameterSpec class.
If you are working with DSA algorithm
parameters, you can utilize this class. If you are operating on
algorithm parameters that should be for a different type of
algorithm, you will need to supply your own AlgorithmParameterSpec
implementation appropriate for that type of algorithm.
The Java 2 SDK defines the following algorithm parameter specification interfaces and
classes in the java.security.spec package:
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 and
DSAParams interfaces) specifies the set of parameters used with
the DSA algorithm. It has the following methods:
public BigInteger getP()
public BigInteger getQ()
public BigInteger getG()
These methods return the DSA algorithm
parameters: the prime p,
the sub-prime q, and the base g.
Many types of DSA services will find this class useful - for example, it
is utilized by the DSA signature, key pair generator,
algorithm parameter generator, and algorithm parameters classes
implemented by the "SUN" provider. As a specific example, an
algorithm parameters implementation must include an implementation
for the getParameterSpec method, which returns an
AlgorithmParameterSpec. The DSA algorithm parameters implementation
supplied by "SUN" returns an instance of the DSAParameterSpec class.
A key factory provides bi-directional conversions between opaque keys
(of type Key) and key specifications. If you implement a key factory,
you thus need to understand and utilize key specifications. In some
cases, you also need to implement your own key specifications.
Further information about key specifications, the interfaces and
classes supplied in the Java 2 SDK, and key factory requirements with respect
to specifications, is provided below.
Key specifications are transparent representations of the key material
that constitutes a key. If the key is stored on a hardware device, its
specification may 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,
java.security.spec.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 is contrasted with an opaque representation, as defined by the
Key interface, in which you have no direct access to the parameter 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 may be specified in an algorithm-specific way, or in an
algorithm-independent encoding format (such as ASN.1).
For example, a DSA private key may be specified by its components
x, p, q, and g
(see DSAPrivateKeySpec), or it may be
specified using its DER encoding
(see PKCS8EncodedKeySpec).
The Java 2 SDK defines the following key specification interfaces
and classes in the java.security.spec package:
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.
If your provider uses key types (e.g., Your_PublicKey_type and Your_PrivateKey_type)
for which the SDK does not already provide corresponding KeySpec
classes, there are two possible scenarios, one of which requires
that you implement your own key specifications:
If your users will never have to access
specific key material values of your key type, you
will not have to provide any KeySpec classes for your key type.
In this scenario, your users will always create Your_PublicKey_type and
Your_PrivateKey_type keys through the appropriate KeyPairGenerator supplied
by your provider for that key type. If they want to store the generated keys
for later usage, they retrieve the keys' encodings (using the
getEncoded method
of the Key interface). When they want to create an Your_PublicKey_type or
Your_PrivateKey_type key from the encoding (e.g., in order to initialize a
Signature object for signing or verification), they create an instance
of X509EncodedKeySpec or PKCS8EncodedKeySpec from the encoding, and
feed it to the appropriate KeyFactory supplied by your provider for
that algorithm, whose generatePublic and
generatePrivate methods
will return the requested PublicKey (an instance of Your_PublicKey_type) or
PrivateKey (an instance of Your_PrivateKey_type) object, respectively.
If you anticipate a need for users to access specific key material
values of your key type, or to construct a key of your key type from
key material and associated parameter values, rather than from its
encoding (as in the above case), you have to specify new KeySpec
classes (classes that implement the KeySpec interface) with the
appropriate constructor methods and "get" methods for returning key
material fields and associated parameter values for your key type. You
will specify those classes in a similar manner as is done by the
DSAPrivateKeySpec and DSAPublicKeySpec classes provided in the
Java 2 SDK. You need to ship those classes along with your provider classes,
for example, as part of your provider JAR file.
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.
It has the following methods (in addition to the
methods inherited from its superclass RSAPrivateKeySpec):
public BigInteger getPublicExponent()
public BigInteger getPrimeP()
public BigInteger getPrimeQ()
public BigInteger getPrimeExponentP()
public BigInteger getPrimeExponentQ()
public 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 abstract class (which implements the KeySpec
Interface) represents a public or private key in encoded format.
Its getEncoded method returns the encoded key:
public abstract byte[] getEncoded();
and its getFormat method returns the name of the encoding
format:
public abstract String getFormat();
The Java 2 SDK supplies two classes implementing the EncodedKeySpec interface:
PKCS8EncodedKeySpec and
X509EncodedKeySpec.
If desired, you can supply your own EncodedKeySpec implementations
for those or other types of key encodings.
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 or private 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 following information applies to providers who supply an algorithm
that is not listed as one of the standard algorithms in
Appendix A
of the Java Cryptography Architecture API Specification
& Reference.
Mapping from OID to Name
Sometimes the JCA needs to instantiate a cryptographic algorithm
implementation from an algorithm identifier (for example, as encoded in a
certificate), which by definition includes the object identifier (OID)
of the algorithm. For example, in order to verify the signature on an
X.509 certificate, the JCA determines the signature algorithm from the
signature algorithm identifier that is encoded in the certificate,
instantiates a Signature object for that algorithm, and initializes it
for verification.
In order for this to work, you must provide
the object identifier of your algorithm as an alias entry for your
algorithm in your provider master file, in order for the JCA to be
able to find your algorithm.
For example, if your provider implementation resides in the "com.xyz"
package, and your algorithm is of type and is named
"MyAlg" with the object identifier (in string notation)
"1.2.3.4.5.6.7.8", your provider master file should have the following
entries:
If your algorithm is known under more than one object identifier, you
need to create an alias entry for each object identifier under which it
is known.
An example of where the JCA needs to perform this type of mapping is when
your algorithm is a signature algorithm and users run the keytool
-genkey command and specify your (signature) algorithm with
the -sigalg
option. In this case, your provider master file should contain the
following entries:
Other examples of where this type of mapping is performed are (1) when your
algorithm is a keytype algorithm and your program parses a certificate
(using the X.509 implementation of the SUN provider) and extracts the
public key from the certificate in order to initialize a Signature
object for verification, and (2) when keytool users
try to access a private key of your keytype (for example, to perform a
digital signature) after having generated the corresponding keypair.
In these cases, your provider master file should contain the following entries:
If the JCA needs to perform the inverse mapping (that is, from your
algorithm name to its associated OID), you need to provide an alias
entry of the following form for one of the OIDs under which your
algorithm should be known:
If your algorithm is known under more than one object identifier,
prefix the preferred one with "OID.".
An example of where the JCA needs to perform this kind of mapping is when
users run keytool in any mode that takes a
-sigalg option. For example, when the
-genkey and -certreq commands are invoked,
the user can specify your (signature) algorithm with
the -sigalg option.
Below is a copy of the Sun.java file,
which contains a class named Sun that is the
master class for the provider named "SUN".
(This provider is supplied with every SDK installation.)
As with all master classes, this class is a subclass
of Provider. It specifies the class names and package locations
of all the cryptographic service implementations
supplied by the "SUN" provider. Java 2 Security uses this information
to look up the various algorithms and other services
when they are requested.
This code is supplied as an example of a master class.
/*
* @(#)Sun.java 1.28 99/05/27
*
* Copyright 1996-1998 by Sun Microsystems, Inc.,
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
* All rights reserved.
*
* This software is the confidential and proprietary information
* of Sun Microsystems, Inc. ("Confidential Information"). You
* shall not disclose such Confidential Information and shall use
* it only in accordance with the terms of the license agreement
* you entered into with Sun.
*/
package sun.security.provider;
import java.io.*;
import java.util.*;
import java.security.*;
/**
* The SUN Security Provider.
*
* @author Benjamin Renaud
*
* @version 1.28, 05/27/99
*/
/**
* Defines the SUN provider.
*
* Algorithms supported, and their names:
*
* - SHA is the message digest scheme described in FIPS 180-1.
* Aliases for SHA are SHA-1 and SHA1.
*
* - SHA1withDSA is the signature scheme described in FIPS 186.
* (SHA used in DSA is SHA-1: FIPS 186 with Change No 1.)
* Aliases for SHA1withDSA are DSA, DSS, SHA/DSA, SHA-1/DSA, SHA1/DSA,
* SHAwithDSA, DSAWithSHA1, and the object
* identifier strings "OID.1.3.14.3.2.13", "OID.1.3.14.3.2.27" and
* "OID.1.2.840.10040.4.3".
*
* - DSA is the key generation scheme as described in FIPS 186.
* Aliases for DSA include the OID strings "OID.1.3.14.3.2.12"
* and "OID.1.2.840.10040.4.1".
*
* - MD5 is the message digest scheme described in RFC 1321.
* There are no aliases for MD5.
*/
public final class Sun extends Provider {
private static final String INFO = "SUN " +
"(DSA key/parameter generation; DSA signing; " +
"SHA-1, MD5 digests; SecureRandom; X.509 certificates; JKS keystore)";
public Sun() {
/* We are the SUN provider */
super("SUN", 1.2, INFO);
AccessController.doPrivileged(new java.security.PrivilegedAction() {
public Object run() {
/*
* Signature engines
*/
put("Signature.SHA1withDSA", "sun.security.provider.DSA");
put("Alg.Alias.Signature.DSA", "SHA1withDSA");
put("Alg.Alias.Signature.DSS", "SHA1withDSA");
put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA");
put("Alg.Alias.Signature.SHA-1/DSA", "SHA1withDSA");
put("Alg.Alias.Signature.SHA1/DSA", "SHA1withDSA");
put("Alg.Alias.Signature.SHAwithDSA", "SHA1withDSA");
put("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA");
put("Alg.Alias.Signature.OID.1.2.840.10040.4.3",
"SHA1withDSA");
put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA1withDSA");
put("Alg.Alias.Signature.1.3.14.3.2.13", "SHA1withDSA");
put("Alg.Alias.Signature.1.3.14.3.2.27", "SHA1withDSA");
/*
* Key Pair Generator engines
*/
put("KeyPairGenerator.DSA",
"sun.security.provider.DSAKeyPairGenerator");
put("Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1", "DSA");
put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSA");
put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSA");
/*
* Digest engines
*/
put("MessageDigest.MD5", "sun.security.provider.MD5");
put("MessageDigest.SHA", "sun.security.provider.SHA");
put("Alg.Alias.MessageDigest.SHA-1", "SHA");
put("Alg.Alias.MessageDigest.SHA1", "SHA");
/*
* Algorithm Parameter Generator engines
*/
put("AlgorithmParameterGenerator.DSA",
"sun.security.provider.DSAParameterGenerator");
/*
* Algorithm Parameter engines
*/
put("AlgorithmParameters.DSA",
"sun.security.provider.DSAParameters");
put("Alg.Alias.AlgorithmParameters.1.3.14.3.2.12", "DSA");
put("Alg.Alias.AlgorithmParameters.1.2.840.10040.4.1", "DSA");
/*
* Key factories
*/
put("KeyFactory.DSA", "sun.security.provider.DSAKeyFactory");
put("Alg.Alias.KeyFactory.1.3.14.3.2.12", "DSA");
put("Alg.Alias.KeyFactory.1.2.840.10040.4.1", "DSA");
/*
* SecureRandom
*/
put("SecureRandom.SHA1PRNG",
"sun.security.provider.SecureRandom");
/*
* Certificates
*/
put("CertificateFactory.X509",
"sun.security.provider.X509Factory");
put("Alg.Alias.CertificateFactory.X.509", "X509");
/*
* KeyStore
*/
put("KeyStore.JKS", "sun.security.provider.JavaKeyStore");
/*
* KeySize
*/
put("Signature.SHA1withDSA KeySize", "1024");
put("KeyPairGenerator.DSA KeySize", "1024");
put("AlgorithmParameterGenerator.DSA KeySize", "1024");
/*
* Implementation type: software or hardware
*/
put("Signature.SHA1withDSA ImplementedIn", "Software");
put("KeyPairGenerator.DSA ImplementedIn", "Software");
put("MessageDigest.MD5 ImplementedIn", "Software");
put("MessageDigest.SHA ImplementedIn", "Software");
put("AlgorithmParameterGenerator.DSA ImplementedIn",
"Software");
put("AlgorithmParameters.DSA ImplementedIn", "Software");
put("KeyFactory.DSA ImplementedIn", "Software");
put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
put("CertificateFactory.X509 ImplementedIn", "Software");
put("KeyStore.JKS ImplementedIn", "Software");
return null;
}
});
}
}
Below is a copy of the java.security
file that appears in every SDK installation. This file appears
in the lib/security
(lib\security on Windows) directory of the SDK.
Thus, if the JDK is installed in a directory
called j2sdk1.2, the file would be
j2sdk1.2/lib/security/java.security (Solaris)
j2sdk1.2\lib\security\java.security (Windows)
See Step 5 for an example of adding information
about your provider to this file.
#
# This is the "master security properties file".
#
# In this file, various security properties are set for use by
# java.security classes. This is where users can statically register
# Cryptographic Service Providers ("providers" for short). The term
# "provider" refers to a package or set of packages that supply a
# concrete implementation of a subset of the cryptography aspects of
# the Java Security API. A provider may, for example, implement one or
# more digital signature algorithms or message digest algorithms.
#
# Each provider must implement a subclass of the Provider class.
# To register a provider in this master security properties file,
# specify the Provider subclass name and priority in the format
#
# security.provider.n=className
#
# This 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.
#
# className must specify the subclass of the Provider class whose
# constructor sets the values of various properties that are required
# for the Java Security API to look up the algorithms or other
# facilities implemented by the provider.
#
# There must be at least one provider specification in java.security.
# There is a default provider that comes standard with the SDK. It
# is called the "SUN" provider, and its Provider subclass
# named Sun appears in the sun.security.provider package. Thus, the
# "SUN" provider is registered via the following:
#
# security.provider.1=sun.security.provider.Sun
#
# (The number 1 is used for the default provider.)
#
# Note: Statically registered Provider subclasses are instantiated
# when the system is initialized. Providers can be dynamically
# registered instead by calls to either the addProvider or
# insertProviderAt method in the Security class.
#
# List of providers and their preference orders (see above):
#
security.provider.1=sun.security.provider.Sun
#
# Class to instantiate as the system Policy. This is the name of the class
# that will be used as the Policy object.
#
policy.provider=sun.security.provider.PolicyFile
# The default is to have a single system-wide policy file,
# and a policy file in the user's home directory.
policy.url.1=file:${java.home}/lib/security/java.policy
policy.url.2=file:${user.home}/.java.policy
# whether or not we expand properties in the policy file
# if this is set to false, properties (${...}) will not be expanded in policy
# files.
policy.expandProperties=true
# whether or not we allow an extra policy to be passed on the command line
# with -Djava.security.policy=somefile. Comment out this line to disable
# this feature.
policy.allowSystemProperty=true
# whether or not we look into the IdentityScope for trusted Identities
# when encountering a 1.1 signed JAR file. If the identity is found
# and is trusted, we grant it AllPermission.
policy.ignoreIdentityScope=false
#
# Default keystore type.
#
keystore.type=jks
#
# Class to instantiate as the system scope:
#
system.scope=sun.security.provider.IdentityDatabase
#
# List of comma-separated packages that start with or equal this string
# will cause a security exception to be thrown when
# passed to checkPackageAccess unless the
# corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted.
package.access=sun.
#
# List of comma-separated packages that start with or equal this string
# will cause a security exception to be thrown when
# passed to checkPackageDefinition unless the
# corresponding RuntimePermission ("defineClassInPackage."+package) has
# been granted.
#
# by default, no packages are restricted for definition, and none of
# the class loaders supplied with the SDK call checkPackageDefinition.
#
#package.definition=