Почему 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 в качестве ярлыка.