为什么在Java中从密码派生密钥时需要SecretKeySpec?

时间:2014-11-21 10:51:28

标签: java cryptography jce secret-key

Java中SecretKeySecretKeySpec类的区别是什么?

SecretKeySpec的文档说:

  

它可以用于从字节数组

构造一个SecretKey

在此代码中,如果我以十六进制打印secretKey.getEncoded()secret.getEncoded(),则两者都会提供相同的输出。那么为什么我们需要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");

以下是对getEncoded()的两次调用的输出:

00367171843C185C043DDFB90AA97677F11D02B629DEAFC04F935419D832E697

3 个答案:

答案 0 :(得分:16)

每个SecretKey都有一个关联的算法名称。例如,您无法在需要AES密钥的上下文中使用SecretKey算法"DES"

在您的代码中,以下行生成SecretKey

SecretKey secretKey = factory.generateSecret(spec);

但是,此时密钥是AES密钥。如果您致电secretKey.getAlgorithm(),则结果为"PBKDF2WithHmacSHA1"。您需要一些方法告诉Java这实际上是一个AES密钥。

最简单的方法是使用原始密钥数据构造一个新的SecretKeySpec对象,并明确指定算法名称:

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

注意:我个人会将secret声明为SecretKey,因为在此之后我不认为您需要关注具体实施。

答案 1 :(得分:8)

SecretKey只是一个需要特定于提供程序的实现的接口。 SecretKeySpec是一个具体的类,允许从现有的密钥材料中轻松构造SecretKey。因此,为了获得SecretKey,您需要使用适当的工厂类或SecretKeySpec作为快捷方式。

答案 2 :(得分:3)

SecretKey是一个界面,SecretKeySpecSecretKey的实现