Why is a SecretKeySpec needed when deriving a key from a password in Java?

49.1k views Asked by At

What is difference between SecretKey vs SecretKeySpec classes in Java?

The documentation of SecretKeySpec says:

it can be used to construct a SecretKey from a byte array

In this code, if I print secretKey.getEncoded() or secret.getEncoded(), in hex then both give the same output. So why do we need the SecretKeySpec?

final String password = "test";
int pswdIterations = 65536  ;
int keySize = 256;
byte[] ivBytes;
byte[] saltBytes = {0,1,2,3,4,5,6};

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

PBEKeySpec spec = new PBEKeySpec(
                    password.toCharArray(), 
                    saltBytes, 
                    pswdIterations, 
                    keySize
                    );

SecretKey secretKey = factory.generateSecret(spec);

SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(),"AES");

Here is the output of both calls to getEncoded():

00367171843C185C043DDFB90AA97677F11D02B629DEAFC04F935419D832E697

3

There are 3 answers

2
Duncan Jones On BEST ANSWER

Every SecretKey has an associated algorithm name. You cannot use a SecretKey with algorithm "DES" in a context where an AES key is needed, for example.

In your code, the following line produces a SecretKey:

SecretKey secretKey = factory.generateSecret(spec);

However, at this point the key is not an AES key. If you were to call secretKey.getAlgorithm(), the result is "PBKDF2WithHmacSHA1". You need some way of telling Java that this is actually an AES key.

The easiest way to do this is to construct a new SecretKeySpec object, using the original key data and explicitly specifying the algorithm name:

SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(),"AES");

Note: I would personally declare secret as a SecretKey, since I don't think you'll need to care about the concrete implementation after this.

0
Marko Živanović On

SecretKey is just an interface that requires provider-specific implementation. SecretKeySpec is a concrete class that allows for easy construction of SecretKey from existing key material. So, in order to get SecretKey, you need to use either appropriate factory class or SecretKeySpec, as a shortcut.

0
Buhake Sindi On

SecretKey is an interface and SecretKeySpec is an implementation of SecretKey