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
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.