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

Ril*_*low 12 java cryptography jce secret-key

Java中的SecretKeyvs SecretKeySpec类之间有什么区别?

文件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");
Run Code Online (Sandbox Code Playgroud)

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

00367171843C185C043DDFB90AA97677F11D02B629DEAFC04F935419D832E697

Dun*_*nes 16

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

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

SecretKey secretKey = factory.generateSecret(spec);
Run Code Online (Sandbox Code Playgroud)

但是,此时密钥不是 AES密钥.如果你打电话secretKey.getAlgorithm(),结果是"PBKDF2WithHmacSHA1".您需要某种方式告诉Java这实际上是一个AES密钥.

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

SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(),"AES");
Run Code Online (Sandbox Code Playgroud)

注:我会亲自宣布secretSecretKey,因为我不认为你需要关心在这之后的具体落实.

  • 强大的加密工作的基础是每个人都知道一切,*除了*你的密钥的价值.一旦有人拥有您的密钥,弄清楚您如何加密数据是一项微不足道的任务.所以不,你的算法不需要保密. (11认同)

Mar*_*vić 8

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


Buh*_*ndi 5

SecretKey是一个接口,SecretKeySpec是一个实现SecretKey