Key 和 KeySpec 有什么区别?

What's the difference between a Key and a KeySpec?

在 Java 加密库中,密钥有两种不同的表示形式 - Key and KeySpec. The docs imply there's a difference between the two - a KeySpec is 'transparent' (whatever that means), but has no methods, whereas Key has got a getEncoded method. You're meant to use a KeyFactory 可以在两者之间进行转换(它确实有一个 getKeySpec 方法可以进行转换) .

但是,SecretKeySpec 同时实现了 KeyKeySpec!但是也有一个 SecretKeyFactory class,它不会继承 KeyFactory

这一切让我彻底糊涂了。 KeyKeySpec 有什么区别,SecretKeySpecSecretKeyFactory 是怎么来的?

密钥对象和密钥规范(KeySpecs)是密钥数据的两种不同表现形式。

密码使用密钥对象来初始化其加密算法,但密钥可能需要转换为更便携的格式才能传输或存储。

键的透明表示意味着您可以通过相应规范 class.

中定义的一种获取方法单独访问每个键 material 值
For example, DSAPrivateKeySpec defines getX, getP, getQ, and getG methods, to access the private key x, and the DSA algorithm parameters used to calculate the key(the prime p, the sub-prime q, and the base g). 

如果密钥存储在硬件设备上,其规范可能包含有助于识别密钥的信息 device.This 表示与 Key 接口定义的不透明表示形成对比,您可以在其中无法直接访问关键 material 字段。换句话说,"opaque" 表示只允许您对密钥进行有限的访问——只有密钥接口定义的三个方法:getAlgorithm、getFormat 和 getEncoded。

密钥可以指定为特定于算法的方式,也可以指定为独立于算法的编码格式(例如 ASN.1)。

For example, a DSA private key may be specified by its components x, p, q, and g (eg: DSAPrivateKeySpec), or it may be specified using its DER encoding (eg: PKCS8EncodedKeySpec).

KeyFactory 和 SecretKeyFactory classes 可用于在不透明和透明密钥表示之间进行转换,即在 Keys 和 KeySpecs 之间进行转换。

参考资料和更多详细信息,请访问: https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#KeySpecs

这里的透明意味着所有 classes/interfaces implementing/extending KeySpec 接口都应该以提供者独立的方式显示关于密钥的元数据。此元数据实际上从未用于密钥的常见用途(加密等),但仅在需要查看密钥的数学属性时才使用。了解有关密钥的此类提供者独立数据可能很有用,例如,如果您想生成密钥 from/to 字节流,如果密钥驻留在 HSM 上则挂钩该密钥,或者甚至查明密钥是否弱:

DESKeySpec.isWeak(byte[] key, int offset)

您想要公开关于您的密钥的任何元数据由您决定。 KeySpec只是作为一个标记界面(marker interface design pattern)。

与使用 KeySpec 进行的这种可能的自省相反,使用 SecretKeyFactory 生成的密钥是 "opaque",因为您无法获得 full 数学(模数、指数、编码等)和其他(如果像上面的 DESKeySpec 那样提供)关于密钥的元数据。

另一方面,

SecretKeySpec 是 JCE 开箱即用的解决方案,用于从字节流生成密钥,因此它同时实现了 KeyKeySpec- 来生成密钥KeySpec 提供,并使用 Key.getEncoded() 使密钥可用。