Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / Security / December 2003

Tip: Looking for answers? Try searching our database.

IBM JCE supports HMAC-MD5?

Thread view: 
Gregory Harman - 26 Nov 2003 19:00 GMT
I need to create a secret key using the HMAC-MD5 algorithm and the IBM
JCE, then be able to export/import that key.

So first I create a key with the following method:

private static final String HMAC_MD5_ALGORITHM_NAME = "HmacMD5";
private Key mKey = null;

public void generateKey() throws KeySupportException {
KeyGenerator keyGen = null;
 try {
  try {
   keyGen =
    KeyGenerator.getInstance(
        HMAC_MD5_ALGORITHM_NAME,
        mPreferredProvider);
   } catch (NoSuchProviderException e) {
    keyGen = KeyGenerator.getInstance(HMAC_MD5_ALGORITHM_NAME);
   }
  } catch (Exception e) {
   throw new KeySupportException(e);
  }
 mKey = keyGen.generateKey();
}

So far, so good. Now I export the key:

String outkey = super.encodeBase64(mKey.getEncoded());

Where super.encodeBase64() functions as described (I'll leave the code
out for berevity) mKey is the same mKey from above.

Again, so far so good - I get a nice encrypted hash in my outkey
variable.

Now, the problem - time to try to come back in a different runtime and
import that key using the following method:

public void importKey(String pEncodedKey) throws KeySupportException {
byte[] keyBytes = null;
try {
 keyBytes = super.decodeBase64(pEncodedKey);
} catch (java.io.IOException e) {
 throw new KeySupportException("Error decoding the key string from
base 64",e);
}

try {
 DESKeySpec secretKeySpec = new DESKeySpec(keyBytes);
 SecretKeyFactory secretFactory = SecretKeyFactory.getInstance(
                    HMAC_MD5_ALGORITHM_NAME,
                    mPreferredProvider);
            mKey = secretFactory.generateSecret(secretKeySpec);
} catch (Exception e) {
 throw new KeySupportException("Error constructing the HMAC-MD5 Key:
used " + pEncodedKey,e);
}
}

Ignoring the fact that I'm using a DESKeySpec object (This part
actually confuses me - there is no HmacMD5Spec class specified, but
it's still supposedly supported?), running this throws the following
exception:

java.security.NoSuchAlgorithmException: No such algorithm: HmacMD5
       at javax.crypto.a.a(Unknown Source)
       at javax.crypto.a.a(Unknown Source)
       at javax.crypto.SecretKeyFactory.getInstance(Unknown Source)
       at HMAC_MD5KeySupport.importKey()

I just used that algorithm above to generate the key, but now it can't
find it? What am I missing here?

thanks,
Greg
JK - 27 Nov 2003 09:55 GMT
Gregory,

I don't quite get what you are trying to do.

With your first code snipped you create a key you can *use* to generate
an MD5-HMAC. This usually is just a an 128 bit random value. So it is
not a key *generated with* the HMAC algorithm but one *to be used for
the calculation* of an HMAC.

OTOH, you are right, there is no such thing in Sun's JCE as a
HMACSecretKeySpec, neither a SecretKeyFactory for HMAC keys. I don't
know exactly why, but it infers quite annoying asymetry to the code.

You can simply make a SecretKey out of your bytes using

  SecretKey mKey = new SecretKeySpec(keyBytes, HMAC_MD5_ALG_NAME);

You don't need a SecretKeyFactory here because SecretKeySpec implements
the SecretKey interface. You can also set any algorithm name you like.

What is the deal in using SecretKeyFactories anyway? The only thing that
comes to my mind is to avoid something like "weak keys", which exist for
DES. When someone sends you raw bytes representing a DES key, you use
the DES key factory which should throw an exception if it is a weak key
and return a SecretKey otherwise. AFAIK, there are no weak keys for
HMACs, so they dropped the HMACKeyFactory and the HMACKeySpec.

In your case, using DESKeySpec keys is also wrong, because des keys are
56 bits, while HMAC-MD5 keys are 128 bits.

Hope this answers your question
JK.

> I need to create a secret key using the HMAC-MD5 algorithm and the IBM
> JCE, then be able to export/import that key.
[quoted text clipped - 71 lines]
> thanks,
> Greg
nobody - 30 Nov 2003 11:07 GMT
> OTOH, you are right, there is no such thing in Sun's JCE as a
> HMACSecretKeySpec, neither a SecretKeyFactory for HMAC keys. I don't
[quoted text clipped - 6 lines]
> You don't need a SecretKeyFactory here because SecretKeySpec implements
> the SecretKey interface. You can also set any algorithm name you like.

Some implementations require the algorithm name to match an implemented
scheme ("DES", etc.).  Which (as you stated) is somewhat annoying
because there is no "HMAC" key type, so anything that is selected ends
up being kludgy.

> In your case, using DESKeySpec keys is also wrong, because des keys are
> 56 bits, while HMAC-MD5 keys are 128 bits.

HMAC keys can actually be arbitrary length (really up to the block size
of the hash function, which is 64 bytes for MD5).  *Optimal* key length
is the length of the hash function output (128 bits for MD5).  If the
key material happens to be longer than the hash function block size, the
hash function is first applied to the key material and the resulting
digest is used as the key for the MAC.

Incidentally, HMAC is fairly trivial to implement using just the
MessageDigest primitive; here is HMAC-MD5:

private static byte[] HmacMD5(byte[] key, byte[] data)
        throws Exception {
    if (key.length > 64) {
        key = MessageDigest.getInstance("MD5").digest(key);
    }
    byte[] ipad = new byte[64];
    byte[] opad = new byte[64];
    for (int i = 0; i < 64; i++) {
        ipad[i] = (byte) 0x36;
        opad[i] = (byte) 0x5c;
    }
    for (int i = key.length - 1; i >= 0; i--) {
        ipad[i] ^= key[i];
        opad[i] ^= key[i];
    }
    byte[] tmp = new byte[data.length + 64];
    System.arraycopy(ipad, 0, tmp, 0, 64);
    System.arraycopy(data, 0, tmp, 64, data.length);
    data = MessageDigest.getInstance("MD5").digest(tmp);
    tmp = new byte[data.length + 64];
    System.arraycopy(opad, 0, tmp, 0, 64);
    System.arraycopy(data, 0, tmp, 64, data.length);
    return MessageDigest.getInstance("MD5").digest(tmp);
}
JK - 01 Dec 2003 08:53 GMT
Right, I mixed something up.
JK

... snipped...

> HMAC keys can actually be arbitrary length (really up to the block size
> of the hash function, which is 64 bytes for MD5).  *Optimal* key length
> is the length of the hash function output (128 bits for MD5).  If the
> key material happens to be longer than the hash function block size, the
> hash function is first applied to the key material and the resulting
> digest is used as the key for the MAC.

... snipped...


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.