Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 736
Riley Willow Avatar asked Nov 21 '14 10:11

Riley Willow


3 Answers

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.

like image 112
Duncan Jones Avatar answered Sep 28 '22 09:09

Duncan Jones


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.

like image 41
Marko Živanović Avatar answered Sep 28 '22 10:09

Marko Živanović


SecretKey is an interface and SecretKeySpec is an implementation of SecretKey

like image 6
Buhake Sindi Avatar answered Sep 28 '22 09:09

Buhake Sindi