Почему SecretKeySpec необходим при получении ключа из пароля в Java?

в чем разница между SecretKey vs SecretKeySpec классы в Java?

документация SecretKeySpec говорит:

его можно использовать для создания секретного ключа из массива байтов

в этом коде, если я распечатаю secretKey.getEncoded() или secret.getEncoded(), в hex затем оба дают один и тот же выход. Так зачем нам 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 ответов


SecretKey связано имя алгоритма. Вы не можете использовать SecretKey алгоритм "DES" в контексте, где необходим ключ AES, например.

в вашем коде следующая строка создает SecretKey:

SecretKey secretKey = factory.generateSecret(spec);

однако в этот момент ключ не ключ AES. Если бы вы позвонили secretKey.getAlgorithm(), результат "PBKDF2WithHmacSHA1". Вам нужно каким-то образом сказать Java, что это на самом деле ключ AES.

самый простой способ сделать это, чтобы построить новый SecretKeySpec объект, используя исходные данные ключа и явно указывая имя алгоритма:

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

примечание: Я бы лично объявить secret как SecretKey, так как я не думаю, что вы должны заботиться о конкретной реализации после этого.


SecretKey - это просто интерфейс, который требует реализации конкретного поставщика. SecretKeySpec конкретный тип который позволяет для легкой конструкции SecretKey от существующего ключевого материала. Итак, чтобы получить SecretKey, вам нужно использовать либо соответствующий заводской класс, либо SecretKeySpec в качестве ярлыка.


SecretKey является интерфейсом и SecretKeySpec реализация SecretKey