public abstract class ISO9796P2S2S3Signature extends ISO9796P2Signature
ISO 9796 (2002) Part 2 ("Digital Signature schemes giving message recovery,
Part 2: Integer factorization based mechanisms") specifies three digital
signature schemes S1, S2, S3. S1 (implemented by class
ISO9796P2Signature
) and S3 are deterministic, S2
is randomized by a random salt value. ISO 9796-2 recommends to use the
randomized scheme (S2) where possible; and to prefer S3 to S1, which only
shall be used if backwards compatibility to the 1997 version of the ISO
9796-2 standard is required. All three schemes provide a digital signature
algorithm that is based on message recovery. In contrast to signature schemes
with appendix (as for instance used by the signature schemes defined in
PKCS#1) where the whole data has to be transmitted with the signature,
message recovery means that the input data -- or parts of the input data --
can be recovered from the signature. Depending on if the length of the
message is shorter than the
capacity
of the signature scheme, the recovery may be either total or
partial. Signature schemes S2, S3
calculate
the capacity
from modulus length, hash length and length of the salt value that is used.
In general JCA Signature engines are not designed for signature schemes
giving message recovery. A JCA Signature engine requires that the data to be
signed or verified is supplied by one or more calls of its
update
methods, and the verify
method only returns
whether the signature has been verified successfully or signature
verification has failed. There is no means for fetching the recovered part of
the message from the Signature engine. Thus an application can use an
ISO-9796 Signature engine in the accustomed way, e.g.:
// create Signature engine Signature signatureEngine = Signature.getInstance("SHAandMGF1/RSA-ISO9796-2-2-3", "IAIK"); // the private signing key PrivateKey privateKey = ...; signatureEngine.initSign(privateKey); // supply data to be signed by one or more update calls signatureEngine.update(...); ... // create signature byte[] signature = signatureEngine.sign();And on the verification side:
// create Signature engine Signature signatureEngine = Signature.getInstance("SHAandMGF1/RSA-ISO9796-2-2-3", "IAIK"); // the public verification key PublicKey publicKey = ...; signatureEngine.initVerify(publicKey); // supply data to be verified by one or more update calls signatureEngine.update(...); ... // verify signature boolean ok = signatureEngine.verify(signature);However, when total recovery has been applied it is possible to verify the signature without supplying the data (i.e. method
update
may not
be called at all) and then get the recovered message from the Signature
engine as RecoveredMessage
parameter:
// create Signature engine Signature signatureEngine = Signature.getInstance("SHAandMGF1/RSA-ISO9796-2-2-3", "IAIK"); // the public verification key PublicKey publicKey = ...; signatureEngine.initVerify(publicKey); // verify signature boolean ok = signatureEngine.verify(signature); // get the recovered message: AlgorithmParameters recoveredMessage = (AlgorithmParameters)signatureEngine.getParameters(); byte[] message = recoveredMessage.getEncoded();Note that you also can get the recovered part of the message when partial recovery has been applied. However, this may not be necessary since in the case of partial recovery you will have to supply the full message via
update
calls anyway as required by the JCA Signature API. This
may be no disadvantage since in practice the document usually may be
transmitted along with the signature (and not splitted into a recoverable and
not-recoverable part to then be put together again at the receiving side).
Method getParameters
only will return the recovered part of the
message if it is called after method verify
has been called. In
any other case you will get null
indicating that the Signature
engine is in a state where no recovered message is available. It also is not
possible to set the recovered message as algorithm parameter for the
Signature engine. The recovered part of the message is gained from the
signature during the verification process and therefore only can be get from
the engine but not set.
ISO9796P2S2S3ParameterSpec
object (note
that these parameters only can be set to the engine, but not get from it; as
mentioned above parameters that are got from the engine represent the
recovered part of the message):
hash engine
and
hash id
: the hash algorithm that is
used by an ISO 9796-2 signature scheme may be indicated by using a single hash identifier octet in the range of (hexadecimal) 0x00
to 0xFF. This library contains concrete RSA based ISO 9796-2 Signature engines for the following dedicated hash
functions for which hash identifiers are defined by ISO/IEC 10118-3: SHA-1 (
S1
,
S2S3
),
SHA-256 (S1
,
S2S3
),
SHA-384 (S1
,
S2S3
),
SHA-512 (S1
,
S2S3
),
RIPEMD128 (S1
,
S2S3
)
and RIPEMD160 (S1
, S2S3
). Since ISO/IEC 10118-3 does not define hash ids
for, e.g., MD5 and SHA-224, we cannot provide concrete implementations for
"MD5andMGF1/RSA-ISO9796-2-2-3" or "SHA224andMGF1/RSA-ISO9796-2-2-3" Signature
engines. However, MD5 or SHA-224 may be used with a general RSA based ISO
9796-2 Signature engine
)
and parameterizing it by specifying the hash engine and -- if available --
hash id to be used, e.g.:
// create parameter spec ISO9796P2S2S3ParameterSpec paramSpec = new ISO9796P2S2S3ParameterSpec(); // set hash engine MessageDigest hashEngine = MessageDigest.getInstance("MD5", "IAIK"); int hashLen = 16; paramSpec.setHashEngine(hashEngine, hashLen); // set hash id int hashID = ...; paramSpec.setHashID(hashID); // create Signature engine Signature signatureEngine = Signature.getInstance("RSA-ISO9796-2-2-3", "IAIK"); // set hash engine and id as parameter signatureEngine.setParameter(paramSpec);You also can set hash engine and/or hash id for any of the concrete ISO 9796-2 Signature engines stated above. However, since these engines are allowed to operate with one specific hash algorithm only, the supplied parameters are checked for compliance and an exception will be thrown if, for instance, trying to set a MD5 MessageDigest engine for a
SHAandMGF1/RSA-ISO9796-2-2-3"
Signature engine.
explicit
or implicit trailer field. When signing a message according to ISO
9796-2 at first a message representative is created which then is "signed"
(i.e. encrypted for RSA) with the private key of the underlying signature
production function (e.g. RSA). The last one or two octets of the message
representative represent the so-called trailer field. Depending on if the hash id octet is included in the trailer field
(explicit) or if it is not included (implicit) the trailer field consists of
two or one octets, respectively. Each of the concrete RSA based ISO 9796-2 implementations listed above uses an implicit
trailer field trailer field by default (since it already "knows" the hash
algorithms it is using). This means that by default the hash identifier is
not included in the trailer field. However, the general (
S1
,
S2S3
) RSA based ISO
9796-2 Signature engines use an explicit trailer by default expecting that
the hash id is provided as parameter. To change the
explicit/implicit trailer field usage set/unset the corresponding boolean
flag of the ISO9796P2S2S3ParameterSpec
,
e.g.:
// create parameter spec ISO9796P2S2S3ParameterSpec paramSpec = new ISO9796P2S2S3ParameterSpec(); // set hash engine MessageDigest hashEngine = ...; int hashLen = ...; paramSpec.setHashEngine(hashEngine, hashLen); // set hash id int hashID = ...; paramSpec.setHashID(hashID); // switch explicit/implicit trailer field usage if desired boolean explicit = ...; paramSpecset.setUseExplicitTrailer(explicit); // create Signature engine Signature signatureEngine = Signature.getInstance("RSA-ISO9796-2-2-3", "IAIK"); // set hash engine and id as parameter signatureEngine.setParameter(paramSpec);
alternative
signature production function specified in ISO 9796-2 or not. ISO 9796-2
(2002), appendix A specifies two signature production functions to may be
used with the underlying public key system (e.g. RSA). The first variant
subtract the result of the modulus exponentiation from the modulus and sets it
as signature value, if it is shorter than the result of the modulus
exponentiation. The second (alternative) method omits this step so that the
signature value is always the result of the modulus exponentiation. This ISO
9796-2 implementation uses the second (alternative) variant by default. To
enforce the first variant unset the corresponding boolean flag of the
ISO9796P2S2S3ParameterSpec
, e.g.:
// create parameter spec ISO9796P2S2S3ParameterSpec paramSpec = new ISO9796P2S2S3ParameterSpec(); // do not use the alternative signature production function: paramSpec.setUseAlternativeSignatureFunction(false); // create Signature engine Signature signatureEngine = Signature.getInstance("SHA1/RSA-ISO9796-2-2-3", "IAIK"); // set hash engine and id as parameter signatureEngine.setParameter(paramSpec);
generator
for supplying random numbers if required (e.g. for RSA blinding,
or generating a random salt value for ISO 9796-2 signature scheme S2, e.g.:
// create parameter spec ISO9796P2S2S3ParameterSpec paramSpec = new ISO9796P2S2S3ParameterSpec(); // create and set SecureRandom: SecureRandom secRandom = ...; paramSpec.setSecureRandom(secRandom); // create Signature engine Signature signatureEngine = Signature.getInstance("SHA1/RSA-ISO9796-2", "IAIK"); // set parameter signatureEngine.setParameter(paramSpec);If no SecureRandom has been explicitly specified via parameterSpec, a default SecureRandom is used for creating random numbers when required by the Signature engine.
length
and/or Salt
value
: these two parameters are
only meaningful for ISO 9796-2 Signature schemes S2 and S3, respectively. The
salt value used for signature scheme S2 is created at random. By default the
length of the salt value is the length of the hash value produced by the hash
algorithm that is used by the Signature engine. The, for instance,
"SHA1andMGF1/RSA-ISO9796-2-2-3"
Signature engine uses a salt value of 20
bytes as this is the length of the hash value produced by the SHA-1 hash
algorithm. The default salt length value can be changed by using a
ISO9796P2S2S3ParameterSpec
, e.g.:
// create parameter spec ISO9796P2S2S3ParameterSpec paramSpec = new ISO9796P2S2S3ParameterSpec(); // set salt length: int saltLength = ...; paramSpec.setSaltLength(saltLength); // create Signature engine Signature signatureEngine = Signature.getInstance("SHA1andMGF1/RSA-ISO9796-2-2-3", "IAIK"); // set parameter signatureEngine.setParameter(paramSpec);If no SecureRandom has been explicitly specified via parameterSpec, a default SecureRandom is used for creating random numbers when required by the Signature engine.
// create parameter spec ISO9796P2S2S3ParameterSpec paramSpec = new ISO9796P2S2S3ParameterSpec(); // set salt value: byte[] salt = ...; paramSpec.setSalt(salt); // create Signature engine Signature signatureEngine = Signature.getInstance("SHA1andMGF1/RSA-ISO9796-2-2-3", "IAIK"); // set parameter signatureEngine.setParameter(paramSpec);As seen from the examples above the signature engine for both signature schemes S2 and S3 are instantiated by the same implementation name ("SHA1andMGF1/RSA-ISO9796-2-2-3"). That is quite correct, both schemes (S2 and S3) are implemented by the same class. By default a random salt is used as required for signature scheme S2. When specifying a fixed salt value via parameter the scheme that is actually used switches from S2 to S3 (which only differ in the usage of random or fixed salt value, respectively).
function
:
this parameter is only meaningful for ISO 9796-2 Signature schemes S2 and S3
and may be used to specify another mask generation
engine
than the default one (
MGF1
), e.g.:
// create parameter spec ISO9796P2S2S3ParameterSpec paramSpec = new ISO9796P2S2S3ParameterSpec(); // set the alternative mask generation algorithm: MaskGenerationAlgorithm mga = ...; paramSpec.setMGFEngine(mga); // create Signature engine Signature signatureEngine = Signature.getInstance("RSA-ISO9796-2-2-3", "IAIK"); // set parameter signatureEngine.setParameter(paramSpec);
cMinus
value: this parameter
is only meaningful for ISO 9796-2 Signature schemes S2 and S3. It may be used
to specify the number of bits that shall be subtracted from the
capacity
(max length of
recovered part of the message) of the signature scheme to give the actual
length of the recovered part of the message. By the default,
cMinus
is 0 to make the recovered part of the message as long es
possible. The default cMinus value can be changed by using a
ISO9796P2S2S3ParameterSpec
, e.g.:
// create parameter spec ISO9796P2S2S3ParameterSpec paramSpec = new ISO9796P2S2S3ParameterSpec(); // set the CMinus value int cMinus = ...; paramSpec.setCMinus(cMinus); // create Signature engine Signature signatureEngine = Signature.getInstance("SHA1andMGF1/RSA-ISO9796-2-2-3", "IAIK"); // set parameter signatureEngine.setParameter(paramSpec);
update
method of the Signature engine. However, in contrast
to the other IAIK Signature engines, there do not exist special "raw" engines
for the ISO 9796-2 Signature schemes. Since in raw mode the hash value (but
not the data to be signed) is specified by calling the update
method, but ISO 9796-2 also needs to know the message length and the
recoverable part of the message, an alternative way is required for telling
the engine the required message length and the recoverable bytes of the
message. This has to be done by using a RawISO9796P2S2S3ParameterSpec
for signature scheme S2 and S3 (the behavior
for signature scheme S2 and S3 is slightly different than for signature
schemes S2, S3, since S1 calculates a hash value on the whole message,
whereas S2 and S3 only need the hash value from the non-recoverable part as
input). When specifying a raw parameter spec the ISO 9796-2 Signature engine
automatically switches into the raw mode. See the raw parameter
documentation
for more information on
how to use ISO 9796-2 Signature schemes S2S3 in raw mode.
getInstance
method of the JCA Signature engine class. When
calling getInstance
the name of the requested Signature
algorithm has to be supplied. Since ISO 9796-2 specifies three signature
schemes S1, S2 and S3 the following rules have to be used for instantiating a
particular ISO 9796-2 Signature engine. As discussed above, the two schemes S2 and S3 only differ in the usage of
random or fixed salt values, respectively. For that reason Signature engines
for S2 and S3 anytime can be requested by specifying the same algorithm name
(since implemented by the same class). An engine switches from S2 to S3 as
soon as a fixed salt value is specified via parameter. Signature.getInstance("RSA-ISO9796-2-2-3", "IAIK")
a RSA based Signature engine for signature schemes S2, S3 is instantiated. As
seen from above, when requesting a Signature engine for scheme 2 or 3, the
"-2-3" suffix has to be appended to the signature algorithm name. The first
"2" in "RSA-ISO9796-2-2-3" indicates that "Part 2" of the ISO 9796 standard
is used.
When requesting an implementation of the RSA based ISO 9796-2 signature schemes S2, S3 for some particular hash algorithm, the name of the requested hash algorithm (together with the name of the mask generation function in use, MGF1) has to be put in front of the "RSA-ISO9796-2-2-3" name, separated by an oblique stroke ("/"). There exist concrete RSA based ISO 9796-2 S2, S3 signature schemes for the hash algorithms SHA-1, SHA-256, SHA-384, SHA-512, RIPEMD-128 and RIPEMD-160 (for which hash ids are defined in ISO/IEC 10118-3):
"SHAandMGF1/RSA-ISO9796-2-2-3"
"SHA256andMGF1/RSA-ISO9796-2-2-3"
"SHA384andMGF1/RSA-ISO9796-2-2-3"
"SHA512andMGF1/RSA-ISO9796-2-2-3"
"RIPEMD128andMGF1/RSA-ISO9796-2-2-3"
"RIPEMD160andMGF1/RSA-ISO9796-2-2-3"
"RSA-ISO9796-2-2-3"
) S2S3 signature engine (see above
for an example).
demo.TestSignature
example that is included in the
demo source library of IAIK-JCE (see src/demo
folder of the
IAIK-JCE distribution).Signature
,
ISO9796P2Signature
,
ISO9796P2ParameterSpec
,
ISO9796P2S2S3ParameterSpec
,
RawISO9796P2ParameterSpec
,
RawISO9796P2S2S3ParameterSpec
,
RecoveredMessage
,
RSAISO9796P2Signature
,
RSAISO9796P2S2S3Signature
,
SHAwithRSAISO9796P2Signature
,
SHA256withRSAISO9796P2Signature
,
SHA384withRSAISO9796P2Signature
,
SHA512withRSAISO9796P2Signature
,
RIPEMD128withRSAISO9796P2Signature
,
RIPEMD160withRSAISO9796P2Signature
,
SHAwithRSAISO9796P2S2S3andMGF1Signature
,
SHA256withRSAISO9796P2S2S3andMGF1Signature
,
SHA384withRSAISO9796P2S2S3andMGF1Signature
,
SHA512withRSAISO9796P2S2S3andMGF1Signature
,
RIPEMD128withRSAISO9796P2S2S3andMGF1Signature
,
RIPEMD160withRSAISO9796P2S2S3andMGF1Signature
Modifier and Type | Field and Description |
---|---|
protected MaskGenerationAlgorithm |
mgfEngine_
The mask generation algorithm engine.
|
hashEngine_, secureRandom_
Modifier | Constructor and Description |
---|---|
protected |
ISO9796P2S2S3Signature(java.lang.String algorithm)
Creates an ISO 9796-2 Signature engine (scheme S2, S3) with the given
algorithm name.
|
protected |
ISO9796P2S2S3Signature(java.lang.String algorithm,
int hLen,
byte hashID)
Creates a ISO 9796-2 Signature engine (scheme S2, S3) with given algorithm
name, hash output length and hash id.
|
Modifier and Type | Method and Description |
---|---|
static int |
calculateCapacity(int modLen,
int hashLen,
boolean explicit)
This method is not supported.
|
static int |
calculateCapacity(int modLen,
int hashLen,
int saltLen,
boolean explicit)
Calculates the capacity of this ISO 9796-2 Signature engine (scheme 2,3).
|
protected void |
engineSetParameter(java.security.spec.AlgorithmParameterSpec params)
Sets any parameters that may be used with this Signature engine.
|
protected byte[] |
engineSign()
Calculates the signature value.
|
protected void |
engineUpdate(byte b)
Updates this Signature engine with the given byte.
|
protected void |
engineUpdate(byte[] b,
int off,
int len)
Updates this Signature engine with the given bytes.
|
protected boolean |
engineVerify(byte[] signature)
Verifies the signature.
|
protected void |
reset(java.math.BigInteger modulus)
Resets this Signature engine to the state after
engineInitSign
or engineInitVerify has been called. |
checkHashEngineName, engineGetParameter, engineGetParameters, engineSetParameter, getSecureRandom, openSignature, produceSignature, registerHashEngine, setSecureRandom
protected MaskGenerationAlgorithm mgfEngine_
protected ISO9796P2S2S3Signature(java.lang.String algorithm)
algorithm
- the name of the signature algorithmprotected ISO9796P2S2S3Signature(java.lang.String algorithm, int hLen, byte hashID)
algorithm
- the name of the signature algorithmhLen
- the length of the value produced by the hash algorithm in usehashID
- the ID of the hash algorithm in usepublic static int calculateCapacity(int modLen, int hashLen, int saltLen, boolean explicit)
modLen
- the length (in bits) of the modulushashLen
- the length (in bits) of the output value of the hash algorithm in
usesaltLen
- the length (in bits) of the salt valueexplicit
- whether the hash id shall be included in the signature or notjava.lang.IllegalArgumentException
- if the calculated capacity < 7public static int calculateCapacity(int modLen, int hashLen, boolean explicit)
S1
signature engine. Use method
calculateCapacity(int
modLen, int hashLen, int saltLen, boolean explicit)
for calculating the
capacity.java.lang.IllegalStateException
- since this method is not supported by this Signature engineprotected void engineUpdate(byte b)
In contrast to signature scheme S1
, where any
given data byte contributes to the hash calculation update, only those
bytes that do not belong to the recoverable part of the message contribute
to the hash update for signature schemes S2 and S3.
engineUpdate
in class ISO9796P2Signature
b
- the data (hash in raw mode) byte with which this engine has to be
updatedprotected void engineUpdate(byte[] b, int off, int len)
In contrast to signature scheme S1
, where any
given data byte contributes to the hash calculation update, only those
bytes that do not belong to the recoverable part of the message contribute
to the hash update for signature schemes S2 and S3.
engineUpdate
in class ISO9796P2Signature
b
- the data (hash in raw mode) bytes with which this engine has to be
updatedoff
- the start index in byte array b
len
- the number of bytes of byte array b
that shall be
used for update, starting at off
protected void engineSetParameter(java.security.spec.AlgorithmParameterSpec params) throws java.security.InvalidAlgorithmParameterException
engineSetParameter
in class ISO9796P2Signature
params
- the parameters as ISO9796P2S2S3ParameterSpec
or
RawISO9796P2S2S3ParameterSpec
InvalidParameterException
- if the supplied parameters are invalid (e.g. not ISO 9796-2
ParameterSpecs for signature scheme S2 or S3)java.security.InvalidAlgorithmParameterException
protected void reset(java.math.BigInteger modulus)
engineInitSign
or engineInitVerify
has been called.reset
in class ISO9796P2Signature
modulus
- the modulus of the public key system (if called during init)protected byte[] engineSign() throws java.security.SignatureException
engineSign
in class ISO9796P2Signature
java.security.SignatureException
- if an error occurs during signature calculationprotected boolean engineVerify(byte[] signature) throws java.security.SignatureException
engineVerify
in class ISO9796P2Signature
signature
- the signature value to be verifiedtrue
if the signature can be successfully verified,
false
otherwisejava.security.SignatureException
- if an error occurs during signature verification