Fw: My opinions on Key, KeySpec, KeyFactory, KeyGenerator, et. al.

George Chung (gchung@openhorizon.com)
Mon, 9 Mar 1998 13:43:34 -0800

From: "George Chung" <gchung@openhorizon.com>
To: <java-security@javasoft.com>
Subject: Fw: My opinions on Key, KeySpec, KeyFactory, KeyGenerator, et. al.
Date: Mon, 9 Mar 1998 13:43:34 -0800

Please see very bottom of message...

-----Original Message-----
From: George Chung <gchung@openhorizon.com>
To: java-security@javasoft.com <java-security@javasoft.com>
Cc: George Chung <gchung@openhorizon.com>
Date: Monday, March 09, 1998 1:24 PM
Subject: My opinions on Key, KeySpec, KeyFactory, KeyGenerator, et. al.

>Types of java.security.Key are what are passed into the cipher/signer
>implementations. In the JCE 1.2 documentation for SecretKeyFactory, it
>states:
>
>"Key factories are used to convert _keys_ (opaque cryptographic keys of
type
>Key) into _key specifications_ (transparent representations of the
>underlying key material), and vice versa....
>A provider should document the key specifications supported by its secret
>key factory. For example, the SecretKeyFactory for DES keys supplied by the
>Sun provider supports DESKeySpec as a transparent representation of DES
>keys...
>The following is an example ofhow to use a SecretKeyFactory to convert
>secret key data into a SecretKey object, which can be used for a subsequent
>Cipher operation:
>
>byte[] desKeyData;
>DESKeySpec desKeySpec = new DESKeySpec(desKeyData);
>SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
>SecretKey secretKey = keyFactory.generateSecret(desKeySpec);"
>
>Hypothetically, it seems like a "FOO" provider of SecretKeyFactory could
>arbitrarily store each byte of the key material in a long (or a String
>representation of the key in hex). If this were the case, then if a "FOO"
>instance of SecretKey were passed into a "BAR" instance of a DES Cipher,
>seems like the "BAR" implementation has to do a lot of work do encrypt the
>buffer with "FOO" key. The BAR implementation will have to do something
>like:
>
>
>String format = key.getFormat()
>byte encoded[] = key.getEncoded();
>usableKey = convert(encoded, format); // throws EFormatNotSupported
>// I have to do the above because I know neither the KeySpec nor the
>Provider
>...
>
>If this _is_ the case (Ciphers from provider BAR can use Keys from provider
>FOO), why not just hide the opaque Key's from the outside world? And have
>Cipher.init() just take a KeySpec as a parameter? Cipher.init() could throw
>a InvalidKeySpecification exception. In general, I'm not seeing much value
>in the Key interface methods now that JDK 1.2 and the JCE provide a KeySpec
>class heirarchy.
>
>If this is _not_ the intention (Ciphers from provider BAR can only use Keys
>from provider BAR), then it seems that instances of KeyGenerator and
>KeyFactory should be returned by new factory methods off of Cipher (or
>Signature). Otherwise, someone could wreak havoc by installing a
>java.security.provider implementation at position 1 and only providing a
DES
>KeyGenerator implementation. This suggestion would _better_ the chances of
>preventing an error, but certainly not eliminating it.
>
>Perhaps one way to completely eliminate the possibility of error is to
>completely eliminate the Key interface (as it currently exists) and to have
>Cipher simply deal with KeySpec's. For example:
>
>void Cipher.init(int mode, KeySpec keyspec);
>KeySpec Cipher.generateKey();
>
>There is no need for a KeyFactory...those details are hidden inside the
>Cipher implementation. There's no need for KeyGenerator either. Cipher
>becomes the factory class for new KeySpec's that can be used with all
>providers of Cipher (which are of the same algorithm).
>
>Note, we can accomplish the same thing with minimal disruption by making
>KeySpec extend Key. That way the above would change to:
>
>void Cipher.init(int mode, Key key);
>Key Cipher.generateKey();
>
>But I think we can still get rid of KeyFactory and KeyGenerator.

Another less-attractive alternative is to have Key have a method that
returns the KeySpec. If that were the case, and we wanted the BAR instance
of a DES Cipher to be able to encrypt with a FOO instance of a DES Key, then
the BAR implementor could do something like:

try {
DESKeySpec desKeySpec = (DESKEYSpec)key.getKeySpec();
}
catch (ClassCastException e) {
// do something
}
myImplSpecificDESKey = staticKeyFactory.generateSecret(desKeySpec);

But I still prefer KeySpec to extend Key and to get rid of KeyGenerator and
KeyFactory (provided my understanding is correct!).