Date: Tue, 10 Mar 1998 14:54:19 -0800 (PST)
From: Jan Luehe <Jan.Luehe@Eng>
Subject: Re: Fw: My opinions on Key, KeySpec, KeyFactory, KeyGenerator, et. al.
To: java-security@javasoft.com, gchung@openhorizon.com
George:
In the Java Crypto Architecture (JCA), keys are generated and passed
around as opaque Key objects, of which only generic properties
can be retrieved, such as the key's algorithm, type, and possibly
its encoding (see the methods defined in the java.security.Key
interface). In some cases, the Key object may also implement some
specialized key interfaces, such as the interfaces for DSA public
and private keys.
In order to retrieve a specification of the key's underlying key
material in a suitable format, you use a key factory, which is
provider-based.
Key factories are bi-directional.
You also use a key factory to build a Key object from a key
specification.
Key objects are opaque, because you cannot tell how they are implemented.
The underlying implementation is provider-dependent, and may be
software or hardware based.
If you have a key specification for a DSA public key, consisting of
y, p, q, and g, and you feed the same specification to DSA key factories
from different providers, the resulting PublicKey objects will most
likely have different underlying implementations. If the key specifications
already implemented the "Key" interface, and the concept of a key
factory were removed (as you suggested), you would remove that flexibility,
and providers would no longer be able to supply their own implementations
of keys.
You described a scenario where Key objects returned from a key factory from
one provider ("FOO") are used to initialize a Cipher object from a different
provider ("BAR"), and you were wondering if this usage is supported by the JCA.
The answer is "yes". Key factories have a method "translate", which attempts
to convert a Key object from one provider to the corresponding Key object from
a different provider (the provider of the key factory). This conversion may fail,
in which case an "InvalidKeyException" is thrown.
To avoid this problem, you may always specify the name of a provider when
you request a Cipher and key factory object. To avoid conversion problems,
you would specify the same provider in both cases.
Hope this answers your questions.
Jan
> 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
> X-Priority: 3
> X-MSMail-Priority: Normal
> X-MimeOLE: Produced By Microsoft MimeOLE V4.72.2106.4
>
> 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!).
>
>