Signaturepublic abstract class Signature extends SignatureSpi This Signature class is used to provide applications the functionality
of a digital signature algorithm. Digital signatures are used for
authentication and integrity assurance of digital data.
The signature algorithm can be, among others, the NIST standard
DSA, using DSA and SHA-1. The DSA algorithm using the
SHA-1 message digest algorithm can be specified as SHA1withDSA.
In the case of RSA, there are multiple choices for the message digest
algorithm, so the signing algorithm could be specified as, for example,
MD2withRSA, MD5withRSA, or SHA1withRSA.
The algorithm name must be specified, as there is no default.
Like other algorithm-based classes in Java Security, Signature
provides implementation-independent algorithms, whereby a caller
(application code) requests a particular signature algorithm
and is handed back a properly initialized Signature object. It is
also possible, if desired, to request a particular algorithm from a
particular provider. See the getInstance methods.
Thus, there are two ways to request a Signature algorithm object: by
specifying either just an algorithm name, or both an algorithm name
and a package provider.
- If just an algorithm name is specified, the system will
determine if there is an implementation of the algorithm requested
available in the environment, and if there is more than one, if
there is a preferred one.
- If both an algorithm name and a package provider are specified,
the system will determine if there is an implementation of the
algorithm in the package requested, and throw an exception if there
is not.
A Signature object can be used to generate and verify digital
signatures.
There are three phases to the use of a Signature object for
either signing data or verifying a signature:
- Initialization, with either
- a public key, which initializes the signature for
verification (see {@link #initVerify(PublicKey) initVerify}), or
- a private key (and optionally a Secure Random Number Generator),
which initializes the signature for signing
(see {@link #initSign(PrivateKey)}
and {@link #initSign(PrivateKey, SecureRandom)}).
- Updating
Depending on the type of initialization, this will update the
bytes to be signed or verified. See the
{@link #update(byte) update} methods.
- Signing or Verifying a signature on all updated bytes. See the
{@link #sign() sign} methods and the {@link #verify(byte[]) verify}
method.
Note that this class is abstract and extends from
SignatureSpi for historical reasons.
Application developers should only take notice of the methods defined in
this Signature class; all the methods in
the superclass are intended for cryptographic service providers who wish to
supply their own implementations of digital signature algorithms. |
Fields Summary |
---|
private static final Debug | debug | private String | algorithm | Provider | provider | protected static final int | UNINITIALIZEDPossible {@link #state} value, signifying that
this signature object has not yet been initialized. | protected static final int | SIGNPossible {@link #state} value, signifying that
this signature object has been initialized for signing. | protected static final int | VERIFYPossible {@link #state} value, signifying that
this signature object has been initialized for verification. | protected int | stateCurrent state of this signature object. | private static final String | RSA_SIGNATURE | private static final String | RSA_CIPHER | private static final List | rsaIds | private static final Map | signatureInfo |
Constructors Summary |
---|
protected Signature(String algorithm)Creates a Signature object for the specified algorithm.
this.algorithm = algorithm;
|
Methods Summary |
---|
void | chooseFirstProvider()
// empty, overridden in Delegate
| public java.lang.Object | clone()Returns a clone if the implementation is cloneable.
if (this instanceof Cloneable) {
return super.clone();
} else {
throw new CloneNotSupportedException();
}
| public final java.lang.String | getAlgorithm()Returns the name of the algorithm for this signature object.
return this.algorithm;
| public static java.security.Signature | getInstance(java.lang.String algorithm)Generates a Signature object that implements the specified digest
algorithm. If the default provider package
provides an implementation of the requested digest algorithm,
an instance of Signature containing that implementation is returned.
If the algorithm is not available in the default
package, other packages are searched.
List list;
if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
list = GetInstance.getServices(rsaIds);
} else {
list = GetInstance.getServices("Signature", algorithm);
}
Iterator t = list.iterator();
if (t.hasNext() == false) {
throw new NoSuchAlgorithmException
(algorithm + " Signature not available");
}
// try services until we find an Spi or a working Signature subclass
NoSuchAlgorithmException failure;
do {
Service s = (Service)t.next();
if (isSpi(s)) {
return new Delegate(s, t, algorithm);
} else {
// must be a subclass of Signature, disable dynamic selection
try {
Instance instance =
GetInstance.getInstance(s, SignatureSpi.class);
return getInstance(instance, algorithm);
} catch (NoSuchAlgorithmException e) {
failure = e;
}
}
} while (t.hasNext());
throw failure;
| private static java.security.Signature | getInstance(sun.security.jca.GetInstance.Instance instance, java.lang.String algorithm)
Signature sig;
if (instance.impl instanceof Signature) {
sig = (Signature)instance.impl;
} else {
SignatureSpi spi = (SignatureSpi)instance.impl;
sig = new Delegate(spi, algorithm);
}
sig.provider = instance.provider;
return sig;
| public static java.security.Signature | getInstance(java.lang.String algorithm, java.lang.String provider)Generates a Signature object implementing the specified
algorithm, as supplied from the specified provider, if such an
algorithm is available from the provider.
if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
// exception compatibility with existing code
if ((provider == null) || (provider.length() == 0)) {
throw new IllegalArgumentException("missing provider");
}
Provider p = Security.getProvider(provider);
if (p == null) {
throw new NoSuchProviderException
("no such provider: " + provider);
}
return getInstanceRSA(p);
}
Instance instance = GetInstance.getInstance
("Signature", SignatureSpi.class, algorithm, provider);
return getInstance(instance, algorithm);
| public static java.security.Signature | getInstance(java.lang.String algorithm, java.security.Provider provider)Generates a Signature object implementing the specified
algorithm, as supplied from the specified provider, if such an
algorithm is available from the provider. Note: the
provider doesn't have to be registered.
if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
// exception compatibility with existing code
if (provider == null) {
throw new IllegalArgumentException("missing provider");
}
return getInstanceRSA(provider);
}
Instance instance = GetInstance.getInstance
("Signature", SignatureSpi.class, algorithm, provider);
return getInstance(instance, algorithm);
| private static java.security.Signature | getInstanceRSA(java.security.Provider p)
// try Signature first
Service s = p.getService("Signature", RSA_SIGNATURE);
if (s != null) {
Instance instance = GetInstance.getInstance(s, SignatureSpi.class);
return getInstance(instance, RSA_SIGNATURE);
}
// check Cipher
try {
Cipher c = Cipher.getInstance(RSA_CIPHER, p);
return new Delegate(new CipherAdapter(c), RSA_SIGNATURE);
} catch (GeneralSecurityException e) {
// throw Signature style exception message to avoid confusion,
// but append Cipher exception as cause
throw new NoSuchAlgorithmException("no such algorithm: "
+ RSA_SIGNATURE + " for provider " + p.getName(), e);
}
| public final java.lang.Object | getParameter(java.lang.String param)Gets the value of the specified algorithm parameter. This method
supplies a general-purpose mechanism through which it is possible to
get the various parameters of this object. A parameter may be any
settable parameter for the algorithm, such as a parameter size, or
a source of random bits for signature generation (if appropriate),
or an indication of whether or not to perform a specific but optional
computation. A uniform algorithm-specific naming scheme for each
parameter is desirable but left unspecified at this time.
return engineGetParameter(param);
| public final java.security.AlgorithmParameters | getParameters()Returns the parameters used with this signature object.
The returned parameters may be the same that were used to initialize
this signature, or may contain a combination of default and randomly
generated parameter values used by the underlying signature
implementation if this signature requires algorithm parameters but
was not initialized with any.
return engineGetParameters();
| public final java.security.Provider | getProvider()Returns the provider of this signature object.
chooseFirstProvider();
return this.provider;
| public final void | initSign(java.security.PrivateKey privateKey)Initialize this object for signing. If this method is called
again with a different argument, it negates the effect
of this call.
engineInitSign(privateKey);
state = SIGN;
| public final void | initSign(java.security.PrivateKey privateKey, java.security.SecureRandom random)Initialize this object for signing. If this method is called
again with a different argument, it negates the effect
of this call.
engineInitSign(privateKey, random);
state = SIGN;
| public final void | initVerify(java.security.PublicKey publicKey)Initializes this object for verification. If this method is called
again with a different argument, it negates the effect
of this call.
engineInitVerify(publicKey);
state = VERIFY;
| public final void | initVerify(java.security.cert.Certificate certificate)Initializes this object for verification, using the public key from
the given certificate.
If the certificate is of type X.509 and has a key usage
extension field marked as critical, and the value of the key usage
extension field implies that the public key in
the certificate and its corresponding private key are not
supposed to be used for digital signatures, an
InvalidKeyException is thrown.
// If the certificate is of type X509Certificate,
// we should check whether it has a Key Usage
// extension marked as critical.
if (certificate instanceof java.security.cert.X509Certificate) {
// Check whether the cert has a key usage extension
// marked as a critical extension.
// The OID for KeyUsage extension is 2.5.29.15.
X509Certificate cert = (X509Certificate)certificate;
Set critSet = cert.getCriticalExtensionOIDs();
if (critSet != null && !critSet.isEmpty()
&& critSet.contains("2.5.29.15")) {
boolean[] keyUsageInfo = cert.getKeyUsage();
// keyUsageInfo[0] is for digitalSignature.
if ((keyUsageInfo != null) && (keyUsageInfo[0] == false))
throw new InvalidKeyException("Wrong key usage");
}
}
PublicKey publicKey = certificate.getPublicKey();
engineInitVerify(publicKey);
state = VERIFY;
| private static boolean | isSpi(java.security.Provider.Service s)
signatureInfo = new ConcurrentHashMap<String,Boolean>();
Boolean TRUE = Boolean.TRUE;
// pre-initialize with values for our SignatureSpi implementations
signatureInfo.put("sun.security.provider.DSA$RawDSA", TRUE);
signatureInfo.put("sun.security.provider.DSA$SHA1withDSA", TRUE);
signatureInfo.put("sun.security.rsa.RSASignature$MD2withRSA", TRUE);
signatureInfo.put("sun.security.rsa.RSASignature$MD5withRSA", TRUE);
signatureInfo.put("sun.security.rsa.RSASignature$SHA1withRSA", TRUE);
signatureInfo.put("sun.security.rsa.RSASignature$SHA256withRSA", TRUE);
signatureInfo.put("sun.security.rsa.RSASignature$SHA384withRSA", TRUE);
signatureInfo.put("sun.security.rsa.RSASignature$SHA512withRSA", TRUE);
signatureInfo.put("com.sun.net.ssl.internal.ssl.RSASignature", TRUE);
signatureInfo.put("sun.security.pkcs11.P11Signature", TRUE);
if (s.getType().equals("Cipher")) {
// must be a CipherSpi, which we can wrap with the CipherAdapter
return true;
}
String className = s.getClassName();
Boolean result = signatureInfo.get(className);
if (result == null) {
try {
Object instance = s.newInstance(null);
// Signature extends SignatureSpi
// so it is a "real" Spi if it is an
// instance of SignatureSpi but not Signature
boolean r = (instance instanceof SignatureSpi)
&& (instance instanceof Signature == false);
if ((debug != null) && (r == false)) {
debug.println("Not a SignatureSpi " + className);
debug.println("Delayed provider selection may not be "
+ "available for algorithm " + s.getAlgorithm());
}
result = Boolean.valueOf(r);
signatureInfo.put(className, result);
} catch (Exception e) {
// something is wrong, assume not an SPI
return false;
}
}
return result.booleanValue();
| public final void | setParameter(java.lang.String param, java.lang.Object value)Sets the specified algorithm parameter to the specified value.
This method supplies a general-purpose mechanism through
which it is possible to set the various parameters of this object.
A parameter may be any settable parameter for the algorithm, such as
a parameter size, or a source of random bits for signature generation
(if appropriate), or an indication of whether or not to perform
a specific but optional computation. A uniform algorithm-specific
naming scheme for each parameter is desirable but left unspecified
at this time.
engineSetParameter(param, value);
| public final void | setParameter(java.security.spec.AlgorithmParameterSpec params)Initializes this signature engine with the specified parameter set.
engineSetParameter(params);
| public final byte[] | sign()Returns the signature bytes of all the data updated.
The format of the signature depends on the underlying
signature scheme.
A call to this method resets this signature object to the state
it was in when previously initialized for signing via a
call to initSign(PrivateKey) . That is, the object is
reset and available to generate another signature from the same
signer, if desired, via new calls to update and
sign .
if (state == SIGN) {
return engineSign();
}
throw new SignatureException("object not initialized for " +
"signing");
| public final int | sign(byte[] outbuf, int offset, int len)Finishes the signature operation and stores the resulting signature
bytes in the provided buffer outbuf , starting at
offset .
The format of the signature depends on the underlying
signature scheme.
This signature object is reset to its initial state (the state it
was in after a call to one of the initSign methods) and
can be reused to generate further signatures with the same private key.
if (outbuf == null) {
throw new IllegalArgumentException("No output buffer given");
}
if (outbuf.length - offset < len) {
throw new IllegalArgumentException
("Output buffer too small for specified offset and length");
}
if (state != SIGN) {
throw new SignatureException("object not initialized for " +
"signing");
}
return engineSign(outbuf, offset, len);
| public java.lang.String | toString()Returns a string representation of this signature object,
providing information that includes the state of the object
and the name of the algorithm used.
String initState = "";
switch (state) {
case UNINITIALIZED:
initState = "<not initialized>";
break;
case VERIFY:
initState = "<initialized for verifying>";
break;
case SIGN:
initState = "<initialized for signing>";
break;
}
return "Signature object: " + getAlgorithm() + initState;
| public final void | update(byte b)Updates the data to be signed or verified by a byte.
if (state == VERIFY || state == SIGN) {
engineUpdate(b);
} else {
throw new SignatureException("object not initialized for "
+ "signature or verification");
}
| public final void | update(byte[] data)Updates the data to be signed or verified, using the specified
array of bytes.
update(data, 0, data.length);
| public final void | update(byte[] data, int off, int len)Updates the data to be signed or verified, using the specified
array of bytes, starting at the specified offset.
if (state == SIGN || state == VERIFY) {
engineUpdate(data, off, len);
} else {
throw new SignatureException("object not initialized for "
+ "signature or verification");
}
| public final void | update(java.nio.ByteBuffer data)Updates the data to be signed or verified using the specified
ByteBuffer. Processes the data.remaining() bytes
starting at at data.position() .
Upon return, the buffer's position will be equal to its limit;
its limit will not have changed.
if ((state != SIGN) && (state != VERIFY)) {
throw new SignatureException("object not initialized for "
+ "signature or verification");
}
if (data == null) {
throw new NullPointerException();
}
engineUpdate(data);
| public final boolean | verify(byte[] signature)Verifies the passed-in signature.
A call to this method resets this signature object to the state
it was in when previously initialized for verification via a
call to initVerify(PublicKey) . 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 .
if (state == VERIFY) {
return engineVerify(signature);
}
throw new SignatureException("object not initialized for " +
"verification");
| public final boolean | verify(byte[] signature, int offset, int length)Verifies the passed-in signature in the specified array
of bytes, starting at the specified offset.
A call to this method resets this signature object to the state
it was in when previously initialized for verification via a
call to initVerify(PublicKey) . 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 .
if (state == VERIFY) {
if ((signature == null) || (offset < 0) || (length < 0) ||
(offset + length > signature.length)) {
throw new IllegalArgumentException("Bad arguments");
}
return engineVerify(signature, offset, length);
}
throw new SignatureException("object not initialized for " +
"verification");
|
|