为啥从 Java 中的密码派生密钥时需要 SecretKeySpec?
Posted
技术标签:
【中文标题】为啥从 Java 中的密码派生密钥时需要 SecretKeySpec?【英文标题】:Why is a SecretKeySpec needed when deriving a key from a password in Java?为什么从 Java 中的密码派生密钥时需要 SecretKeySpec? 【发布时间】:2015-01-19 11:51:42 【问题描述】:Java 中 SecretKey
与 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");
这是对getEncoded()
的两次调用的输出:
00367171843C185C043DDFB90AA97677F11D02B629DEAFC04F935419D832E697
【问题讨论】:
【参考方案1】:SecretKey 只是一个需要提供者特定实现的接口。 SecretKeySpec 是一个具体的类,它允许从现有的密钥材料轻松构造 SecretKey。因此,为了获取 SecretKey,您需要使用适当的工厂类或 SecretKeySpec 作为快捷方式。
【讨论】:
【参考方案2】:每个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
,因为我认为您不需要关心之后的具体实现。
【讨论】:
"每个 SecretKey 都有一个关联的算法名称。" ,那不会降低加密的安全性吗?键不应该独立于算法吗? ,例如,如果有人得到了密钥,他们就不能识别用于加密的算法吗? 强密码学的工作基础是每个人都知道一切,除了你的密钥的值。一旦有人拿到了你的密钥,弄清楚你是如何加密数据的就是一件小事。所以不,你的算法不需要保密。【参考方案3】:SecretKey
是一个接口,SecretKeySpec
是SecretKey
的实现
【讨论】:
以上是关于为啥从 Java 中的密码派生密钥时需要 SecretKeySpec?的主要内容,如果未能解决你的问题,请参考以下文章