public class ESDHKeyAgreement
extends javax.crypto.KeyAgreementSpi
iaik.security.dh.DHKeyAgreement to provide the
functionality of the ephemeral static Diffie Hellman key agreement algorithm for
generating shared secret key encryption keys as specified by
RFC 2631.
RFC 2631 gives a special variant of the Diffie Hellman algorithm, based on the ANSI X9.42 draft. From the shared secret value ZZ shared keying material -- typically used as key encryption key (KEK) for encrypting (wrapping) a content encryption key (CEK) -- is created by repeatedly calculating the SHA-1 hash of ZZ and additional other information:
KM = H ( ZZ || OtherInfo)where
OtherInfo is specified as:
OtherInfo ::= SEQUENCE {
keyInfo KeySpecificInfo,
partyAInfo [0] OCTET STRING OPTIONAL,
suppPubInfo [2] OCTET STRING }
KeySpecificInfo ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
counter OCTET STRING SIZE (4..4) }
KeySpecificInfo specifies the CEK wrapping algorithm with which
this KEK will be used and a counter (32 bit number, represented in network
byte order, initial value is 1 for any ZZ) that is incremented by one every
time the above key generation function is run for a given KEK.
partyAInfo is a random string provided by the sender, especially
required in static-static mode (where the sender has a static key pair with the
public key placed in a certificate).
suppPubInfo id the length of the generated KEK , in bits, represented
as a 32 bit number in network byte order. E.g. for DESede it would be
the byte sequence 00 00 00 C0.
For generating a KEK, the KM above (SHA-1 hash of ZZ || OtherInfo) is calcualted as often as necessary to give the required keying material by concatenating the KM blocks resulting from the several steps. In each step the counter is incremented by 1. For DESede, e.g., which requires 192 bits of keying material, the algorithm must be run twice, once with a counter value of 1 (to generate K1', K2', and the first 32 bits of K3') and once with a counter value of 2 (to generate the last 32 bits of K3). K1',K2' and K3' are then parity adjusted to generate the 3 DES keys K1,K2 and K3. For RC2-128, which requires 128 bits of keying material, the algorithm is run once, with a counter value of 1, and the left-most 128 bits are directly converted to an RC2 key. Similarly, for RC2-40, which requires 40 bits of keying material, the algorithm is run once, with a counter value of 1, and the leftmost 40 bits are used as the key.
Any application wishing to be participated into a Diffie Hellman key agreement
for generating a shared secret key according to RFC 2631 has to instantiate the
javax.crypto.KeyAgreement class (with "ESDH" as name) and initialize
it with its DHPrivateKey for bringing in the required private information.
A DH Hellman private key maybe generated using a proper key pair generator, e.g.:
KeyPairGnerator dh_key_gen = KeyPairGenerator.getInstance("DH");
dh_key_gen.initialize(1024);
KeyPair dh_key_pair = dh_key_gen.generateKeyPair();
DHPrivateKey dh_priv_key = (DHPrivateKey)dh_key_pair.getPrivate();
When initializing the ESDHKeyAgreement, together with the private key a
ESDHKEKParameterSpec has to be
supplied giving the required other information as described above:
// we want TripleDES key wrap
AlgorithmID tripleDesWrap = AlgorithmID.cms_3DES_wrap;
// key length of KEK:
int keyLength = 192;
// generate the OtherInfo
ESDHKEKParameterSpec otherInfo = new ESDHKEKParameterSpec(tripleDesWrap.getAlgorithm(), keyLength);
// the sender has supplied random patryAInfo:
otherInfo.setPartyAInfo(partyAInfo);
// now create an ESDHKeyAgreement object:
KeyAgreement esdh_key_agreement = KeyAgreement.getInstance("ESDH");
esdh_key_agreement.init(dh_priv_key, otherInfo, random);
Each phase of a key agreement is performed by a call to the doPhase
method, supplied with some other entity's public key or some intermediate key
resulting from the last phase. When calling doPhase it has to be
specified, whether to perform already the last phase of the key agreement or not
by setting the lastPhase parameter to true or
false:
esdh_key_agreement.doPhase(dhPubKey_from_other_entity, true);Actually generating the shared secret is done by calling the
generateSecret method:
byte[] shared_secret = esdh_key_agreemant.generateSecret();
Please note that calling generateSecret on a ESDHKeyAgreement
does NOT return the shared secret value (ZZ, see above), rather already the
key material generated from the shared secret value ZZ is returned. If you
want to get the ZZ value only, you may use an "ordinary" DHKeyAgreement object by instantiating
KeyAgreement.getInstance("DH").
Please note that the key material retrieved from calling generateSecret
may be different from that contained in the SecretKey retrieved
when calling generateSecret(algorithm). A DESede key, e.g., returned by
generateSecret(algorithm) already is parity adjusted, whereas
the DESede key material returned by generateSecret is not parity
adjusted.
Please note that a ESDHKeyAgreement has to be initialized with
a ESDHKEKParameterSpec (representing
the OtherInfo) to be distinguished from a DHParameterSpec which may be used for initializing a DH KeyPairGenerator or
DHKeyAgreement (see ESDHKEKParameterSpec
for more information on this issue).
This class SHOULD NOT be used directly; it should only be used through the JCA/JCE.
DHKeyAgreement,
ESDHKEKParameterSpec,
ESDHKEKParameters| Constructor and Description |
|---|
ESDHKeyAgreement()
The constructor; creates a new instance of the ESDH key agreement
algorithm.
|
| Modifier and Type | Method and Description |
|---|---|
protected java.security.Key |
engineDoPhase(java.security.Key key,
boolean lastPhase)
Executes the next phase of this key agreement with the given key that was
received from one of the other parties involved in this key agreement.
|
protected byte[] |
engineGenerateSecret()
Generates the shared secret and returns it in a new buffer.
|
protected int |
engineGenerateSecret(byte[] sharedSecret,
int offset)
Generates the shared secret, and places it into the buffer
sharedSecret, beginning at offset inclusive. |
protected javax.crypto.SecretKey |
engineGenerateSecret(java.lang.String algorithm)
Creates the shared secret and returns it as a secret key object of the
requested algorithm type.
|
protected void |
engineInit(java.security.Key key,
java.security.spec.AlgorithmParameterSpec params,
java.security.SecureRandom random)
Initializes this key agreement with the given key, set of algorithm
parameters, and source of randomness.
|
protected void |
engineInit(java.security.Key key,
java.security.SecureRandom random)
Initializes this key agreement with the given key and source of
randomness.
|
public ESDHKeyAgreement()
Applications should never use this constructor, instead the key agreement
algorithm should be requested from the appropriate JCA/JCE cryptographic
service provider as follows:
KeyAgreement.getInstance("ESDH", "IAIK").
protected void engineInit(java.security.Key key,
java.security.spec.AlgorithmParameterSpec params,
java.security.SecureRandom random)
throws java.security.InvalidKeyException
engineInit in class javax.crypto.KeyAgreementSpikey - [FIPS 140-2 data input] [FIPS 140-2 CSP] the party's private
information. For example, in the case of the Diffie-Hellman
key agreement, this would be the party's own Diffie-Hellman
private key.params - [FIPS 140-2 data input] the key agreement parametersrandom - [FIPS 140-2 control input] the source of randomnessjava.security.InvalidKeyException - [FIPS 140-2 status output] if the given key is
inappropriate for this key agreement, e.g., is of the
wrong type or has an incompatible algorithm type.java.security.InvalidAlgorithmParameterException - [FIPS 140-2 status output] if the given parameters are
inappropriate for this key agreement.Fips140ErrorStateException - [FIPS 140-2 status output] thrown if the Toolkit is not
allowed to perform cryptographic operationsprotected void engineInit(java.security.Key key,
java.security.SecureRandom random)
throws java.security.InvalidKeyException
If the key agreement algorithm requires random bytes, it gets them from
the given source of randomness, random. However, if the
underlying algorithm implementation does not require any random bytes,
random is ignored.
engineInit in class javax.crypto.KeyAgreementSpikey - [FIPS 140-2 data input] [FIPS 140-2 CSP] the party's private
information. For example, in the case of the Diffie-Hellman
key agreement, this would be the party's own Diffie-Hellman
private key.random - [FIPS 140-2 control input] the source of randomnessjava.security.InvalidKeyException - [FIPS 140-2 status output] if the given key is
inappropriate for this key agreement, e.g., is of the
wrong type or has an incompatible algorithm type.Fips140ErrorStateException - [FIPS 140-2 status output] thrown if the Toolkit is not
allowed to perform cryptographic operationsprotected java.security.Key engineDoPhase(java.security.Key key,
boolean lastPhase)
throws java.security.InvalidKeyException,
java.lang.IllegalStateException
engineDoPhase in class javax.crypto.KeyAgreementSpikey - [FIPS 140-2 data input] [FIPS 140-2 CSP] the key for this
phase. For example, in the case of Diffie-Hellman between 2
parties, this would be the other party's Diffie-Hellman public
key.lastPhase - [FIPS 140-2 control input] flag which indicates whether or not
this is the last phase of this key agreement.java.security.InvalidKeyException - [FIPS 140-2 status output] if the given key is
inappropriate for this phase.java.lang.IllegalStateException - [FIPS 140-2 status output] if this key agreement has not
been initialized.Fips140ErrorStateException - [FIPS 140-2 status output] thrown if the Toolkit is not
allowed to perform cryptographic operationsprotected javax.crypto.SecretKey engineGenerateSecret(java.lang.String algorithm)
throws java.lang.IllegalStateException,
java.security.NoSuchAlgorithmException,
java.security.InvalidKeyException
This method resets this KeyAgreementSpi object, so that it
can be reused for further key agreements. Unless this key agreement is
reinitialized with one of the engineInit methods, the same
private information and algorithm parameters will be used for subsequent
key agreements.
engineGenerateSecret in class javax.crypto.KeyAgreementSpialgorithm - [FIPS 140-2 control input] the requested secret key algorithmjava.lang.IllegalStateException - [FIPS 140-2 status output] if this key agreement has not
been completed yetjava.security.NoSuchAlgorithmException - [FIPS 140-2 status output] if the requested secret key
algorithm is not availablejava.security.InvalidKeyException - [FIPS 140-2 status output] if the shared secret key
material cannot be used to generate a secret key of the
requested algorithm type (e.g., the key material is too
short)Fips140ErrorStateException - [FIPS 140-2 status output] thrown if the Toolkit is not
allowed to perform cryptographic operationsprotected int engineGenerateSecret(byte[] sharedSecret,
int offset)
throws java.lang.IllegalStateException,
javax.crypto.ShortBufferException
sharedSecret, beginning at offset inclusive.
If the sharedSecret buffer is too small to hold the result,
a ShortBufferException is thrown. In this case, this call
should be repeated with a larger output buffer.
This method resets this KeyAgreementSpi object, so that it
can be reused for further key agreements. Unless this key agreement is
reinitialized with one of the engineInit methods, the same
private information and algorithm parameters will be used for subsequent
key agreements.
engineGenerateSecret in class javax.crypto.KeyAgreementSpisharedSecret - [FIPS 140-2 data output] [FIPS 140-2 CSP] the buffer for the
shared secretoffset - [FIPS 140-2 data input] the offset in
sharedSecret where the shared secret will be
storedsharedSecretjava.lang.IllegalStateException - [FIPS 140-2 status output] if this key agreement has not
been completed yetjavax.crypto.ShortBufferException - [FIPS 140-2 status output] if the given output buffer is
too small to hold the secretFips140ErrorStateException - [FIPS 140-2 status output] thrown if the Toolkit is not
allowed to perform cryptographic operationsprotected byte[] engineGenerateSecret()
throws java.lang.IllegalStateException
This method resets this KeyAgreementSpi object, so that it
can be reused for further key agreements. Unless this key agreement is
reinitialized with one of the engineInit methods, the same
private information and algorithm parameters will be used for subsequent
key agreements.
engineGenerateSecret in class javax.crypto.KeyAgreementSpijava.lang.IllegalStateException - [FIPS 140-2 status output] if this key agreement has not
been completed yetFips140ErrorStateException - [FIPS 140-2 status output] thrown if the Toolkit is not
allowed to perform cryptographic operations